Ctypes - Passing a Void Pointer from Python
Question: I am accessing a C++ DLL using Python Ctypes on Windows 7. I have the
documentation for the DLL, but I can't actually open it. I'm trying to use a
C++ function that takes in a function, which in turn takes in an unsigned int
and a void pointer. Here is a short code sample that fails:

    
    
    import ctypes
    import os
    
    root = os.path.dirname(__file__)
    lib = ctypes.WinDLL(os.path.join(root, 'x86', 'toupcam.dll')) #works
    
    cam = lib.Toupcam_Open(None) #works
    
    def f(event, ctx): #Python version of function to pass in
        pass
    
    #converting Python function to C function:
    #CFUNTYPE params: return type, parameter types
    func = ctypes.CFUNCTYPE(None, ctypes.c_uint, ctypes.c_void_p)(f)
    
    res = lib.Toupcam_StartPullModeWithCallback(cam, func) #fails
    

Whenever I run this code I get this error on the last line:

    
    
    OSError: exception: access violation writing 0x002CF330.
    

I don't really know how to approach this issue, since it's a C++ error not a
Python error. I think it has to do with my void pointer, since similar errors
I found online for C++ were pointer-related. Is there something wrong with the
Ctypes void pointer, or am I doing something wrong?


Answer: You need to declare the argument types of the functions you call using
`argtypes`. Since I don't know your exact API, here's an example:

Windows C DLL code with a callback:

    
    
    typedef void (*CB)(int a);
    
    __declspec(dllexport) void do_callback(CB func)
    {
        int i;
        for(i=0;i<10;++i)
            func(i);
    }
    

Python code:

    
    
    from ctypes import *
    
    # You can use as a Python decorator.
    @CFUNCTYPE(None,c_int)
    def callback(a):
      print(a)
    
    # Use CDLL for __cdecl calling convention...WinDLL for __stdcall.
    do_callback = CDLL('test').do_callback
    do_callback.restype = None
    do_callback.argtypes = [CFUNCTYPE(None,c_int)]
    
    do_callback(callback)
    

Output:

    
    
    0
    1
    2
    3
    4
    5
    6
    7
    8
    9
    

