【发布时间】:2016-07-28 19:12:02
【问题描述】:
我正在做一个项目,我有一个可用的大型 C++ 代码库,我想用 cython 包装并在 python 中提供。
这样做时,我面临的情况是我的一些 C++ 函数返回 Vector 对象或简单对象(具有多个属性)。我想将此对象返回给 Python,以便可以访问其值。
为此,我几乎完全关注这篇文章:How to expose a function returning a C++ object to Python without copying the object?
我有一个非常相似的要求。请参阅上述论坛中实现/使用的 move 构造。
以下是我尝试为简单(非向量情况)实现的代码:
test_header.pxd
from libcpp.vector cimport vector
from libcpp.string cimport string
from libcpp.map cimport map
cdef extern from "main_class.h":
cdef cppclass main_class:
int ID1
double ID2
cdef extern from "class2.h":
cdef cppclass class2:
class2() except +
class2(const double& T) except +
void Add(const main_class& ev)
const vector[main_class]& GetEvs()
#Process Class
cdef extern from "Pclass.h":
cdef cppclass Pclass:
Pclass(const unsigned& n, const unsigned& dims) except +
unsigned GetDims()
double processNext(const class2& data, const unsigned& num_iter)
cdef extern from "main_algo.h":
#TODO: Check if inheritance works correctly, virtual functions, objects, std::vector
cdef cppclass main_algo:
main_algo(const unsigned& dims) except +
main_class getNext(Pclass& pr, const class2& d)
test.pyx
from header cimport main_class, class2, Pclass, main_algo
from libcpp.vector cimport vector
from libcpp.string cimport string
from libcpp.map cimport map
cdef extern from "<utility>":
vector[class2]&& move(vector[class2]&&)
main_class&& move(main_class&&)
cdef class main_class_2:
cdef main_class* thisptr
cdef main_class_3 evs
def __cinit__(self,main_class_3 evs):
self.evs = evs
self.thisptr = &evs.evs
cdef class main_class_3:
cdef main_class evs
cdef move_from(self, main_class&& move_this):
self.evs = move(move_this)
cdef class implAlgo:
cdef:
main_algo *_thisptr
def __cinit__(implAlgo self):
self._thisptr = NULL
def __init__(implAlgo self, unsigned dims):
self._thisptr = new main_algo(dims)
def __dealloc__(implAlgo self):
if self._thisptr != NULL:
del self._thisptr
cdef int _check_alive(implAlgo self) except -1:
if self._thisptr == NULL:
raise RuntimeError("Wrapped C++ object is deleted")
else:
return 0
cdef getNext(implAlgo self, Pclass& p, const class2& s):
self._check_alive()
cdef main_class evs = self._thisptr.getNext(p, sq)
retval = main_class_3()
retval.move_from(move(evs))
return retval
这里,main_algo 类实现了getNext() 方法,该方法返回一个main_class 类的对象。
从 test.pyx,我想将此对象返回到可以访问其值的纯 python 文件。
当我尝试编译上面的代码时,我得到了多个实例 在我使用该方法的多个地方出现以下错误,并且对于 ')' 或 '*' 等不同的标记,我得到了类似的错误。一些示例错误是:
sources.cpp:5121:70: error: expected primary-expression before ‘*’ token
__pyx_vtable_11Cython_test_7sources_main_class_3.move_from = (PyObject *(*)(struct __pyx_obj_11Cython_test_7sources_main_class_3 *, main_class &&))__pyx_f_11Cython_test_7sources_8main_class_3_move_from;
^
sources.cpp:5121:73: error: expected primary-expression before ‘)’ token
__pyx_vtable_11Cython_test_7sources_main_class_3.move_from = (PyObject *(*)(struct __pyx_obj_11Cython_test_7sources_main_class_3 *, main_class &&))__pyx_f_11Cython_test_7sources_8main_class_3_move_from;
^
sources.cpp:5121:75: error: expected primary-expression before ‘struct’
__pyx_vtable_11Cython_test_7sources_main_class_3.move_from = (PyObject *(*)(struct __pyx_obj_11Cython_test_7sources_main_class_3 *, main_class &&))__pyx_f_11Cython_test_7sources_8main_class_3_move_from;
^
sources.cpp:5121:133: error: expected primary-expression before ‘&&’ token
__pyx_vtable_11Cython_test_7sources_main_class_3.move_from = (PyObject *(*)(struct __pyx_obj_11Cython_test_7sources_main_class_3 *, main_class &&))__pyx_f_11Cython_test_7sources_8main_class_3_move_from;
但是所有这些标记都与我创建的用于将 C++ 对象移动到 python 的对象相关。任何其他声明都没有错误。
谁能帮我看看我哪里错了?
【问题讨论】:
-
您是否确保它在编译时使用的是 c++11 模式(或更高版本)。对于 gcc,您可以添加类似
extra_link_args=['-std=c++11']到setup.pystackoverflow.com/questions/1676384/… -
如果一个 cython 方法能够返回一个内存视图,那么就不会有复制(可能是这个question)
-
我搜索了
Cython/Includes/libcpp的内容,似乎没有std::move()在那里定义(cython 0.24.1)。