C模型
假设我有以下C数据结构,我希望向Python公开.
#include
#include
struct mystruct
{
int a, b, c, d, e, f, g, h, i, j, k, l, m;
};
typedef std::vector> mystruct_list;
提升Python
我可以使用boost :: python使用以下代码相当有效地包装它们,轻松地允许我使用现有的mystruct(复制shared_ptr)而不是重新创建现有对象.
#include "mystruct.h"
#include
using namespace boost::python;
BOOST_PYTHON_MODULE(example)
{
class_>("MyStruct", init<>())
.def_readwrite("a", &mystruct::a);
// add the rest of the member variables
class_("MyStructList", init<>())
.def("at", &mystruct_list::at, return_value_policy());
// add the rest of the member functions
}
用Cython
在Cython中,我不知道如何从mystruct_list中提取项目,而不复制底层数据.我不知道如何从现有的shared_ptr< mystruct>初始化MyStruct,而不是以各种形式之一复制所有数据.
from libcpp.memory cimport shared_ptr
from cython.operator cimport dereference
cdef extern from "mystruct.h" nogil:
cdef cppclass mystruct:
int a, b, c, d, e, f, g, h, i, j, k, l, m
ctypedef vector[v] mystruct_list
cdef class MyStruct:
cdef shared_ptr[mystruct] ptr
def __cinit__(MyStruct self):
self.ptr.reset(new mystruct)
property a:
def __get__(MyStruct self):
return dereference(self.ptr).a
def __set__(MyStruct self, int value):
dereference(self.ptr).a = value
cdef class MyStructList:
cdef mystruct_list c
cdef mystruct_list.iterator it
def __cinit__(MyStructList self):
pass
def __getitem__(MyStructList self, int index):
# How do return MyStruct without copying the underlying `mystruct`
pass
我看到许多可能的解决方法,但没有一个是非常令人满意的:
我可以初始化一个空的MyStruct,并在Cython中通过shared_ptr进行分配.然而,这将导致浪费一个初始化的结构,绝对没有理由.
MyStruct value
value.ptr = self.c.at(index)
return value
我也可以将现有mystruct中的数据复制到新的mystruct中.然而,这遭受类似的膨胀.
MyStruct value
dereference(value.ptr).a = dereference(self.c.at(index)).a
return value
我还可以为每个__cinit__方法公开一个init = True标志,如果C对象已经存在(当init为False时),它将阻止在内部重建对象.但是,这可能会导致灾难性问题,因为它会暴露给Python API并允许取消引用null或未初始化的指针.
def __cinit__(MyStruct self, bint init=True):
if init:
self.ptr.reset(new mystruct)
我也可以使用暴露于Python的构造函数(它将重置self.ptr)重载__init__,但如果从Python层使用__new__,这将有危险的内存安全性.
底线
我很想使用Cython,编译速度,语法糖和许多其他原因,而不是相当笨重的boost :: python.我现在正在看pybind11,它可能会解决编译速度问题,但我仍然希望使用Cython.
有没有什么办法可以在Cython中以惯用方式完成这么简单的任务?谢谢.