2009-11-09 7 views
1

est ici le natif (Delphi 7) Fonction:Comment appeler cette fonction dll native à partir de C#?

function Foo(const PAnsiChar input) : PAnsiChar; stdcall; export; 
var 
    s : string; 
begin 
    s := SomeInternalMethod(input); 
    Result := PAnsiChar(s); 
end; 

Je dois appeler cela de C#, mais le nom de la dll n'est pas connu au moment de la compilation - donc je dois utiliser LoadLibrary pour y accéder.

C'est ce que mon code C# ressemble à ce jour:

[DllImport("kernel32.dll")] 
public extern static IntPtr LoadLibrary(String lpFileName); 

[DllImport("kernel32.dll")] 
public extern static IntPtr GetProcAddress(IntPtr handle, string funcName); 

[UnmanagedFunctionPointer(CallingConvention.StdCall)] 
private delegate string FooFunction(string input); 

... 

IntPtr dllHandle = LoadLibrary(dllName); 
IntPtr fooProcAddr = GetProcAddress(dllHandle, "Foo"); 

FooFunction foo = (FooFunction)Marshal.GetDelegateForFunctionPointer(
    fooProcAddr, typeof(FooFuncion) 
); 

string output = foo(myInputString); 

Maintenant, cela fonctionne en fait - au moins, le code delphi reçoit correctement la chaîne, et le code C# reçoit la chaîne de sortie.

Cependant, je l'ai remarqué quelques étrangetés lors du débogage du code delphi quand il est appelé à partir du code C# - le débogueur saute les lignes quand il ne devrait pas ..

Et je crains que je fuite mémoire - est-ce que quelqu'un nettoie ces PChars?

Quelqu'un peut-il me donner quelques commentaires/conseils sur la façon dont cela devrait être fait?

+2

La seule fois où j'ai vu un débogueur ignorer des lignes alors qu'il ne le devrait pas, c'est quand le code compilé ne correspond pas à la source. Êtes-vous certain que vous êtes lié à la bonne version de l'assemblage? –

Répondre

3

La seule chose raisonnable que vous pouvez faire est de supprimer cette fonction et de la réécrire. Il n'y a aucun moyen que cela fonctionne. s est une variable de chaîne locale de la fonction Foo(), de sorte que la mémoire occupée par la chaîne sera libérée lorsque vous quitterez Foo(). Le pointeur que vous renvoyez pointe vers un emplacement de mémoire non valide qui, par hasard, contient toujours les données de chaîne. Si vous utilisez un gestionnaire de mémoire qui efface la mémoire lorsque les pointeurs y sont libérés, il ne contiendra même plus les données. Si la mémoire est réutilisée elle contiendra autre chose, si le bloc contenant ce morceau de mémoire est libéré vous obtiendrez un AV.

Il existe d'autres questions ici sur StackOverflow comment retourner des données de séquence de caractères à partir d'une DLL. Utilisez un type de chaîne compatible avec la façon dont l'API Windows fait des affaires, une chaîne COM, ou passez un tampon préalloué à votre fonction et remplissez-le avec des données. Dans ce dernier cas, vous pouvez utiliser la même manière que pour chaque fonction API similaire.

+0

Merci, j'étais confus parce que ça fonctionnait vraiment - je pensais que peut-être que le casting PChar faisait quelque chose d'intelligent comme l'allocation de mémoire. – Blorgbeard

+0

Pouvez-vous me diriger vers une ressource sur "la façon dont l'API Windows fait des affaires"? Je ne veux pas avoir à préallouer un tampon, car la longueur de la chaîne retournée variera énormément. – Blorgbeard

+0

OK, j'essaye cette approche: http://stackoverflow.com/questions/1699736/how-can-i-return-a-pchar-from-a-dll-function-to-a-vb6-application- sans risque/1699889 # 1699889 – Blorgbeard

2

Pour la détection de fuite de mémoire, vous pouvez utiliser le code source ouvert FastMM4 memory manager for Delphi.

« FastMM est un gestionnaire de mémoire de remplacement rapide comme l'éclair pour applications Embarcadero Delphi Win32 que les échelles bien dans multi-thread applications, n'est pas sujette à la fragmentation mémoire et supports partagés mémoire sans l'utilisation de fichiers .DLL externes . "

Il est idéal pour la vitesse, la vérification des fuites et le partage de mémoire entre les DLL.

Egalement très utile est le FastMM4 Options Interface qui aide à configurer FastMM4.

+0

Cheers, je vais jeter un coup d'oeil à cela – Blorgbeard