Cython and c++ class constructors

2024/10/3 23:21:38

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

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 derefcdef class PySession:cdef Session* thisptrdef __cinit__(self, PyConfigParams pars):self.thisptr = new Session(deref(pars.thisptr))def doSomething(self):self.thisptr.doSomething()
https://en.xdnf.cn/q/70673.html

Related Q&A

How to share state when using concurrent futures

I am aware using the traditional multiprocessing library I can declare a value and share the state between processes. https://docs.python.org/3/library/multiprocessing.html?highlight=multiprocessing#s…

Does IronPython implement python standard library?

I tried IronPython some time ago and it seemed that it implements only python language, and uses .NET for libraries. Is this still the case? Can one use python modules from IronPython?

finding the last occurrence of an item in a list python

I wish to find the last occurrence of an item x in sequence s, or to return None if there is none and the position of the first item is equal to 0This is what I currently have:def PositionLast (x,s):co…

pandas cut a series with nan values

I would like to apply the pandas cut function to a series that includes NaNs. The desired behavior is that it buckets the non-NaN elements and returns NaN for the NaN-elements.import pandas as pd numbe…

Using Selenium with PyCharm CE

Im trying to use Selenium with PyCharm CE. I have installed Selenium using pip install Selenium and Im able to use it via the terminal however when I try to use it with PyCharm I get an import error Im…

Reusing generator expressions

Generator expressions is an extremely useful tool, and has a huge advantage over list comprehensions, which is the fact that it does not allocate memory for a new array.The problem I am facing with gen…

ModuleNotFoundError: No module named librosa

Currently I am working on voice recognition where I wanted to use Librosa library. I install librosa with the command on ubuntu: conda install -c conda-forge librosaBut when I run the code I got the fo…

Python - Convert Very Large (6.4GB) XML files to JSON

Essentially, I have a 6.4GB XML file that Id like to convert to JSON then save it to disk. Im currently running OSX 10.8.4 with an i7 2700k and 16GBs of ram, and running Python 64bit (double checked). …

Python create tree from a JSON file

Lets say that we have the following JSON file. For the sake of the example its emulated by a string. The string is the input and a Tree object should be the output. Ill be using the graphical notation …

disable `functools.lru_cache` from inside function

I want to have a function that can use functools.lru_cache, but not by default. I am looking for a way to use a function parameter that can be used to disable the lru_cache. Currently, I have a two ver…