Python使用ctypes访问DLL函数- 使用函数*名称*失败

2024-03-28 09:09:52 发布

您现在位置:Python中文网/ 问答频道 /正文

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

Tags: 函数includemyclassthisctypesnamespaceintattributeerror
3条回答
<>你的C++编译器正在对所有外部可见对象的名称进行修改,以反映它们的命名空间、类和签名(这就是过载可能成为可能)。

<>为了避免这种错误,需要从非可见代码中看到的外部可见名称(^ ^),{CD1.}}(因此,这些名称不能重载,也不能在C++标准中,它们可以是内联的,在命名空间内,或在类内,尽管一些C++编译器在某些方向上扩展了标准)。

可能是因为C++名称被编译器损坏,而不是从DLL导出为^ {CD1>}。您检查过它在导出的名称中是否与此完全相同吗?

现在一切正常:)总结你的文章:

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

然后可以使用program 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

相关问题 更多 >