【发布时间】:2020-07-18 22:45:24
【问题描述】:
考虑一下test.c:
#include <stdio.h>
const char *x = "one";
void set_x(const char *new_x) {
x = new_x;
}
void print_x(void) {
printf("x is %s\n", x);
}
void first_f(void) {
puts("In first function");
}
void (*f)(void) = first_f;
void set_f(void (*new_f)(void)) {
f = new_f;
}
void do_f(void) {
f();
}
还有这个test.py:
#!/usr/bin/env python3
import ctypes
def second_f():
print('In second function')
def third_f():
print('In third function')
test_so = ctypes.CDLL('./test.so')
x_type = ctypes.c_char_p
f_type = ctypes.CFUNCTYPE(None)
test_so.set_x.restype = None
test_so.set_x.argtypes = (x_type,)
test_so.print_x.restype = None
test_so.print_x.argtypes = ()
test_so.set_f.restype = None
test_so.set_f.argtypes = (f_type,)
test_so.do_f.restype = None
test_so.do_f.argtypes = ()
test_so.print_x()
x = x_type.in_dll(test_so, 'x')
x.value = b'two'
test_so.print_x()
new_x = x_type(b'three')
test_so.set_x(new_x)
test_so.print_x()
test_so.do_f()
f = f_type.in_dll(test_so, 'f')
f.value = second_f
test_so.do_f()
new_f = f_type(third_f)
test_so.set_f(new_f)
test_so.do_f()
当我运行 gcc -g -fPIC -shared test.c -o test.so && ./test.py 时,我会得到以下输出:
x is one
x is two
x is three
In first function
In first function
In third function
我想要/期望得到In second function,而不是第二次出现In first function。为什么不直接使用in_dll 设置全局变量f,而我所做的一切都与x 一样?显然,Python 知道如何将自己的函数转换为 C 函数指针,因为当我使用 third_f 调用 setter 时它可以正常工作。但是如何在没有 setter 的情况下使其工作,例如 x 工作?
【问题讨论】:
-
CFUNCTYPE创建函数类型,而不是函数指针类型。如果你创建一个函数指针类型并通过正确的类型访问f会发生什么? -
(另外,您需要保留对通过
f_type创建的对象的引用,因为 ctypes 无法为您做到这一点。您通过在其生命周期后尝试使用回调来调用未定义的行为结束。) -
@user2357112supportsMonica 你的意思是如果我不是
f_type = ctypes.CFUNCTYPE(None),而是f_type = ctypes.POINTER(ctypes.CFUNCTYPE(None))?然后倒数第二行不变,但最后一行替换为Traceback (most recent call last): File "./test.py", line 33, in <module> test_so.set_f(f_type(third_f)) TypeError: expected CFunctionType instead of function。 -
我更新了我的代码以保留参考。
-
@user2357112supportsMonica A
POINTER(CFUNCTYPE(None)也不起作用。CFUNCTYPE(NONE)实例“衰减”为指向函数的指针,因此它更像是指向函数的双指针。我在this answer 中玩过这个问题(这个问题可以标记为那个问题的副本),它也不起作用。ctypes似乎不直接支持全局函数指针,必须使用辅助函数。
标签: python c global-variables function-pointers ctypes