Python:使用 ctypes 访问 DLL 函数 - 通过函数 *name* 访问失败
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
myPythonClient
(below) wants to invoke a ringBell
function (loaded from a DLL using ctypes
). However, attempting to access ringBell
via its name results in an AttributeError
. Why?
RingBell.h
contains
namespace MyNamespace
{
class MyClass
{
public:
static __declspec(dllexport) int ringBell ( void ) ;
} ;
}
RingBell.cpp
contains
#include <iostream>
#include "RingBell.h"
namespace MyNamespace
{
int __cdecl MyClass::ringBell ( void )
{
std::cout << "\a" ;
return 0 ;
}
}
myPythonClient.py
contains
from ctypes import *
cdll.RingBell[1]() # this invocation works fine
cdll.RingBell.ringBell() # however, this invocation errors out
# AttributeError: function 'ringBell' not found
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
您的 C++ 编译器正在修改所有外部可见对象的名称,以反映(及其底层名称)它们的命名空间、类和签名(这就是重载成为可能的方式)。
为了避免这种损坏,您需要在希望从非 C++ 代码中可见的外部可见名称上使用
extern "C"
(因此此类名称不能被重载,在 C++ 标准中也不能重载)它们是内联的、在命名空间内或在类内,尽管一些 C++ 编译器在其中一些方向上扩展了标准)。Your C++ compiler is mangling the names of all externally visible objects to reflect (as well as their underlying names) their namespaces, classes, and signatures (that's how overloading becomes possible).
In order to avoid this mangling, you need an
extern "C"
on externally visible names that you want to be visible from non-C++ code (and therefore such names cannot be overloaded, nor in C++ standard can they be inline, within namespaces, or within classes, though some C++ compilers extend the standard in some of these directions).现在一切正常:) 总结一下您的帖子:
用 C++ 编写 DLL:
然后您可以使用程序 link.exe 来查看 dll 中的真实函数名称。
例如,MSVC2010 中的 link.exe 如下:
使用:
你会看到类似的内容:
然后在 python 中你可以将其导入为:
All is working now :) To summarize your posts:
Write DLL in C++:
Then you can use program link.exe to see real function name in dll.
link.exe is for example in MSVC2010 here:
use:
you see Something like:
Then in python you can import it as:
也许是因为 C++ 名称被编译器破坏了,并且没有作为
RingBell
从 DLL 导出。 您是否检查过它在导出的名称中是否完全一样?Perhaps because the C++ name is mangled by the compiler and not exported from the DLL as
RingBell
. Have you checked that it appears in the exported names exactly like that?