cup python c++ swig

python - swig cup



Pasando un objeto C++ a Python (2)

Esta es una respuesta parcial a mi propia pregunta. Lo digo parcial, porque creo que hay una mejor manera.

Sobre la base de esta publicación http://swig.10945.n7.nabble.com/Pass-a-Swig-wrapped-C-class-to-embedded-Python-code-td8812.html Generé el encabezado de tiempo de ejecución de swig, como se describe Aquí, la sección 15.4: http://www.swig.org/Doc2.0/Modules.html#Modules_external_run_time

Incluyendo el encabezado generado en el código C ++ anterior, permita que se escriba el siguiente código:

PyObject* pObj = SWIG_NewPointerObj((void*)&obj, SWIG_TypeQuery("_p_MyClass"), 0 );

Este código utiliza información de los archivos de origen de Swig python wrap, a saber, el nombre "swig" del tipo MyClass, es decir, _p_MyClass .

Con el PyObject * anterior como un argumento a la función PyObject_CallObject, la función execute () de python en el código anterior se ejecuta correctamente, y el código de Python, que utiliza el módulo python generado, tiene acceso adecuado a los datos internos de los objetos MyClass. Esto es genial.

Aunque el código anterior ilustra cómo pasar y recuperar datos entre C ++ y Python de una manera bastante simple, no es lo ideal, en mi opinión.

El uso del archivo de encabezado de swig en el código de C ++ no es realmente tan bonito, y además, requiere que el usuario examine "manualmente" el código de envoltorio generado por swig para encontrar el código "_p_MyClass".

¿¡Debe haber una mejor manera!? ¿Tal vez debería agregarse algo al archivo de interfaz swig para que esto se vea mejor?

Esta pregunta trata sobre cómo pasar un objeto C ++ a una función de Python que se llama en un intérprete de Python integrado (C ++) .

La siguiente clase de C ++ (MyClass.h) está diseñada para pruebas:

#ifndef MyClassH #define MyClassH #include <string> using std::string; class MyClass { public: MyClass(const string& lbl): label(lbl) {} ~MyClass(){} string getLabel() {return label;} private: string label; }; #endif

Un módulo de Python, que expone la clase C ++, puede ser generado por el siguiente archivo de interfaz Swig:

%module passmetopython %{ #include "MyClass.h" %} %include "std_string.i" //Expose to Python %include "MyClass.h"

A continuación se muestra una secuencia de comandos de Python que utiliza el módulo de Python

import passmetopython as pmtp def execute(obj): #This function is to be called from C/C++, with a #MyClass object as an argument print ("Entering execute function") lbl = obj.getLabel(); print ("Printing from within python execute function. Object label is: " + lbl) return True def main(): c = pmtp.MyClass("Test 1") retValue = execute(c) print("Return value: " + str(retValue)) #Test function from within python if __name__ == ''__main__'': main()

Esta pregunta es sobre cómo hacer que funcione la función python execute () , cuando se llama desde c ++, con un objeto C ++ como argumento.

El siguiente programa de C ++ se escribió para probar las funciones (cantidad mínima de comprobación de errores):

#include "Python.h" #include <iostream> #include <sstream> #include "MyClass.h" using namespace std; int main() { MyClass obj("In C++"); cout << "Object label: /"" << obj.getLabel() << "/"" << endl; //Setup the Python interpreter and eventually call the execute function in the //demo python script Py_Initialize(); //Load python Demo script, "passmetopythonDemo.py" string PyModule("passmetopythonDemo"); PyObject* pm = PyUnicode_DecodeFSDefault(PyModule.c_str()); PyRun_SimpleString("import sys"); stringstream cmd; cmd << "sys.path.append(/"" << "." << "/")"; PyRun_SimpleString(cmd.str().c_str()); PyObject* PyModuleP = PyImport_Import(pm); Py_DECREF(pm); //Now create PyObjects for the Python functions that we want to call PyObject* pFunc = PyObject_GetAttrString(PyModuleP, "execute"); if(pFunc) { //Setup argument PyObject* pArgs = PyTuple_New(1); //Construct a PyObject* from long PyObject* pObj(NULL); /* My current attempt to create avalid argument to Python */ pObj = PyLong_FromLong((long) &obj); PyTuple_SetItem(pArgs, 0, pObj); /***** Calling python here *****/ cout<<endl<<"Calling function with an MyClass argument/n/n"; PyObject* res = PyObject_CallObject(pFunc, pArgs); if(!res) { cerr << "Failed calling function.."; } } return 0; }

Cuando se ejecuta el código anterior, la función de python execute () , con un objeto MyClass como argumento, falla y devuelve NULL. Sin embargo, la función Python se ingresa, ya que puedo ver la salida ( Entrando en la función de ejecución ) en la salida de la consola, lo que indica que el objeto que se aprobó no es, de hecho , un objeto MyClass válido.

Hay muchos ejemplos sobre cómo pasar tipos simples, como ints, dobles o tipos de cadenas a Python desde C / C ++. Pero hay muy pocos ejemplos que muestran cómo pasar un objeto / puntero C / C ++, lo cual es un tanto desconcertante.

El código anterior, con un archivo CMake, se puede consultar en github: https://github.com/TotteKarlsson/miniprojects/tree/master/passMeToPython

Este código no debe usar ningún impulso de python u otra API. Sin embargo, Cython parece interesante, y si se puede usar para simplificar en el lado de C ++, podría ser aceptable.


PyObject *pValue; pValue = PyObject_CallMethod(pInstance, "add","(i)",x); if (pValue) Py_DECREF(pValue); else PyErr_Print();