Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Writing Python ctypes for Function pointer callback function in C

Tags:

python

c

ctypes

I am trying to write python code to call dll functions and stuck at the function below, which I believe is related to the typedef callback function or the function pointer thing.

I have tested the code below, when the callback function is called, python crashes (Window notification-- python.exe has stop responding) with no debug msg.

I am deeply confused, any help will be appreciated :)

Thanks!

C:

#ifdef O_Win32
/** @cond */
#ifdef P_EXPORTS
#define API __declspec(dllexport)
#else
#define API __declspec(dllimport)
#endif // #ifdef P_EXPORTS
/** @endcond */
#endif // #ifdef O_Win32

// Type definition
typedef void (__stdcall *StatusCB)(int nErrorCode, int nSID, void *pArg);

//Function 
void GetStatus(StatusCB StatusFn, void *pArg);

Python:

from ctypes import *

def StatusCB(nErrorCode, nSID, pArg):
    print 'Hello world'

def start():
    lib = cdll.LoadLibrary('API.dll')
    CMPFUNC = WINFUNCTYPE(c_int, c_int, c_void_p)
    cmp_func = CMPFUNC(StatusCB)
    status_func = lib.GetStatus
    status_func(cmp_func)
like image 970
genxstylez Avatar asked Jul 31 '13 20:07

genxstylez


1 Answers

Your callback type has the wrong signature; you forgot the result type. It's also getting garbage collected when the function exits; you need to make it global.

Your GetStatus call is missing the argument pArg. Plus when working with pointers you need to define argtypes, else you'll have problems on 64-bit platforms. ctypes' default argument type is a C int.

from ctypes import * 

api = CDLL('API.dll')
StatusCB = WINFUNCTYPE(None, c_int, c_int, c_void_p)

GetStatus = api.GetStatus
GetStatus.argtypes = [StatusCB, c_void_p]
GetStatus.restype = None

def status_fn(nErrorCode, nSID, pArg):        
    print 'Hello world'
    print pArg[0]  # 42?

# reference the callback to keep it alive
_status_fn = StatusCB(status_fn)

arg = c_int(42) # passed to callback?    

def start():        
    GetStatus(_status_fn, byref(arg))
like image 151
Eryk Sun Avatar answered Sep 22 '22 12:09

Eryk Sun