gpt4 book ai didi

python - 自引用类 : concrete python class from C interface

转载 作者:太空狗 更新时间:2023-10-29 15:35:27 32 4
gpt4 key购买 nike

我正在尝试设计一个可以在 Python 中轻松扩展的 C 接口(interface)(使用 ctypes )。我用过 natural idiom在 C:

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 扩展这个接口(interface),它工作得很好:

struct derived /* concrete implementation */
{
struct format base;
};

但我真正想做的是使用 ctypes 从 Python 实现这个接口(interface)。这是我目前所拥有的:

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 定义原型(prototype)。从技术上讲,它应该是:

OPENFUNC    = ctypes.CFUNCTYPE(ctypes.POINTER(python_format), ctypes.c_char_p)

但是我需要先定义 python_format,这又需要定义 OPENFUNC

奖励点:实际的功能实现是什么?例如:

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 实例的指针?

最佳答案

documentation对于 ctypes.Structure._fields_,它解释了如何执行此操作:

It is possible to define the _fields_ class variable after the class statement that defines the Structure subclass, this allows to create data types that directly or indirectly reference themselves

这意味着您可以添加:

class python_format(ctypes.Structure):  # forward declaration
pass

然后在定义OPENFUNC(和其他函数类型)之后:

OPENFUNC = ctypes.CFUNCTYPE(ctypes.POINTER( python_format ), ctypes.c_char_p)
DELETEFUNC = etc...

然后能够这样定义 python_format._fields_:

python_format._fields_ = (
('can_open', CANOPENFUNC),
('open', OPENFUNC),
('delete', DELETEFUNC),
('read', READFUNC),
)

这是一个基于您的代码的更完整的示例:

import ctypes

class python_format(ctypes.Structure): # forward declaration
pass

CANOPENFUNC = ctypes.PYFUNCTYPE(ctypes.c_int, ctypes.c_char_p)
OPENFUNC = ctypes.PYFUNCTYPE(ctypes.c_int,
ctypes.POINTER(python_format),
ctypes.c_char_p)
DELETEFUNC = ctypes.PYFUNCTYPE(None, ctypes.c_void_p)
READFUNC = ctypes.PYFUNCTYPE(ctypes.c_int, ctypes.c_void_p)

def py_canopen_func(self, string):
print "py_canopen_func", string
return 1

def py_open_func(self, string):
print "py_open_func2", string
# Return types from callbacks cannot be anything other than simple
# datatypes (c_int, c_float, ..., c_void_p). For other datatypes
# (STRUCTURE, POINTER, ...), ctypes returns the following error
# "Invalid result type for callback function"
# see http://bugs.python.org/issue5710
return 1 # can't return ctypes.byref(self)

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):
python_format._fields_ = (
('can_open', CANOPENFUNC),
('open', OPENFUNC),
('delete', DELETEFUNC),
('read', READFUNC),
)

def __init__(self):
self.can_open = canopen_func
self.open = open_func
#self.delete = delete_func
#self.read = read_func

pf = python_format()

关于python - 自引用类 : concrete python class from C interface,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29631692/

32 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com