我正在尝试设计一个可以在Python中轻松扩展的C接口(使用ctypes)。我在C中使用了natural idiom:
struct format {
int (*can_open)(const char *filename);
struct format * (*open)(const char *filename);
void (*delete)(struct format *self);
int (*read)(struct format *self, char *buf, size_t len);
};
如果我想直接从C扩展这个接口,它会很好地工作:
^{pr2}$但我真正想做的是使用ctypes从Python实现这个接口。以下是我目前所掌握的情况:
CANOPENFUNC = ctypes.CFUNCTYPE(ctypes.c_int, ctypes.c_char_p)
#OPENFUNC = ctypes.CFUNCTYPE(ctypes.c_void_p, ctypes.c_char_p)
#OPENFUNC = ctypes.CFUNCTYPE(ctypes.POINTER( python_format ), ctypes.c_char_p)
#DELETEFUNC = ctypes.CFUNCTYPE(None, ctypes.c_void_p)
#READFUNC = ctypes.CFUNCTYPE(ctypes.c_int, ctypes.c_void_p)
def py_canopen_func( string ):
print "py_canopen_func", string
return 1
canopen_func = CANOPENFUNC(py_canopen_func)
#open_func = OPENFUNC( py_open_func)
#delete_func = DELETEFUNC(py_canopen_func)
#read_func = READFUNC(py_canopen_func)
class python_format(ctypes.Structure):
_fields_ = (
('can_open', CANOPENFUNC),
('open', OPENFUNC),
('delete', DELETEFUNC),
('read', READFUNC),
)
def __init__(self):
self.can_open = canopen_func
OPENFUNC = ctypes.CFUNCTYPE(ctypes.POINTER(python_format), ctypes.c_char_p)
def py_open_func2( string ):
print "py_open_func2", string
return ctypes.byref(self)
self.open = OPENFUNC( py_open_func2 )
#self.delete = delete_func
#self.read = read_func
实际上,我正在努力定义OPENFUNC
的原型。技术上应该是:
OPENFUNC = ctypes.CFUNCTYPE(ctypes.POINTER(python_format), ctypes.c_char_p)
不过,我需要先定义python_format
,这又需要{
加分:什么是实际的函数实现?例如:
def func( str ): return None
或者
def func( str ): i = python_format(); return ctypes.pointer(i)
两者都给了我:
class python_format(ctypes.Structure):
pass
OPENFUNC = ctypes.CFUNCTYPE(ctypes.POINTER( python_format ), ctypes.c_char_p)
OPENFUNC( func )
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: invalid result type for callback function
这和另一个issue有关吗?如果是这样的话,我应该改变我最初的C设计,因为我将无法从回调返回指向python_format
实例的指针?在
在
ctypes.Structure
的文档中,它解释了如何执行此操作:这意味着您可以添加:
然后在定义
^{pr2}$OPENFUNC
(以及其他函数类型)之后:因此,能够定义
python_format._fields_
:下面是一个基于您的代码的更完整的示例:
为了得到一个规范的答案,我将回答我自己的问题,这要感谢@eryksun的指导。在
因此,首先,虽然这在documentation中并不清楚,但不能从回调函数返回复杂类型。因此,不能映射C函数指针:
到
^{pr2}$上面的代码可以很好地编译,但是在运行时,可以得到:
长话短说的答案是:
因此,到今天为止,在issue 5710修复之前,唯一的解决方案是:
相关问题 更多 >
编程相关推荐