的Python:使用ctypes的访问DLL函数 - 按功能存取名*失败
-
23-08-2019 - |
题
myPythonClient
(下面)想要调用ringBell
函数(使用ctypes
一个DLL加载)。然而,试图访问经由其名称的结果ringBell
在AttributeError
。为什么呢?
RingBell.h
包含
namespace MyNamespace
{
class MyClass
{
public:
static __declspec(dllexport) int ringBell ( void ) ;
} ;
}
RingBell.cpp
包含
#include <iostream>
#include "RingBell.h"
namespace MyNamespace
{
int __cdecl MyClass::ringBell ( void )
{
std::cout << "\a" ;
return 0 ;
}
}
myPythonClient.py
包含
from ctypes import *
cdll.RingBell[1]() # this invocation works fine
cdll.RingBell.ringBell() # however, this invocation errors out
# AttributeError: function 'ringBell' not found
解决方案
也许是因为C ++名称是由编译器错位,而不是从DLL作为RingBell
导出。你检查它出现在导出的名字完全一样?
其他提示
您C ++编译器重整所有外部可见对象的名称,以反映(以及它们的基础名称)他们的命名空间,类,和签名(这是如何重载成为可能)。
为了避免这种混淆,需要对要可见从非C ++代码(并且因此这样的名字不能被重载外部可见的名字的extern "C"
,也不在C ++标准可以它们是内联的,名称空间内,或类中,虽然有些C ++编译器延伸在一些这些方向的标准)。
现在所有的工作:)总结一下自己的帖子:
在C ++写DLL:
// 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;
}
然后你可以使用程序LINK.EXE在DLL中看到真正的函数名。 LINK.EXE是例如在这里MSVC2010:
c:\program files\microsoft visual studio 10.0\VC\bin\link.exe
使用:
link /dump /exports yourFileName.dll
您看到喜欢的东西:
ordinal hint RVA name
1 0 00001040 ?MyAdd2@@YAHHH@Z = ?MyAdd2@@YAHHH@Z (int __cdecl MyAdd2(int,int))
2 1 00001030 MyAdd = _MyAdd
然后在Python可将其导入为:
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
不隶属于 StackOverflow