2009-07-20 9 views
1

J'utilise une DLL avec la fonction suivante dans C# Visual Studio 2008:Comment transmettre un paramètre par référence au code managé en C#?

[DllImport("slpapi62", EntryPoint = "[email protected]")] 
public static extern int SlpGetPrinterName(int nIndex, string strPrinterName, int nMaxChars); 

L'appel de cette fonction, strPrinterName est supposé retourner une chaîne.

string name = ""; 
SlpGetPrinterName(0, name, 128); 

Comment puis-je faire passer ce paramètre par référence?

Répondre

2

passer un objet StringBuilder au lieu d'une chaîne:

[DllImport("slpapi62", EntryPoint = "[email protected]")] 
public static extern int SlpGetPrinterName(int nIndex, StringBuilder strPrinterName, int nMaxChars); 

Qualifiant:

StringBuilder name = new StringBuilder(128); 
int value = SlpGetPrinterName(0, name, name.Capacity); 
+0

Cela a fonctionné! Quelqu'un peut-il me dire pourquoi j'ai besoin d'utiliser la classe StringBuilder par rapport à une chaîne normale? –

+1

En fait, une chaîne est un type de référence, mais elle est immuable. Par conséquent, lorsque le marshaleur appelle un code non géré avec une chaîne, il crée une copie de son tampon afin que l'original reste inchangé. Techncially, il devrait le faire de toute façon parce que 1) la chaîne n'est pas épinglée (le GC peut déplacer ses données) et 2) il doit le convertir en ANSI ou tout ce qui est demandé. Fondamentalement, cela signifie que même si la méthode que vous appelez modifie le tampon, les modifications sont simplement rejetées. Le tampon de StringBuilder est mutable, ce qui signifie que si la fonction modifie son tampon, elle est recopiée dans le tampon de StringBuilder. –

+0

Son cas de type Value vs Reference. Bien que la chaîne soit techniquement un type de référence, elle se comporte comme un type de valeur: http://stackoverflow.com/questions/636932/in-c-why-is-string-a-reference-type-that-behaves-like-a- valeur-type – 7wp

0

Pouvez-vous utiliser le mot-clé ref?

string name = ""; 
SlpGetPrinterName(0, ref name, 128); 

Il y a une explication détaillée des variables passant ici par référence http://www.yoda.arachsys.com/csharp/parameters.html

+0

ne semble pas travailler avec le mot-clé ref –

1

Utilisez un objet StringBuilder pour le paramètre de chaîne.

0

Il semble que vous ayez besoin que la valeur du nom soit définie par le code externe. Il a été un certain temps depuis que je l'ai fait tout Pinvoke, mais je crois que ce qui suit est la signature correcte:

[DllImport("slpapi62", EntryPoint = "[email protected]")] 
public static extern int SlpGetPrinterName(int nIndex, out string strPrinterName, int nMaxChars); 

Notez le mot-clé « out » avant « string strPrinterName ». Vous pouvez ensuite appeler comme ceci:

string name; 
SlpGetPrinterName(0, out name, 128); 
Questions connexes