Search code examples
pythondllctypesprivatename-mangling

How to use ctypes to call a DLL function with double underline function name?


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?


Solution

  • 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.