The CB_Func (cbFunc) parameter receives garbage collection immediately after the setCallback function. This object must be stored until a callback can be called ( 15.17.1.17. Callback functions , last paragraph). Assign it to a variable and save it. Here is my working example:
Dll
typedef unsigned int DWORD; typedef long LONG; typedef int BOOL; #define TRUE 1 #define FALSE 0 typedef void (__stdcall *CALLBACK)(DWORD,DWORD); CALLBACK g_callback = 0; DWORD g_port = 0; DWORD g_user = 0; BOOL __declspec(dllexport) setCallback (LONG nPort, CALLBACK callback, DWORD nUser) { g_callback = callback; g_port = nPort; g_user = nUser; return TRUE; } void __declspec(dllexport) Fire() { if(g_callback) g_callback(g_port,g_user); }
Error Script
from ctypes import * def cb_func(port,user): print port,user x = CDLL('x') CALLBACK = WINFUNCTYPE(None,c_uint,c_uint)
Transfer Script
from ctypes import * def cb_func(port,user): print port,user x = CDLL('x') CALLBACK = WINFUNCTYPE(None,c_uint,c_uint) cbfunc = CALLBACK(cb_func) x.setCallback(1,cbfunc,2) x.Fire()
Change In addition, since CALLBACK
is a function returning a function, it can be used as a decorator for Python callbacks, eliminating the problem of callbacks that go out of scope:
from ctypes import * CALLBACK = WINFUNCTYPE(None,c_uint,c_uint) @CALLBACK def cb_func(port,user): print port,user x = CDLL('x') x.setCallback(1,cb_func,2) x.Fire()
source share