7

有人可以建议一种使用 Cython 操作 c++ 对象的方法,当一个类的 c++ 实例预计将提供另一个包装类的构造函数时,如下所述?

请查看 PySession 类的 pyx 文件上的注释,该类将 python PyConfigParams 对象作为参数,然后需要从中提取值以构造 c++ ConfigParams 对象。然后使用 ConfigParams 对象来提供 Session 的构造函数。

最好有一个过程,它允许我将 PyConfigParams 对象包装的 ConfigParams c++ 对象直接“注入”到 Session 的构造函数中,而不必先拆除它,然后再构建一个新的 c++ 对象来提供构造函数。这当然有效。然而,实现这个解决方案是一种繁琐、残酷的方式,更不用说不可靠了。

我知道 PyCapsule,但是它可能需要触摸 c++ 标头,这是我无法做到的。

与此相关,但另一个问题是:如果我需要一个包装类(我们在这里说 PySession)通过返回一个 ConfigParams 实例来模拟 C++ api 的行为怎么办?我是否需要反向操作并拆除 c++ 对象来构建 Python PyConfigParams,然后将其返回给 Python 世界中的 Python 用户?非常欢迎任何建议!谢谢!

假设我有两个名为 ConfigParams 和 Session 的 C++ 类。ConfigParams 的一个实例用于提供 Session 类的构造函数:

C++ 类

ConfigParams 类

// ConfigParams.h
#include <iostream> 
using namespace std; 
class ConfigParams 
{ 
  int parameter1; 
 public: 
  ConfigParams(int par1) { this->parameter1 = par1;} 
  int getPar1() { return this->parameter1; } 
};

会话类

// Session.h 
#include <iostream> 
using namespace std; 
#include "configparams.h" 
class Session 
{ 
  int sessionX; 
 public: 
  Session(ConfigParams parameters) { this->sessionX = parameters.getPar1(); } 
  void doSomething(); 
}; 

void Session::doSomething() 
{ 
  cout << "Session parameters set as: " << endl; 
  cout << "X = " << this->sessionX << endl; 
} 

上述类的 Cython pyx 和 pxd 文件:

PyConfigParams

# configparams.pxd 
cdef extern from "configparams.h": 
    cppclass ConfigParams: 
        ConfigParams(int par1) 
        int getPar1() 

# configparams.pyx 
cdef class PyConfigParams: 
    cdef ConfigParams* thisptr 
    def __cinit__(self, i): 
        self.thisptr = new ConfigParams(<int> i) 
    def getPar1(self): 
        return self.thisptr.getPar1() 

PySession 类

# session.pxd 
from configparams cimport * 
cdef extern from "session.h": 
    cdef cppclass Session: 
        Session(ConfigParams parameters) 
        void doSomething() 

# session.pyx
cdef class PySession: 
    cdef Session* thisptr 
    def __cinit__(self, pars): 
        # Note that here I have to extract the values 
        # from the pars (python PyConfigParams object) 
        # in order to build a c++ ConfigParams object 
        # which feeds the c ++ constructor of Session. 
        cdef ConfigParams* cpppargsptr = new ConfigParams(<int> pars.getPar1()) 
        self.thisptr = new Session(cpppargsptr[0]) 
    def doSomething(self): 
        self.thisptr.doSomething() 
4

1 回答 1

6

解决方案:

在 configparams.pxd 模块中前向声明 PyConfigParams(因此可以从 session.pyx 模块调用)

# configparams.pxd                                                                                                                                                                                                                                            
cdef extern from "configparams.h":
    cppclass ConfigParams:
        ConfigParams(int par1)
        int getPar1()

cdef class PyConfigParams:
    cdef ConfigParams* thisptr

在 session.pyx 模块中导入 PyConfigParams,并为构造函数转换参数,这将授予对指向 c++ 对象的 PyConfigParams 指针的访问权限,该指针需要被取消引用。

# session.pyx                                                                                                                                                                                                                                                 
from configparams cimport PyConfigParams
from cython.operator cimport dereference as deref

cdef class PySession:
    cdef Session* thisptr
    def __cinit__(self, PyConfigParams pars):
        self.thisptr = new Session(deref(pars.thisptr))
    def doSomething(self):
        self.thisptr.doSomething()
于 2012-05-22T18:15:58.753 回答