Assigning Python function to ctypes pointer variable -
i have following c source compile dll:
int (*pfuncextb)(int a, int b); int funcb(int a, int b) { return funcextb(a, b); } int funcextb(int a, int b) { return pfuncextb(a, b); } what want make pfuncextb "point" python function, in python:
from ctypes import * def add(a, b): return + b mutdll = cdll.loadlibrary("my.dll") pfuncextb = (pointer(cfunctype(c_int, c_int, c_int))).in_dll(mutdll, 'pfuncextb') funcb = mutdll.funcb funcb.argtypes = [c_int, c_int] funcb.restype = c_int pfuncextb.contents = cfunctype(c_int, c_int, c_int)(add) print funcb(3 , 4) after expect following call return 7
print funcb(3, 4) but get:
traceback (most recent call last): .................. print funcb(3, 4) windowserror: exception: access violation reading 0x00000001 so doing wrong here? possible have python function "assigned" ctypes pointer-to-function variable?
edit: after seeing mark tolonen's workaround (a set function pointer function variable written in c), found why didn't work me when tried it.
this not work:
set(cfunctype(c_int,c_int,c_int)(add)) print funcb(2, 3) while works:
callback = cfunctype(c_int,c_int,c_int)(add) set(callback) print funcb(2, 3) where set c function assigns pointer-to-function argument global in mark's answer. pointed out answer lays in docs:
important note callback functions: make sure keep references cfunctype() objects long used c code. ctypes doesn’t, , if don’t, may garbage collected, crashing program when callback made.
the correct type of global variable in python cfunctype(c_int,c_int,c_int) (no pointer()), don't see method change value of variable once have it. if can add set function can work:
c
typedef int (*func)(int,int); __declspec(dllexport) func pfuncextb; __declspec(dllexport) void set(func f) { pfuncextb = f; } int funcextb(int a, int b) { return pfuncextb(a, b); } __declspec(dllexport) int funcb(int a, int b) { return funcextb(a, b); } python
from ctypes import * func = cfunctype(c_int,c_int,c_int) @func def add(a, b): return + b mutdll = cdll.loadlibrary('x') mutdll.set.argtypes = [func] mutdll.set.restype = none mutdll.set(add) # set global variable pfuncextb = func.in_dll(mutdll,'pfuncextb') print(pfuncextb(1,2)) # -> 3 funcb = mutdll.funcb funcb.argtypes = [c_int, c_int] funcb.restype = c_int print(funcb(3 , 4)) # -> 7 note not work:
pfuncextb = pointer(func).in_dll(mutdll,'pfuncextb') pfuncextb.contents(1,2) # exception!
Comments
Post a Comment