Cython和c ++类构造函数 [英] Cython and c++ class constructors

查看:156
本文介绍了Cython和c ++类构造函数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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



请参考PySession类的注释,其中
使用python PyConfigParams对象作为参数,然后需要
提取值,以便构造一个c ++ ConfigParams
对象。然后使用ConfigParams对象来提供Session的构造函数



这将是理想的有一个程序,这将允许我注入
ConfigParams c ++对象包装的PyConfigParams对象
直接Session的构造函数,而不必先拆卸
,然后构建一个新的c ++对象来构造函数。
这当然是。然而,实施这个解决方案是一种麻烦,粗暴的方式,更不用说不可靠。



我知道PyCapsule,但它可能需要触摸c ++标题,这是我不能做的。


$ b $与此相关,但一个不同的问题是:如果我需要一个封装的
类(这里说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;
#includeconfigparams.h
class Session
{
int sessionX;
public:
Session(ConfigParams parameters){this-> sessionX = parameters.getPar1(); }
void doSomething();
};

void Session :: doSomething()
{
cout< 会话参数设置为:< endl;
cout<< X =<< this-> sessionX< endl;
}



上述类的Cython pyx和pxd文件:



PyConfigParams



 #configparams.pxd 
cdef extern fromconfigparams.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 b $ b return self.thisptr.getPar1()



PySession类



 #session.pxd 
来自configparams cimport *
cdef extern fromsession.h:
cdef cppclass Session:
Session(ConfigParams parameters)
void doSomething()

#session.pyx
cdef class PySession:
cdef Session *注意,这里我必须从pars(python PyConfigParams对象)
#中提取值
#,以构建一个c ++ ConfigParams对象
#,它提供了Session的c ++构造函数。
cdef ConfigParams * cpppargsptr = new ConfigParams(< int> pars.getPar1())
self.thisptr = new Session(cpppargsptr [0])
def doSomething $ b self.thisptr.doSomething()


解决方案



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

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

cdef class PyConfigParams:
cdef ConfigParams * thisptr

在session.pyx模块中导入PyConfigParams,并为constuctor转换参数,这将允许访问PyConfigParams指向c ++对象的指针,这需要被解引用。

 #session.pyx 
来自configparams cimport PyConfigParams
来自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()


Can someone suggest a way to manipulate c++ objects with Cython, when the c++ instance of one class is expected to feed the constructor of another wrapped class as described below?

Please look at the note on the pyx file for the class PySession, which takes a python PyConfigParams object as argument and then needs to extract values from it in order to construct a c++ ConfigParams object. the ConfigParams object is then used to feed the constructor of Session.

It would be ideal to have a procedure which would allow me to "inject" the ConfigParams c++ object wrapped by the PyConfigParams object directly into the constructor of Session, without having to dismantle it first and then building a new c++ object to feed the constructor. This works, of course. However, it is a cumbersome, sort of brutal way to implement this solution, not to mention unreliable.

I am aware of PyCapsule, however it may require to touch the c++ headers, which is something I can not do.

Related to this, but a different question is: what if I need a wrapped class (let's say here PySession) to simulate the behavior of the C++ api by returning a ConfigParams instance? would I need to do the reverse and dismantle the c++ object to build a Python PyConfigParams which would then be returned to the Python user in the Python world? Any suggestions are very welcome! Thank you!

Let's suppose I have two c++ classes named ConfigParams and Session. An instance of ConfigParams is used to feed the constructor of the Session class:

C++ classes

ConfigParams class

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

Session class

// 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 and pxd files for the above classes:

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 class

# 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() 

解决方案

Solution:

Forward declare PyConfigParams in the configparams.pxd module (so it can be invoked from the session.pyx module)

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

cdef class PyConfigParams:
    cdef ConfigParams* thisptr

Import PyConfigParams in the session.pyx module, and cast the argument for the constuctor, this will grant access to the PyConfigParams pointer to the c++ object, which will need to be dereferenced.

# 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()

这篇关于Cython和c ++类构造函数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆