我正在尝试使用 Cython 将 C++ 库包装到 python API 中。我想要包装的类具有以下模板:
template<typename Value>
class ClassToWrap
{
public:
typedef std::shared_ptr<std::vector<Value> > TypeToWrap;
ClassToWrap(TypeToWrap data)
{
}
}
我对 C++ 标准库没有信心。如何将 TypeToWrap 包装在 Cython 中,使其能够以简单的方式(例如数组或多维数组)进行初始化,例如使用 for 赋值循环?感谢您的任何建议。
最佳答案
假设您有一个 C++ header ,如下所示:
// cpp_class.h
#include <memory>
#include <vector>
template<typename Value>
class ClassToWrap
{
public:
typedef std::shared_ptr<std::vector<Value> > TypeToWrap;
ClassToWrap(TypeToWrap data) : obj(std::move(data))
{
}
private:
TypeToWrap obj;
};
您需要将此类公开给 cython,这是由 cython wrapping Cpp 中的 cdef extern
完成的文档。
# my_cy_class.pyx
# distutils: language = c++
from libcpp.memory cimport make_shared, shared_ptr
from libcpp.vector cimport vector
cdef extern from "cpp_class.h" nogil:
cdef cppclass ClassToWrap[T]:
ctypedef shared_ptr[vector[T]] TypeToWrap
ClassToWrap(TypeToWrap)
# define anything you intend to use
请注意,您只需要定义函数,而不需要它们的实现。
其次,让我们定义一个 cython 类来包装它并将其暴露给 python,因为 python 要使用它,所以它需要知道 T
的类型,我们假设它是一个 int
:
from cython.operator cimport dereference as deref
from libcpp.utility cimport move
cdef class wrapper_class:
cdef ClassToWrap[int]* wrapped_obj # needs to be a defined type and heap allocated
def __cinit__(self, some_list):
cdef vector[int] v = some_list
cdef ClassToWrap[int].TypeToWrap ptr = make_shared[vector[int]](move(v))
self.wrapped_obj = new ClassToWrap[int](move(ptr))
# deref(self.wrapped_obj).foo()
def __dealloc__(self):
del self.wrapped_obj
您可能想知道为什么使用指向对象的指针?原因是因为您的对象没有默认的零参数构造函数,并且 cython 需要一个默认的零参数构造函数才能使用 __cinit__ 和 __dealloc__ 保证对其进行堆栈分配没有内存泄漏
注意,some_list
不需要是一个python列表,它可以很容易地是一个numpy数组,并且事先知道类型可以帮助编译器优化它的代码,以下代码可以测试一下。
import pyximport
script_args = ["--cython-cplus"]
setup_args = {
"script_args": script_args,
"include_dirs": ['.'],
}
pyximport.install(setup_args=setup_args, language_level=3,)
import numpy as np
import my_cy_class
inputs = np.array([1,2,3,4,5])
a = my_cy_class.wrapper_class(inputs)
关于c++ - 如何在 Cython 中包装来自 C++ 的 std::shared_ptr 和 std::vector ?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/75626349/