I'm trying to call a function in a DLL using Python 3.8 with the ctypes
module.
The function name in the DLL is __apiJob()
. Pay attention, this function starts with a double underline.
I want to call it in a self-defined object like:
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()
But as the function name starts with double underline, with the name mangling function in Python, it will be regarded as a private method. Therefore, when running this script, the __apiJob
will be renamed to _Job_apiJob
which results in an error: "_Job__apiJob" not found
.
How can I deal with situation?
The function can be called with the following syntax as well, and bypasses the obfuscation Python applies to "dunder" attributes of class instances:
self.windll['__apiJob']()
Example below:
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)
Output:
123
As an aside, WinDLL
is used for DLLs declaring functions using __stdcall
calling convention in 32-bit DLLs. CDLL
is used for the default __cdecl
calling convention. 64-bit DLLs have only one calling convention, so either works, but for portability keep this in mind.