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:
// 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;
}
# 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()
# 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()
Cython is a programming language that blends Python with the static type system of C and C++. cython is a compiler that translates Cython source code into efficient C or C++ source code. This source can then be compiled into a Python extension module or a standalone executable.
Cython has native support for most of the C++ language. Specifically: C++ objects can be dynamically allocated with new and del keywords. C++ objects can be stack-allocated.
[Cython] is a programming language that makes writing C extensions for the Python language as easy as Python itself. It aims to become a superset of the [Python] language which gives it high-level, object-oriented, functional, and dynamic programming.
Cython is a compiled language that is typically used to generate CPython extension modules.
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()
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With