I have the following C source that I compile into a 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 I want to do is to make pfuncExtB "point" to a Python function, so this is what I do in Python:
from ctypes import *
def add(a, b):
return a + 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 this I expect that the following call to return 7
print funcB(3, 4)
But I get:
Traceback (most recent call last):
..................
print funcB(3, 4)
WindowsError: exception: access violation reading 0x00000001
So what am I doing wrong here? Is it possible to have a Python function "assigned" to a ctypes pointer-to-function variable?
Edit: After seeing Mark Tolonen's workaround (a set function for the pointer to function variable written in C), I found why it didn't work for me when I tried it.
This does not work:
set(CFUNCTYPE(c_int,c_int,c_int)(add))
print funcB(2, 3)
While this works:
callback = CFUNCTYPE(c_int,c_int,c_int)(add)
set(callback)
print funcB(2, 3)
Where set is a C function that assigns the pointer-to-function argument to the global like in Mark's answer. As he pointed out the answer is lays in the docs:
Important note for callback functions: Make sure you keep references to CFUNCTYPE() objects as long as they are used from C code. ctypes doesn’t, and if you don’t, they may be garbage collected, crashing your program when a callback is made.