2010-12-12 77 views
1

J'ai une classe abstraite dans un programme C++ qui ressembleCrash lors de C++ appelle programme DLL Delphi fonctionne

class Interface { 
    virtual void blah() = 0; 
    virtual int asdf() = 0; 
}; 

et ce programme C++ vous permet de charger les DLL avec LoadLibrary. Lorsque vous chargez une DLL, elle appelle une fonction dans la DLL appelée Setup avec GetProcAddress, en passant un pointeur sur une sous-classe d'Interface en tant que paramètre.

J'ai un DLL Delphi qui imite la classe et expose la fonction de configuration comme ceci:

type 
Interface = class abstract 
    procedure blah(); virtual; abstract; 
    function asdf() : Integer; virtual; abstract; 
end; 

function Setup(I : Interface) : Integer; export; cdecl; 
begin 
    Result := 0; 
end 

exports Setup; 

Mais lorsque le programme appelle la fonction, il se bloque. Si je change la fonction d'installation à ceci:

function Setup(I : Pointer) : Integer; export; cdecl; 

Il fonctionne très bien et ne tombe pas en panne, mais bien sûr, je ne peux pas le laisser comme ça, je dois être en mesure d'utiliser la classe. Quelqu'un peut-il me dire ce que je fais mal?

+0

Je ne sais pas comment résoudre votre problème car je n'utilise pas (et ne m'inquiète pas?) Beaucoup d'appeler des conventions. Mais j'allais dire qu'il semble que vous êtes sur la bonne voie avec la modification de votre convention d'appel. Vous pourriez vouloir le changer pour votre interface C++. –

+0

Je n'ai pas de contrôle sur le code C++, juste le delphi. –

+0

Vous n'avez absolument aucun contrôle sur le code C++? Vous ne pouvez même pas se plaindre aux développeurs C++ qu'ils ont foiré, et ensuite exiger qu'ils le réparent? Ce n'est pas bon. –

Répondre

1

Si votre code C++ est vraiment tel que vous le dites, vous devez déterminer quelle convention d'appel il utilise. Utilise-t-il définitivement la convention d'appel C? Avec quoi est-il compilé, et quels drapeaux pour appeler la convention?

Votre Interface classe doit inclure aussi la convention d'appel, quelque chose comme:

Interface = class abstract 
    procedure blah(); cdecl; virtual; abstract; 
    function asdf() : Integer; cdecl; virtual; abstract; 
end; 

Si la convention d'appel utilisée par C++ est quelque chose comme fastcall de MSVC, il n'y a pas d'équivalent à Delphes. Ce que vous pourriez faire dans ce cas est d'écrire une DLL proxy dans MSVC qui convertit l'interface de MSVC fastcall en cdecl ou similaire.

+0

Non, la convention d'appel est définitivement cdecl. Juste pour m'assurer que j'ai essayé stdcall aussi, ça plante aussi. –

+0

@john comment pouvez-vous vraiment être certain de cela? Tout simplement parce que les crashs de __stdcall ne sont pas suffisants pour faire cette détermination. Avez-vous accès aux fichiers d'en-tête de la bibliothèque C++ avec laquelle vous essayez d'interagir? Je commencerais par jeter un coup d'œil à et voir comment il est prototypé. La suggestion de Barry d'envelopper l'interface est probablement votre meilleur pari. – greatwolf

+0

Les classes Microsoft C++ * n'utilisent pas * cdecl * comme convention d'appel. Ils utilisent * thiscall *. Cela place le pointeur d'objet dans le registre ECX et les paramètres déclarés sur la pile. Avec * cdecl *, le pointeur sera en haut de la pile, là où Delphi le cherche. Utilisez des conventions d'appel explicitement déclarées sur les * deux * classes. –

2

Je ne connais pas le C++, mais les interfaces Delphi sont automatiquement comptées par référence (via IUnknown). On dirait que votre interface a déjà été détruite au moment où vous essayez de l'utiliser.

Editer: Désolé, j'étais confus: vous n'utilisez pas d'interfaces.

Les classes Delphi et C++ ne sont pas compatibles, donc je ne pense pas que cela fonctionne. Vous devez changer la classe à une interface COM ou un enregistrement de pointeurs de fonction. Si vous n'avez aucun contrôle sur le côté C++, j'ai peur que vous n'ayez pas de chance.