如何使用 ctypes 调用具有双下划线函数名的 DLL 函数?
Posted
技术标签:
【中文标题】如何使用 ctypes 调用具有双下划线函数名的 DLL 函数?【英文标题】:How to use ctypes to call a DLL function with double underline function name? 【发布时间】:2021-03-21 21:51:55 【问题描述】:我正在尝试使用带有 ctypes
模块的 Python 3.8 调用 DLL 中的函数。
DLL 中的函数名是__apiJob()
。注意,这个函数以双下划线开头。
我想在自定义对象中调用它,例如:
class Job:
def __init__(self,dll_path):
self.windll = ctypes.WinDLL(dll_path)
def execute(self):
self.windll.__apiJob()
a = Job('api64.dll')
a.execute()
但是由于函数名以双下划线开头,在 Python 中以 mangling 函数命名,会被视为私有方法。因此,在运行此脚本时,__apiJob
将被重命名为 _Job_apiJob
,从而导致错误:"_Job__apiJob" not found
。
我该如何处理这种情况?
【问题讨论】:
【参考方案1】:也可以使用以下语法调用该函数,并绕过 Python 对类实例的“dunder”属性的混淆:
self.windll['__apiJob']()
下面的例子:
test.cpp
extern "C" __declspec(dllexport)
int __apiJob()
return 123;
test.py
import ctypes
class Job:
def __init__(self):
dll = ctypes.CDLL('./test')
self.apiJob = dll['__apiJob'] # bypass "dunder" class name mangling
self.apiJob.argtypes = ()
self.apiJob.restype = ctypes.c_int
def execute(self):
return self.apiJob()
a = Job()
result = a.execute()
print(result)
输出:
123
顺便说一句,WinDLL
用于在 32 位 DLL 中使用 __stdcall
调用约定声明函数的 DLL。 CDLL
用于默认的 __cdecl
调用约定。 64 位 DLL 只有一个调用约定,因此任何一种都可以,但为了可移植性,请记住这一点。
【讨论】:
以上是关于如何使用 ctypes 调用具有双下划线函数名的 DLL 函数?的主要内容,如果未能解决你的问题,请参考以下文章
从 QMainWindow 调用具有变量名的 Python 函数