[英]cython wrap cpp structs and function with parameter an array of structs
我正在使用 Cython 在 python 中包装一个 C++ 库。 不幸的是,我无法访问 C++ 库。 因此,我必须以某种方式找到一种方法来包装由 lib API 公开的结构和函数。
我的问题是关于包装 c++ 结构的最佳方式和; 随后,如何在python中创建一个内存视图并将其指针(第一个元素地址)传递给一个带有参数cpp结构数组的c++函数。
例如,假设我有以下 h 文件:
//test.h
struct cxxTestData
{
int m_id;
double m_value;
};
void processData(cxxTestData* array_of_test_data, int isizeArr)
我的 pyx 文件将如下所示
cdef extern from "Test.h":
cdef struct cxxTestData:
int m_id
double m_value
cdef class pyTestData:
cdef cxxTestData cstr
def __init__(self, id, value):
self.cstr.m_id = id
self.cstr.m_value = value
@property
def ID(self):
return self.cstr.m_id
@property
def Value(self):
return self.cstr.m_value
现在,我想创建一些 pyTestData 并将它们存储在一个 dtype 对象数组中。 然后我想在 cython/python 函数中将此数组作为内存视图传递。
包装函数将具有以下签名
cpdef void pyProcessData(pyTestData[::1] test_data_arr)
我已经测试了上面的内容并且它编译成功。 我还设法修改了每个结构的成员。 然而,这不是我想要达到的目标。 我的问题是如何从这一点上传递一个数组,其中包含封装在每个 pyTestData 对象中的 C++ 结构(通过 self.cstr)。
作为示例,请查看以下列表:
cpdef void pyProcessData(pyTestData[::1] test_data_arr):
cdef int isize test_data_arr.shape[0]
# here I want to create/insert an array of type cxxTestData to pass it
# to the cpp function
# In other words, I want to create an array of [test_data_arr.cstr]
# I guess I can use cxxTestData[::1] or cxxTestData* via malloc and
# copy each test_data_arr[i].cstr to this new array
cdef cxxTestData* testarray = <cxxTestData*>malloc(isize*sizeof(cxxTestData))
cdef int i
for i in range(isize):
testarray[i] = test_data_arr[i].cstr
processData(&testarray[0], isize)
for i in range(isize):
arrcntrs[i].pystr = testarray[i]
free(testarray)
有没有人遇到过这样的情况? 有没有更好的方法可以在上面的函数中传递我的 python 对象,而不必在内部复制 cxx 结构?
如果我做了一些根本错误的事情,非常感谢并道歉。
由于您希望将cxxTestData
数组传递给 C++ 函数,因此最好将其分配为数组。 一些未经测试的代码说明了该方法:
cdef class TestDataArray:
cdef cxxTestData* array:
def __init__(self, int length):
self.array = <cxxTestData*>calloc(length,sizeof(cxxTestData))
def __dealloc__(self):
free(self.array)
def __getitem__(self, int idx):
return PyTestData.from_pointer(&self.array[idx],self) # see later
def __setitem__(self, int idx, PyTestData pyobj): # this is optional
self.array[idx] = deref(pyobj.cstr)
然后您想稍微修改您的PyTestData
类,以便它保存一个指针而不是直接保存该类。 它还应该有一个字段代表数据的最终所有者(例如数组)。 这可以确保数组保持活动状态,并且还可以允许PyTestData
拥有自己的数据的情况:
cdef class PyTestData:
cdef cxxTestData* cstr
cdef object owner
def __init__(self, id, value):
self.owner = None
self.cstr = <cxxTestData*>malloc(sizeof(cxxTestData))
self.cstr.m_id = id
self.cstr.m_value = value
def __dealloc__(self):
if self.owner is None: # i.e. this class owns it
free(self.cstr)
@staticmethod
cdef PyTestData from_pointer(cxxTestData* ptr, owner):
# calling __new__ avoids calling the constructor
cdef PyTestData x = PyTestData.__new__(PyTestData)
x.owner = owner
x.cstr = ptr
return x
创建TestDataArray
类需要一些额外的努力,但它以可直接从 C++ 使用的格式存储数据,因此我认为这是最好的解决方案。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.