Python: el acceso a la función DLL usando ctypes - el acceso de la función * Nombre * falla

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

Pregunta

myPythonClient (abajo) quiere invocar una función ringBell (cargado desde un archivo DLL usando ctypes). Sin embargo, el intento de acceder a través de sus ringBell nombre resultados en una AttributeError. ¿Por qué?

RingBell.h contiene

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

RingBell.cpp contiene

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

myPythonClient.py contiene

from ctypes import *
cdll.RingBell[1]() # this invocation works fine
cdll.RingBell.ringBell() # however, this invocation errors out
# AttributeError: function 'ringBell' not found
¿Fue útil?

Solución

Tal vez porque el nombre de C ++ está destrozado por el compilador y no exporta desde el DLL como RingBell. ¿Ha comprobado que aparezca en los nombres exportados exactamente así?

Otros consejos

Su compilador de C ++ está destrozando los nombres de todos los objetos visibles externamente para reflejar (así como sus nombres subyacentes) sus espacios de nombres, clases y firmas (así es como se hace posible sobrecarga).

Con el fin de evitar este mangling, necesita un extern "C" sobre los nombres visibles externamente que desea ser visible desde el código no-C ++ (y por lo tanto tales nombres no pueden ser sobrecargados, ni en C ++ estándar puede que sea en línea, dentro de los espacios de nombres, o dentro de las clases, aunque compiladores algunos C ++ extienden el estándar en algunas de estas direcciones).

Todo está trabajando ahora :) Para resumir sus mensajes:

Escribir 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;
} 

A continuación, puede utilizar link.exe programa para ver una función real en la DLL. link.exe es por ejemplo en MSVC2010 aquí:

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

uso:

link /dump /exports yourFileName.dll

ves algo como:

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

A continuación, en Python se puede importar como:

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
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top