Python: l'accès à la fonction DLL à l'aide ctypes - nom d'accès par la fonction * * échoue

StackOverflow https://stackoverflow.com/questions/1088085

Question

myPythonClient (ci-dessous) souhaite invoquer une fonction de ringBell (chargé à partir d'une DLL en utilisant ctypes). Cependant, la tentative d'accès ringBell via ses nom Résultats dans un AttributeError. Pourquoi?

RingBell.h contient

namespace MyNamespace
    {
    class MyClass
        {
        public:
            static __declspec(dllexport) int ringBell ( void ) ;
        } ;
    }

RingBell.cpp contient

#include <iostream>
#include "RingBell.h"
namespace MyNamespace
    {
    int __cdecl MyClass::ringBell ( void )
        {
        std::cout << "\a" ;
        return 0 ;
        }
    }

myPythonClient.py contient

from ctypes import *
cdll.RingBell[1]() # this invocation works fine
cdll.RingBell.ringBell() # however, this invocation errors out
# AttributeError: function 'ringBell' not found
Était-ce utile?

La solution

Peut-être parce que le nom C ++ est mutilée par le compilateur et non exportée de la DLL comme RingBell. Avez-vous vérifié qu'il apparaît dans les noms exportés exactement comme ça?

Autres conseils

Votre compilateur C ++ est mutiler les noms de tous les objets visibles de l'extérieur pour refléter (ainsi que leurs noms sous-jacents) leurs espaces de noms, les classes et les signatures (c'est comment devient possible surcharge).

Pour éviter ce mutiler, vous avez besoin d'un extern "C" sur les noms visibles de l'extérieur que vous souhaitez être visible à partir du code non-C ++ (et par conséquent ces noms ne peuvent être surchargées, ni en C ++ standard peuvent-ils en ligne, dans les espaces de noms, ou dans les classes, bien que certains C compilateurs étendent la norme dans certaines de ces directions).

Tout fonctionne maintenant :) Pour résumer vos messages:

Ecrire DLL en C ++:

// Header
extern "C"
{   // Name in DLL will be "MyAdd" - but you won't be able to find parameters etc...
    __declspec(dllexport) int MyAdd(int a, int b);
}  
// Name will be with lot of prefixes but some other info is provided - IMHO better approach
__declspec(dllexport) int MyAdd2(int a, int b);

//.cpp Code
__declspec(dllexport) int MyAdd(int a, int b)
{   return a+b;
}
__declspec(dllexport) int MyAdd2(int a, int b)
{   return a+b;
} 

Ensuite, vous pouvez utiliser link.exe programme pour voir son vrai nom de fonction dll. link.exe est par exemple MSVC2010 ici:

c:\program files\microsoft visual studio 10.0\VC\bin\link.exe

utilisation:

link /dump /exports yourFileName.dll

vous voyez quelque chose comme:

ordinal hint RVA      name
      1    0 00001040 ?MyAdd2@@YAHHH@Z = ?MyAdd2@@YAHHH@Z (int __cdecl MyAdd2(int,int))
      2    1 00001030 MyAdd = _MyAdd

Ensuite, en python, vous pouvez l'importer comme:

import ctypes

mc = ctypes.CDLL('C:\\testDll3.dll')

#mc.MyAdd2(1,2) # this Won't Work - name is different in dll
myAdd2 = getattr(mc,"?MyAdd2@@YAHHH@Z") #to find name use: link.exe /dump /exports fileName.dll 
print myAdd2(1,2)
#p1 = ctypes.c_int (1) #use rather c types
print mc[1](2,3) # use indexing - can be provided using link.exe

print mc.MyAdd(4,5)
print mc[2](6,7) # use indexing - can be provided using link.exe
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top