2010-04-01 15 views
3

J'ai suivi un excellent article de Rudy Velthuis sur l'utilisation de classes C++ dans les DLL. Tout était en or, sauf que j'ai besoin d'accéder à certaines classes qui n'ont pas d'usines correspondantes dans la DLL C++. Comment puis-je construire une instance d'une classe dans la DLL? Les classes en question sont définies commeCréer une instance d'une classe C++ exportée à partir de Delphi

class __declspec(dllexport) exampleClass 
{ 
public: 
    void foo(); 
}; 

Maintenant sans usine, je n'ai aucun moyen clair d'instancier la classe, mais je sais que cela peut être fait, comme je l'ai vu des scripts SWIG (fichiers .i) qui rendent ces classes disponibles pour Python. Si Python & SWIG peut le faire, alors je suppose/j'espère qu'il y a un moyen de le faire se produire dans Delphi aussi.

Maintenant, je ne sais pas grand chose sur SWIG, mais il semble qu'il génère une sorte de carte pour les noms C++ brouillés? Est-ce que c'est proche? En regardant les exportations de la DLL, je suppose que je pouvais accéder aux fonctions & constructor/destructor par index ou le nom mutilé directement, mais ce serait méchant; et cela fonctionnerait-il même? Même si je peux appeler le constructeur, comment puis-je faire l'équivalent de "new CClass();" à Delphi?

+0

Juste pour clarifier, j'utilise la solution des classes virtuelles pures (classes abstraites pures en Delphi). – Atorian

Répondre

5

La bonne façon de le faire est d'écrire une DLL qui expose une enveloppe usine pour la classe dont vous avez besoin.

Je ne suis pas sûr que SWW fonctionne, mais tout ce qui repose sur l'ingénierie inverse du nom mangling semble une approche douteuse. En outre, un objet C++ doit être créé uniquement en code C++, en plus d'un objet C + +. Vous devez laisser la sémantique de création d'objet à l'environnement d'exécution C++.

Il existe une raison pour laquelle COM existe.Précisément pour faire en sorte que cette métaphore de l'objet de langue croisée fonctionne proprement.

J'ai partitions écrites des objets COM qui sont appelés à partir de Delphi, Python et C#

+0

Ah un wrapper DLL en C++. Merci, cela va certainement aider. Je m'attendais à ce qu'une solution utilisable soit beaucoup plus complexe. – Atorian

2

Si python peut, cela ne signifie pas nécessairement que n'importe quelle langue peut.

Python (ou tout autre langage de script) peut être capable d'accéder au code C++ exactement dans le même compilateur et la même version que celle avec laquelle il a été compilé.

Le test décisif est de savoir si le code python peut accéder à la classe, quel que soit il est compilé avec (par exemple, une implémentation de Python avec le même DLL généré avec msvc et gcc)

En général, tout avec des noms déchiquetés est compilateur et -version spécifique. Le seul moyen est de compiler un programme de test avec le compilateur que vous ciblez, de le désassembler, de trouver les appels d'exécution correspondants (pour le type de classe, le constructeur et les assistants d'exécution) et de les imiter avec les fonctions cdecl ou asm en Delphi. Les gens comme Rudy peuvent nettoyer cela en utilisant la fonctionnalité pascal autant que possible et la présenter comme quelque chose qui semble facile, mais la compatibilité croisée des HLLs est un sujet difficile (sinon impossible).

5

Il est possible de le faire en utilisant SWIG. Au moins, cela devrait être possible. J'ai écrit un module SWIG ciblant ObjectPascal et je l'utilise avec succès dans mon propre projet. J'ai transposé GEOS et la bibliothèque GDAL/OGR. J'ai aussi une branche dans le dépôt SWIG, MAIS je dois encore terminer les étapes finales pour construire toutes les suites de tests et pour corriger les typemaps afin d'avoir le module accepté.

Quelqu'un voudrait-il vous aider?

Stefano Moratto [email protected] www.csiat.it

+0

Je voudrais vraiment le voir sur la liste des fonctionnalités SWIG. Serait très utile pour moi et probablement beaucoup d'autres développeurs Delphi. – Atorian

+0

D'accord. Stefano/n'importe qui, si vous avez encore ce code, pourriez-vous poster un lien? Je vais le passer sur le forum Lazarus/FreePascal www.lazarus.freepascal.org car il peut devenir extrêmement utile pour générer des liaisons C++ pour FreePascal – reiniero

+0

Mise à jour: trouvé ceci: https://sourceforge.net/tracker/?func= browse & group_id = 1645 & atid = 301645, c'est peut-être celui que vous vouliez dire? – reiniero

7

La façon dont fonctionne rasade est: 1) Il crée une API plate pour chaque méthode de classe et de construire l'usine classe/destroyer fonction. par exemple:

class C { 
     public : 
      C() {...} 
      int M1(int P1) {...} 
     } 

ce produit:

 C* New_C(); 
     Destroy_C(C*self); 
     int C_M1(C*self,int P1) {} 

l'API plat doit être compilé dans une nouvelle DLL

2) elle produit de l'API plat d'une unité contenant la déclaration api plat en pascal 3) l'api pascal plat peut être utilisé en option pour construire automatiquement une classe Pascal par exemple:

type TC = class 


private 

     FObj : pointer; 
public 

     constructor Create(); 
     destructor Destroy(); override; 
     function m1(p1:integer: integer; 
    ... 

    constructor TC.Create(); 
    begin 
    inherited; 
    FObj := New_C(); 
    end; 

    destructor TC.Destroy(); 
    begin 
     Destroy_C(FObj); 
     inherited; 
    end; 

    function TC.M1(P1:integer) : integer; 
    begin 
     Result := C_M1(FObj, P1); 
end; 
+0

Résumé très utile, merci. C'est exactement ce que je vois dans les fichiers python de SWIG. J'ai remarqué qu'il semble aussi produire un fichier .pyd pour python, que je suppose être la DLL d'interface plate dont vous parlez, bien que ce soit une DLL étrange; taille massive mais n'exporte qu'une seule fonction init_interfacename; les bonnes choses ne sont probablement utilisables que par Python, car les fichiers .py produits appellent des tonnes de méthodes interfacename semi-mutables.xxx qui ne sont certainement pas dans la DLL C++. – Atorian