Constructores de clase Cython y c++

¿Alguien puede sugerir una forma de manipular objetos de C++ con Cython, cuando se espera que la instancia de C++ de una clase alimente al constructor de otra clase envuelta como se describe a continuación?

Mire la nota en el archivo pyx para la clase PySession, que toma un objeto python PyConfigParams como argumento y luego necesita extraer valores de él para construir un objeto C++ ConfigParams. el objeto ConfigParams luego se usa para alimentar al constructor de Session.

Sería ideal tener un procedimiento que me permitiera "inyectar" el objeto ConfigParams c ++ envuelto por el objeto PyConfigParams directamente en el constructor de Session, sin tener que desmantelarlo primero y luego construir un nuevo objeto C ++ para alimentar el constructor. Esto funciona, por supuesto. Sin embargo, es una forma engorrosa y brutal de implementar esta solución, sin mencionar que no es confiable.

Conozco PyCapsule, sin embargo, es posible que deba tocar los encabezados de c ++, que es algo que no puedo hacer.

Relacionado con esto, pero una pregunta diferente es: ¿qué pasa si necesito una clase envuelta (digamos aquí PySession) para simular el comportamiento de la API de C++ al devolver una instancia de ConfigParams? ¿Tendría que hacer lo contrario y desmantelar el objeto c ++ para construir un PyConfigParams de Python que luego se devolvería al usuario de Python en el mundo de Python? ¡Cualquier sugerencia es muy bienvenida! ¡Gracias!

Supongamos que tengo dos clases de C++ llamadas ConfigParams y Session. Se usa una instancia de ConfigParams para alimentar al constructor de la clase Session:

Clases de C ++

clase ConfigParams

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

Clase de sesión

// 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; 
} 

Archivos Cython pyx y pxd para las clases anteriores:

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

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

preguntado el 03 de mayo de 12 a las 18:05

1 Respuestas

Solución:

Reenviar declarar PyConfigParams en el módulo configparams.pxd (para que pueda invocarse desde el módulo session.pyx)

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

cdef class PyConfigParams:
    cdef ConfigParams* thisptr

Importe PyConfigParams en el módulo session.pyx y emita el argumento para el constructor, esto otorgará acceso al puntero de PyConfigParams al objeto C++, que deberá ser desreferenciado.

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

contestado el 22 de mayo de 12 a las 19:05

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.