Cette question est au sujet de la façon de passer d'un objet C++ une fonction python qui est appelée dans un (C++) interpréteur Python embarqué.
Le C++ suivant (de la classe Maclasse.h) est conçu pour tester:
#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 module python, l'exposition de la classe C++, peut être généré par le texte suivant Rasade fichier d'interface:
%module passmetopython
%{ #include "MyClass.h" %}
%include "std_string.i"
//Expose to Python
%include "MyClass.h"
Ci-dessous est un script Python à l'aide du module 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()
Cette question est de savoir comment tirer le python execute() de la fonction de travail, lorsqu'il est appelé à partir de c++, avec un objet C++ comme un argument.
Le C++ suivant le programme a été écrit pour tester les fonctions (montant minimum de vérification des erreurs):
#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;
}
Lors de l'exécution du code ci-dessus, le execute() fonction python, avec un MyClass objet comme argument, échoue et renvoie la valeur NULL. Cependant, la fonction Python est entré, que je puisse voir la sortie (Entrant en fonction execute) dans la console de sortie, indiquant que l'objet passé n'est pas, en effet, un valide MyClass objet.
Il y a beaucoup d'exemples sur la façon de passer d'un type simple, comme les entiers, doubles ou chaîne types de Python, C/C++. Mais il y a très peu d'exemple montrant comment passer un C/C++ objet/ pointeur, ce qui est un peu déroutant.
Le code ci-dessus, avec un fichier CMake, peut être vérifié à partir de github: https://github.com/TotteKarlsson/miniprojects/tree/master/passMeToPython
Ce code est de ne pas utiliser le boost de python ou d'autres API. Cython semble intéressant, et si elle peut être utilisée pour simplifier sur le C++ côté, il pourrait être acceptable.