【问题标题】:How to use ctypes to call a DLL function with double underline function name?如何使用 ctypes 调用具有双下划线函数名的 DLL 函数?
【发布时间】: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

我该如何处理这种情况?

【问题讨论】:

    标签: python dll ctypes private name-mangling


    【解决方案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 只有一个调用约定,因此任何一种都可以,但为了可移植性,请记住这一点。

    【讨论】:

      猜你喜欢
      • 2015-09-21
      • 1970-01-01
      • 2013-11-25
      • 2021-11-03
      • 1970-01-01
      • 1970-01-01
      • 2013-08-28
      • 1970-01-01
      • 2010-10-21
      相关资源
      最近更新 更多