2012-02-17 9 views
3

Fonctionne très bien si je ne renvoie rien, ou si je renvoie un entier. Mais si j'essaie de retourner un PChar, à savoir ..Application Web ASP.NET appelant DLL Delphi sur le serveur Web IIS, se verrouille lors du renvoi de la chaîne PChar

result := PChar('') or result:= PChar('Hello') 

L'application Web gèle et je regarde sa mémoire compte obtenir progressivement plus en plus haut dans le gestionnaire de tâches. La chose étrange est que la DLL fonctionne bien sur le serveur de débogage VStudio, ou via une application C#. La seule chose que je peux penser à cela ferait une différence est que le serveur IIS fonctionne en 64 bits Windows.

Cela ne semble pas être un problème de compatibilité, car je peux écrire avec succès dans des fichiers texte et faire d'autres choses à partir de la DLL ... Je ne peux pas retourner une chaîne PChar. Essayé en utilisant PWideChar, essayé de retourner «quelque chose \ 0», essayé tout ce que je pouvais penser. Pas de chance malheureusement.

[DllImport("TheLib.dll", CallingConvention = CallingConvention.StdCall, CharSet = CharSet.Ansi)] 
private static extern string SomeFunction(); 

string result = SomeFunction(); 

delphi:

library TheLib; 

function SomeFunction() : PChar export; stdcall; 
begin 
return PChar(''); 
end; 

exports 
    SomeFunction 

Répondre

4

Dampsquid's analysis est correct, donc je ne vais pas le répéter. Cependant, je préfère une solution différente que je trouve plus élégante. Ma solution préférée pour un tel problème est d'utiliser Delphi Widestring qui est un BSTR.

Du côté Delphi vous écrire comme ceci:

function SomeFunction: Widestring; stdcall; 
begin 
    Result := 'Hello'; 
end; 

Et du côté C# vous le faites comme ceci:

[DllImport(@"TheLib.dll")] 
[return: MarshalAs(UnmanagedType.BStr)] 
private static extern string SomeFunction(); 

Et voilà. Parce que les deux parties utilisent le même allocateur COM pour l'allocation de mémoire, tout fonctionne simplement.


@NoPyGod signale de manière intéressante que ce code échoue avec une erreur d'exécution. Après avoir examiné cela, je pense que c'est un problème à la fin de Delphes.Par exemple, si nous laissons le code C# tel qu'il est et utiliser ce qui suit, alors les erreurs sont résolues:

function SomeFunction: PChar; stdcall; 
begin 
    Result := SysAllocString(WideString('Hello')); 
end; 

Il semblerait que les valeurs de retour Delphi de type WideString ne sont pas traités comme ils devraient être. Les paramètres Out et Var sont gérés comme prévu. Je ne sais pas pourquoi les valeurs de retour échouent de cette manière.

+0

Je dois attendre jusqu'à lundi pour essayer votre solution sur IIS au travail, mais le raisonnement derrière cela me semble solide. Une chose cependant .. J'ai testé le code à la maison, et je ne peux pas obtenir la valeur de retour au travail, il donne juste une exception 'Tentative de lire ou d'écrire de la mémoire protégée.'. Je suis cependant capable de réaliser ce que je veux faire en utilisant une variable 'out' et en passant le résultat de cette façon. Savez-vous pourquoi je serais incapable de revenir? Je rassemble le résultat comme dans votre code. Est-ce parce que c'est Delphi 2007? Je vais bien utiliser le truc 'out', mais j'aimerais savoir pourquoi c'est nécessaire. – NoPyGod

+0

Je vois Alex a le même problème ici - http://stackoverflow.com/questions/8533505/accessing-delphi-dll-throwing-ocasional-exception – NoPyGod

+0

Voici ma source http://pastebin.com/NfWLdF6V – NoPyGod

-1

essayer d'activer dans le pool d'applications paramètres avancés applications 32 bits:

enter image description here

+0

-1 ceci n'est pas lié à la question à mon avis. –

+0

Je crois que cela est vrai lors de l'utilisation d'un ** COM ** Dll 32 bits. pas lors de l'importation en C#. – kobik

+0

mes excuses O :-) –

3

Vous ne pouvez pas retourner une chaîne comme ça, la chaîne est locale à la fonction et sera libéré dès que la fonction retourne, laissant le PChar retourné pointant vers un emplacement invalide. Vous devez passer un pointeur à remplir dans la DLL, créer dynamiquement la chaîne et la libérer dans le code C# ou créer un tampon statique dans yout DLL et le renvoyer.

De loin le plus sûr moyen est de passer un pointeur dans la fonction c.-à-

function SomeFunction(Buffer: PChar; MaxLength: PInteger): wordbool; stdcall; 
{ 
    // fill in the buffer and set MaxLength to length of data 
} 

vous devez définir MaxLength au Sixe du tampon avant d'appeler votre dll afin que le dll peut vérifier qu'il ya suffisamment d'espace pour les données à retourner.

+0

À quoi le code ressemblerait-il du côté C#? Parce qu'il semble la même chose ici en excluant le paramètre maxlength. Et pourquoi le code fonctionne-t-il en dehors de iis? Merci – NoPyGod

+0

Je suppose que vous faites une faute de frappe, devrait Pchar être un nom de variable. Réjouissez-vous d'essayer ceci quand j'arrive à un ordinateur. – NoPyGod

+0

Vous pourriez retourner un BSTR et laisser le marshaller gérer les choses. Ce serait mon option préférée. –

Questions connexes