29 votes

Comment utiliser des classes C ++ avec des ctypes?

Je suis juste de commencer avec ctypes et souhaitez utiliser une classe C++ que j'ai exporté dans un fichier dll à partir de l'intérieur de python à l'aide de ctypes. Donc disons que mon code C++ ressemble à quelque chose comme ceci:

class MyClass {
  public:
    int test();
...

Je sais créer un .dll fichier qui contient cette classe et puis de charger le .dll fichier en python à l'aide de ctypes. Maintenant, comment aurais-je créer un Objet de type Maclasse et appeler sa fonction de test? Si, c'est possible avec ctypes? Sinon je voudrais envisager d'utiliser GORGÉE ou Boost.Python, mais ctypes semble être l'option la plus facile pour les petits projets.

Toute aide est appréciée,

Jörg

25voto

Mark Rushakoff Points 97350

La petite histoire c'est qu'il n'y a pas de binaire standard d'interface pour le C++ dans la façon dont il est pour C. Différents compilateurs de sortie binaires différents pour le même C++ bibliothèques dynamiques, en raison de nom et d'amputation des différentes façons de gérer la pile entre la bibliothèque des appels de fonction.

Donc, malheureusement, il n'est pas vraiment un portable moyen d'accéder à des bibliothèques C++ en général. Mais, pour un compilateur à un moment, ça ne pose aucun problème.

Ce blog a aussi un bref aperçu de pourquoi cela ne fonctionne pas. Peut-être qu'après C++0x sort, nous allons avoir un standard de l'ABI C++? Jusqu'alors, vous êtes probablement ne va pas avoir un moyen d'accéder à des classes C++ par Python ctypes.

25voto

AudaAero Points 181

En Plus De Boost.Python(qui est probablement un plus de solution à l'amiable pour les grands projets qui nécessitent one-to-one mapping des classes C++ pour les classes python), vous pourriez fournir sur le C++ côté d'une interface C. C'est une solution de beaucoup de sorte qu'il a ses propres avantages et inconvénients, mais je vais le présenter pour le bénéfice de ceux qui ne sont pas familiers avec la technique. Pour une information complète, avec cette approche, on ne serait pas interfaçage C++, python, mais le C++ à C de Python. Ci-dessous j'ai inclus un exemple qui répond à vos exigences pour vous montrer l'idée générale de la extern "c" installation de compilateurs C++.

//YourFile.cpp (compiled into a .dll or .so file)
#include <new> //For std::nothrow
//Either include a header defining your class, or define it here. 

extern "C"  //Tells the compile to use C-linkage for the next scope.
{
    //Note: The interface this linkage region needs to use C only.  
    void * CreateInstanceOfClass( void )
    {
        // Note: Inside the function body, I can use C++. 
        return new(std::nothrow) MyClass;
    }

    //Thanks Chris. 
    void DeleteInstanceOfClass (void *ptr)
    {
         delete(std::nothrow) ptr; 
    }

    int CallMemberTest(void *ptr)
    {

        // Note: A downside here is the lack of type safety. 
        // You could always internally(in the C++ library) save a reference to all 
        // pointers created of type MyClass and verify it is an element in that
        //structure. 
        //
        // Per comments with Andre, we should avoid throwing exceptions.  
        try
        {
            MyClass * ref = reinterpret_cast<MyClass *>(ptr);
            return ref->Test();
        }
        catch(...)
        {
           return -1; //assuming -1 is an error condition. 
        }
    }

} //End C linkage scope.

Vous pouvez compiler ce code avec

gcc -shared -o test.so test.cpp
#creates test.so in your current working directory.

Dans votre code python que vous pourriez faire quelque chose comme ceci (l'invite interactive de 2,7 indiqué):

>>> from ctypes import cdll
>>> stdc=cdll.LoadLibrary("libc.so.6") # or similar to load c library
>>> stdcpp=cdll.LoadLibrary("libstdc++.so.6") # or similar to load c++ library
>>> myLib=cdll.LoadLibrary("/path/to/test.so")
>>> spam = myLib.CreateInstanceOfClass()
>>> spam
[outputs the pointer address of the element]
>>> value=CallMemberTest(spam)
[does whatever Test does to the spam reference of the object] 

Je suis sûr que Boost.Python fait la même chose sous le capot, mais peut-être la compréhension de la baisse des niveaux de concepts est utile. Je voudrais être plus excité à propos de cette méthode si vous tentiez d'accéder à des fonctionnalités d'une bibliothèque C++ et un one-to-one mapping n'était pas nécessaire.

Pour plus d'informations sur C/C++ interaction consulter cette page à partir du Soleil: http://dsc.sun.com/solaris/articles/mixing.html#cpp_from_c

1voto

ifryed Points 307

Voici une courte explication sur la façon d'utiliser c et c ++ avec C_types en python. Comment écrire une DLL / SO en C ++ pour Python

0voto

mtasic85 Points 1223

J'ai trouvé cela très intéressant: appeler C ++ depuis Haskell - "The Hard Way"

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X