2010-11-03 20 views
2

Je souhaite appeler une ou plusieurs fonctions d'une bibliothèque native, mais je ne suis pas sûr des mappages de type. La fonction en particulier, je suis en train est actuellement comme suit, voici la petite application de la console que je suis dans Smasher:Comment invoquer cette méthode native à partir de C#

extern char *tgetstr (const char *name, char **area); 

Et voici ma tentative de cartographie cette option pour utiliser dans une console .NET. Je reçois une erreur en essayant de lire ou d'écrire de la mémoire protégée.

class Program 
{ 
    [DllImport("termcap.dll")] 
    public static extern IntPtr tgetstr(IntPtr name, IntPtr area); 

    static void Main(string[] args) 
    { 
     IntPtr ptr1 = new IntPtr(); 
     IntPtr a = tgetstr(Marshal.StringToCoTaskMemAnsi("cl"), ptr1); 
     Console.WriteLine(Marshal.PtrToStringBSTR(a)); 
    } 
} 

TIA

Andrew

Répondre

2

Vous devez passer votre IntPtr par ref, de sorte que la fonction peut écraser. Ensuite, vous devez également libérer la chaîne après l'avoir copiée, en espérant que la DLL fournisse une fonction de désallocation correspondante. StringToCoTaskMemAnsi ne vous aide pas non plus, c'est juste une fuite de mémoire.

La déclaration p/Invoke correcte est probablement

[DllImport("termcap.dll", CharSet = CharSet.Ansi)] 
public static extern IntPtr tgetstr(string name, ref IntPtr area); 
0

Je n'ai pas travaillé avec le code non géré depuis 3 ans, mais je pense que vous pouvez le faire en marquant les paramètres de la méthode avec l'attribut MarshalAs. Vérifiez cet article,

MSDN

0

Vous devez épingler vos ptr1.

GCHandle handle = GCHandle.Alloc(ptr1, GCHandleType.Pinned);

+0

qui ne touche que l'adresse de 'ptr1' pas la valeur (l'adresse stockée à l'intérieur), donc ne fera aucune différence. De plus, la couche p/invoke le ferait automatiquement. –