Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/308.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 用ctypes替换共享库中的函数指针_Python_C_Callback_Function Pointers_Ctypes - Fatal编程技术网

Python 用ctypes替换共享库中的函数指针

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; }

我试图通过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;
}
要测试它的脚本:

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