The way to access global variables from ctypes
is to use in_dll
, but there doesn't seem to be an exposed way to change a function pointer. I was only able to read it and call it, so I don't think it is possible without a helper function.
The example below alters an int
global variable, but CFUNCTYPE
instances don't have a value
member to alter it. I added a C helper to set the global to work around the issue and a default value of the callback to verify it was accessed correctly before changing it.
test.c:
#include <stdio.h>
#define API __declspec(dllexport)
typedef void (*CB)();
void dllplot() {
printf("default
");
}
API CB plot = dllplot;
API int x = 5;
API int c_main() {
printf("x=%d (from C)
",x);
plot();
return 0;
}
API void set_cb(CB cb) {
plot = cb;
}
test.py:
from ctypes import *
PLOT = CFUNCTYPE(None)
dll = CDLL('./test')
dll.c_main.argtypes = ()
dll.c_main.restype = c_int
dll.set_cb.argtypes = PLOT,
dll.set_cb.restype = None
@PLOT
def plotxy():
print("plotxy")
x = c_int.in_dll(dll,'x')
plot = PLOT.in_dll(dll,'plot')
print(f'x={x.value} (from Python)')
x.value = 7
print('calling plot from Python directly:')
plot()
print('calling c_main():')
dll.c_main()
dll.set_cb(plotxy)
print('calling plot from Python after setting callback:')
plot()
print('calling plot from C after setting callback:')
dll.c_main()
Output:
x=5 (from Python)
calling plot from Python directly:
default
calling c_main():
x=7 (from C)
default
calling plot from Python after setting callback:
plotxy
calling plot from C after setting callback:
x=7 (from C)
plotxy
Note that global pointers use .contents
to access their value, so I experimented with using a POINTER(CFUNCTYPE(None))
and using plot.contents = plotxy
but that doesn't assign the global variable correctly and C crashed.
I even tried adding an actual global pointer to function pointer:
API CB plot = dllplot;
API CB* pplot = &plot;
and then using:
PLOT = CFUNCTYPE(None)
PPLOT = POINTER(PLOT)
plot = PPLOT.in_dll(dll,'pplot')
plot.contents = plotxy
That let me assign the function via .contents
, but c_main
still called the default plot value. So the functionality of using CFUNCTYPE
as anything but a function parameter doesn't appear to be implemented.
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…