Cython:如何包装一个返回C++对象的C++函数?

MCo*_*Cor 5 c++ python wrapper cython

我正在开发一个Python项目,我希望与已编写的C++包接口.由于我将在本项目的其他部分使用Cython,我更喜欢使用Cython进行换行.

简而言之,我需要包装一个返回自定义类型Bar对象的函数FooBar.

这是Bar.h:

#include <cstddef> // For size_t
#include <vector>

/* data returned by function FooBar()*/
class Bar {
public:
    size_t X;
    std::vector<size_t> Y;      
    std::vector<double> Z;  
    std::vector<double> M;  
    std::vector<size_t> N;  

};


Bar FooBar(const std::vector<double> & O, size_t P, size_t Q);
Run Code Online (Sandbox Code Playgroud)

和PyBar.pyx:

from libcpp.vector cimport vector

cdef extern from "Bar.h":
    cdef cppclass Bar:
        size_t X
        vector[size_t] Y    
        vector[double] Z    
        vector[double] M 
        vector[size_t] N    
    cdef Bar FooBar(const vector[double] & O, size_t P, size_t Q)

cdef class PyBar:
    cdef Bar *thisptr      # hold a C++ instance which we're wrapping

    def __cinit__(self, O, P, Q):
        C_Bar = FooBar(O, P, Q)
        self.thisptr = &C_Bar

    def __dealloc__(self):
        del self.thisptr
Run Code Online (Sandbox Code Playgroud)

实际问题:这是否是我想要做的正确方法?作为参考,如果我只是试图自己包装类我没有问题:我可以导入模块,使用PyBar()创建对象,并且在类上实现的底层C方法可以工作.问题是尝试包装一个返回C++类对象的函数.在野外,我实际上永远不会想要创建任何不是由FooBar创建的Bar对象的PyBar表示,所以这是我经过多次努力之后决定的方法.

Dav*_*idW 4

关于问题的第一部分,我认为更优雅的更改是将 FooBar 定义为:

Bar* FooBar(const std::vector<double> & O, size_t P, size_t Q);
Run Code Online (Sandbox Code Playgroud)

并让它返回一个“新”分配的指针。我认为在您最初的 Cython 代码中,__cinit__您将创建一个堆栈分配的 Bar,获取其指针,然后该指针将过期,导致最终的灾难。

另一种可能有效的解决方案是让 FooBar 返回 Bar,更改 PyBar 以便它启动

cdef class PyBar:
   cdef Bar this_obj

   def __cinit__(self, O, P, Q):
      self.this_obj = FooBar(O,P,Q)
Run Code Online (Sandbox Code Playgroud)

即保留一个对象而不是指针。没有__dealloc__必要。

我不知道未定义的符号错误......