Python 用ctypes替换共享库中的函数指针
我试图通过ctypes用Python中定义的回调函数替换共享库中现有的函数指针 C中共享库的源:Python 用ctypes替换共享库中的函数指针,python,c,callback,function-pointers,ctypes,Python,C,Callback,Function Pointers,Ctypes,我试图通过ctypes用Python中定义的回调函数替换共享库中现有的函数指针 C中共享库的源: #include <assert.h> #include <stdio.h> void (*plot)(); int c_main(int argc, void** argv) { printf("plot is %p\n", (void*)plot); assert(plot != NULL); plot(); return 0; }
#include <assert.h>
#include <stdio.h>
void (*plot)();
int c_main(int argc, void** argv) {
printf("plot is %p\n", (void*)plot);
assert(plot != NULL);
plot();
return 0;
}
要测试它的脚本:
gcc -fPIC -shared -o test.so test.c
python3 test.py
我得到的输出:
# ./test.sh
<CFunctionType object at 0x7fb1f0abb1c0>
<_FuncPtr object at 0x7fb1f0abb640>
<CFunctionType object at 0x7fb1f0abb1c0>
plot is (nil)
python3: test.c:8: c_main: Assertion `plot != NULL' failed.
./test.sh: line 3: 21171 Aborted python3 test.py
#/test.sh
图为(无)
python3:test.c:8:c_main:Assertion`plot!=“NULL”失败。
./test.sh:line 3:21171中止的python3 test.py
因此,Python(plotxy)中定义的函数类型似乎是CFunctionType
,而C中定义的函数指针类型是\u FuncPtr
。虽然应用了CAUXDLL
中的替换,但在调用main函数时似乎没有效果
除了阅读,我还发现了其他问题(如or),但我找不到如何将CFunctionType
(plotxy)转换为\u FuncPtr
编辑
我相信这可能不是常规使用ctypes的问题。我已经成功地做到了这一点,文档中对此做了充分的解释。这个问题超出了范围。我不想执行C函数。我希望Python用Python编写的回调函数替换现有的函数指针。请注意,可以通过使用helper C函数来实现(请参阅)。因此,这个问题是关于如何在没有辅助函数的情况下实现它(如果可能)。从
ctypes
访问全局变量的方法是使用dll中的,但似乎没有公开的方法来更改函数指针。我只能读它并调用它,所以我认为没有辅助函数是不可能的
下面的示例更改了int
全局变量,但是CFUNCTYPE
实例没有值
成员来更改它。我添加了一个C助手来设置全局函数来解决这个问题,并添加了一个回调的默认值来验证在更改它之前是否正确访问了它
测试c:
#include <stdio.h>
#define API __declspec(dllexport)
typedef void (*CB)();
void dllplot() {
printf("default\n");
}
API CB plot = dllplot;
API int x = 5;
API int c_main() {
printf("x=%d (from C)\n",x);
plot();
return 0;
}
API void set_cb(CB cb) {
plot = cb;
}
输出:
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
请注意,全局指针使用.contents
来访问其值,因此我尝试使用指针(CFUNCTYPE(None))
和plot.contents=plotxy
,但这并没有正确分配全局变量,C崩溃
我甚至尝试将实际的全局指针添加到函数指针:
API CB plot = dllplot;
API CB* pplot = &plot;
然后使用:
PLOT = CFUNCTYPE(None)
PPLOT = POINTER(PLOT)
plot = PPLOT.in_dll(dll,'pplot')
plot.contents = plotxy
这让我可以通过.contents
分配函数,但是c_main
仍然调用默认的绘图值。因此,将CFUNCTYPE
用作函数参数之外的任何东西的功能似乎都没有实现。对于不正确的重复,我深表歉意。c_的主要参数是一个转移注意力的问题,可以从问题中删除。我在下面的回答中跳过了它们。不用担心!很抱歉给你添麻烦了。我找不到如何回复您的私人评论,我不确定您是否会在一个封闭式问题(标记为dup)中收到评论/编辑的通知。感谢您富有洞察力的回答。不幸的是,您证实了我的猜测,但我在_dll
和\u declspec(dllexport)中了解了。
API CB plot = dllplot;
API CB* pplot = &plot;
PLOT = CFUNCTYPE(None)
PPLOT = POINTER(PLOT)
plot = PPLOT.in_dll(dll,'pplot')
plot.contents = plotxy