在 cython 中将 C++ 对象转换为 python 对象?

Posted

技术标签:

【中文标题】在 cython 中将 C++ 对象转换为 python 对象?【英文标题】:Converting C++ object to python object in cython? 【发布时间】:2017-06-10 00:40:45 【问题描述】:

我的第一个 cython 程序遇到了困难,所以如果我有一个愚蠢的问题,请不要气馁。

这是我的例子:

c_foo.h:

// c_foo.h
class foo:

    public:
        ....

        std::unique_ptr<2DVector> get_cFoo_unique_ptr(); // Vec2D<T> is a vector of vectors of T
                                                         // std::vector<std::vector<T>>

    private:
        std::unique_ptr<Vec2D> cFoo_unique_ptr; // Vec2D<T> is a vector of vectors of T

foo.pyx: # foo.pyx 进口赛通 ... # 其他导入 从 cython.operator cimport unique_ptr as cpp_unique_ptr

cdef extern from c_foo.h:
    cdef cppclass c_foo:
        ...

        cpp_unique_ptr get_cFoo_unique_ptr()


cdef class py_foo:
    cdef c_foo* cFoo

    ...

    def get_Vec2D(self):
        return self.cFoo.get_cFoo_unique_ptr().get()

所以,我在这里要做的是从 C++ unique_ptr 获取数据并在 python 中返回它们。 cython 抱怨它。

def get_Vec2D(self):
    return self.cFoo.get_cFoo_unique_ptr().get()
----------------------------------------------------------
 foo.pyx:xx:xx: Cannot convert 'T *' to Python object   

另一个尝试是我尝试其他方式来声明向量的 cython unique_ptr:

# foo.pyx
import cython
... # other import
from cython.memory cimport unique_ptr as cpp_unique_ptr
from cython.vector cimport vector as cpp_vector

cdef extern from c_foo.h:
    cdef cppclass c_foo:
        ...

        cpp_unique_ptr[cpp_vector[cpp_vector[T]]] get_cFoo_unique_ptr()


cdef class py_foo:
    cdef c_foo* cFoo

    ...

    def get_Vec2D(self):
        return self.cFoo.get_cFoo_unique_ptr().get()

还是同样的错误:

Cannot convert 'vector[vector[T]] *' to Python object

所以,我的问题是如何在 cython 中访问 C++ unique_ptr 的数据? 对于通过 cython 在 C++ 和 python 之间传递数据,我应该知道什么好的做法吗?

谢谢

【问题讨论】:

第二个选项靠近右边。如果 Cython 不知道 T 是什么,它应该如何将其转换为 Python 对象? 见question for a similar answer。 TL;DR - 您需要一个工厂类来将 C++ 类转换为 Python 对象以便返回。 Cython 会自动为内置类型执行此操作,但不能用于自定义结构或类。 【参考方案1】:

这种事情让我困惑了很久。我只在 C 环境中使用过 Cython,而不是 C++,所以我不知道您的案例中可能存在的其他选项。但我会解释我是如何做到的,希望对您有所帮助。

您必须在 Cython 函数的末尾创建 Python 对象,因为这些是唯一有效的返回值。这意味着,除其他外,您不能返回指针或 C 数组。例如,假设我有一个计算双精度数组的 Cython 函数 f:

def f():
    cdef double aa[1000]
    cdef int i
    # ....
    # some calculation that populates aa
    # ....
    # Now I can't just return aa because aa isn't a Python object.
    # I have to convert it to a Python list:
    a = []
    for i in range(1000):
        a.append(aa[i])  # Cython knows how convert one C float to one Python float
    return a

【讨论】:

以上是关于在 cython 中将 C++ 对象转换为 python 对象?的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Cython 中将大型 malloc 数组返回或保存为 Python 对象?

在 C++ 中将 bitset 转换为 int

Cython:将 C 结构转换为 pythons 对象会增加引用计数

Cython:如何使用 C++ 类的用户定义转换?

在 C++ 中将非 const 转换为 const

Cython 和 SIMD 内在函数:防止 SIMD 内在函数的参数转换为 python 对象