2010-04-02 16 views
5

j'ai une méthode que je veux importer à partir d'une DLL et il a une signature:DllImport et char *

BOOL GetDriveLetter(OUT char* DriveLetter) 

J'ai essayé

[DllImport("mydll.dll")] 
    public static extern bool GetDriveLetter(byte[] DriveLetter); 

et

[DllImport("mydll.dll")] 
    public static extern bool GetDriveLetter(StringBuilder DriveLetter); 

mais aucun n'a renvoyé quoi que ce soit dans la variable DriveLetter.

Répondre

6

Il semble que la fonction GetDriveLetter attend un char* qui pointe sur une quantité de mémoire suffisante pour contenir la lettre de lecteur.

Je pense que la meilleure façon d'aborder ce problème est de passer une IntPtr cru et envelopper les appels à GetDriveLetter dans une API qui prend en charge la gestion des ressources et la conversion à un string.

[return:MarshalAsAttribute(UnmanagedType.Bool)] 
private static extern bool GetDriveLetter(IntPtr ptr); 

public static bool GetDriveLetter(out string drive) { 
    drive = null; 
    var ptr = Marshal.AllocHGlobal(10); 
    try { 
    var ret = GetDriveLetter(ptr); 
    if (ret) { 
     drive = Marshal.PtrToStringAnsi(ptr); 
    } 
    return ret; 
    } finally { 
    Marshal.FreeHGlobal(ptr); 
    } 
} 
+0

Que signifie le UnmanagedType.I1? – Malfist

+0

@Malfist, La valeur I1 indique au CLR de marshaler la valeur sous la forme d'un entier de 1 octet. Il était en fait incorrect dans cet exemple car I4 est la valeur correcte (mise à jour un peu plus tôt). Quant à savoir pourquoi consulter cette entrée de blog, j'ai écrit sur les valeurs de marshalling bool: http://blogs.msdn.com/jaredpar/archive/2008/10/14/pinvoke-and-bool-or-should-i-say-bool .aspx – JaredPar

+0

Quand je le fais I4, je reçois MarshalDirectiveException – Malfist

0

Le StringBuilder est probablement le chemin à parcourir, mais vous devez définir la capacité du constructeur de chaîne avant d'appeler la fonction. Puisque C# n'a aucune idée de la quantité de mémoire utilisée par GetDriveLeter, vous devez vous assurer que StringBuilder dispose de suffisamment d'espace. Le marshaller passera ensuite un char* alloué à cette longueur à la fonction et la ramènera au StringBuilder.

[return:MarshalAsAttribute(UnmanagedType.I4)] 
private static extern bool GetDriveLetter(StringBuilder DriveLetter); 

public static bool GetDriveLetter(out string driverLetter) { 
    StringBuilder buffer = new StringBuilder(10); 
    bool ret = GetDriveLetter(buffer); 
    driveLetter = buffer.ToString(); 
    return ret; 
} 

Voir le p/invoke sample for GetWindowText(), pour un exemple.

+0

Ne renvoie pas la chaîne correcte, contrairement à la réponse acceptée. – Malfist

+0

Que faire si vous ajoutez CharSet = CharSet.Ansi à l'attribut DllImport? C'est si vous vous souciez depuis que vous avez une solution de travail. – shf301

+0

L'ajout de CharSet.Ansi à DllImport ne fait aucune différence. – Malfist

0
[DllImport("mydll.dll")] 
public static extern bool GetDriveLetter([MarshalAs(UnmanagedType.LPStr)] string DriveLetter)