Il y a deux parties à cette réponse. D'abord, vous devez exposer votre interface en Python d'une manière qui permet implémentations de Python pour remplacer les pièces de à volonté. Ensuite, vous devez montrer votre programme C++ (en main
comment appeler Python.
Exposer l'interface existante pour Python:
La première partie est assez facile à faire avec SWIG. J'ai modifié votre exemple de scénario légèrement pour corriger quelques problèmes et a ajouté une fonction supplémentaire pour les tests:
// myif.h
class myif {
public:
virtual float myfunc(float a) = 0;
};
inline void runCode(myif *inst) {
std::cout << inst->myfunc(5) << std::endl;
}
Pour l'instant, je vais regarder le problème sans l'incorporation de Python dans votre application, c'est à dire de commencer excetion en Python, et non pas en int main()
en C++. Il est relativement simple d'ajouter que, plus tard bien que.
La première est l'obtention de la croix de langue polymorphisme de travail:
%module(directors="1") module
// We need to include myif.h in the SWIG generated C++ file
%{
#include <iostream>
#include "myif.h"
%}
// Enable cross-language polymorphism in the SWIG wrapper.
// It's pretty slow so not enable by default
%feature("director") myif;
// Tell swig to wrap everything in myif.h
%include "myif.h"
Pour ce faire, nous avons activé RASADE de directeur de la fonctionnalité à l'échelle mondiale et en particulier pour notre interface. Le reste est assez standard RASADE bien.
J'ai écrit un test Python de mise en œuvre:
import module
class MyCl(module.myif):
def __init__(self):
module.myif.__init__(self)
def myfunc(self,a):
return a*2.0
cl = MyCl()
print cl.myfunc(100.0)
module.runCode(cl)
Avec qui j'étais alors en mesure de compiler et d'exécuter ceci:
swig -python -c++ -Wall myif.j'
g++ -Wall-Wextra -shared-o _module.donc myif_wrap.cxx -I/usr/include/python2.7 -lpython2.7
python mycl.py
200.0
10
Exactement ce que vous espérer de voir à partir de ce test.
L'incorporation de l'Python dans l'application:
Ensuite, nous avons besoin de mettre en œuvre un réel version de votre mymain.cc. J'ai mis en place une esquisse de ce à quoi il pourrait ressembler:
#include <iostream>
#include "myif.h"
#include <Python.h>
int main()
{
Py_Initialize();
const double input = 5.0;
PyObject *main = PyImport_AddModule("__main__");
PyObject *dict = PyModule_GetDict(main);
PySys_SetPath(".");
PyObject *module = PyImport_Import(PyString_FromString("mycl"));
PyModule_AddObject(main, "mycl", module);
PyObject *instance = PyRun_String("mycl.MyCl()", Py_eval_input, dict, dict);
PyObject *result = PyObject_CallMethod(instance, "myfunc", (char *)"(O)" ,PyFloat_FromDouble(input));
PyObject *error = PyErr_Occurred();
if (error) {
std::cerr << "Error occured in PyRun_String" << std::endl;
PyErr_Print();
}
double ret = PyFloat_AsDouble(result);
std::cout << ret << std::endl;
Py_Finalize();
return 0;
}
Il est fondamentalement juste norme intégration de Python dans une autre application. Il fonctionne et donne exactement ce que vous espérer voir aussi:
g++ -Wall-Wextra -I/usr/include/python2.7 main.cc -o -lpython2.7
./principal
200.0
10
10
La dernière pièce du puzzle est en mesure de convertir l' PyObject*
que vous obtenez à partir de la création de l'instance en Python en myif *
. GORGÉE de nouveau fait ce assez simple.
Nous avons d'abord besoin de demander GORGÉE d'exposer son exécution dans un headerfile pour nous. Nous faisons cela avec un appel supplémentaire à RASADE:
swig -Wall-c++ -python -externe-runtime runtime.h
Ensuite, nous avons besoin de re-compiler nos RASADE module, donnant explicitement la table des types de SWIG sait à propos d'un nom afin que nous puissions le regarder de l'intérieur de notre main.cc. Nous recompiler le .donc, en utilisant:
g++ -DSWIG_TYPE_TABLE=myif -Wall-Wextra -shared-o _module.donc myif_wrap.cxx -I/usr/include/python2.7 -lpython2.7
Ensuite, nous ajoutons une fonction d'aide pour la conversion de l' PyObject*
de myif*
dans notre main.cc:
#include "runtime.h"
// runtime.h was generated by SWIG for us with the second call we made
myif *python2interface(PyObject *obj) {
void *argp1 = 0;
swig_type_info * pTypeInfo = SWIG_TypeQuery("myif *");
const int res = SWIG_ConvertPtr(obj, &argp1,pTypeInfo, 0);
if (!SWIG_IsOK(res)) {
abort();
}
return reinterpret_cast<myif*>(argp1);
}
Maintenant, c'est en place, on peut l'utiliser à partir d' main()
:
int main()
{
Py_Initialize();
const double input = 5.5;
PySys_SetPath(".");
PyObject *module = PyImport_ImportModule("mycl");
PyObject *cls = PyObject_GetAttrString(module, "MyCl");
PyObject *instance = PyObject_CallFunctionObjArgs(cls, NULL);
myif *inst = python2interface(instance);
std::cout << inst->myfunc(input) << std::endl;
Py_XDECREF(instance);
Py_XDECREF(cls);
Py_Finalize();
return 0;
}
Enfin, nous avons pour compiler main.cc avec -DSWIG_TYPE_TABLE=myif
, ce qui donne:
./principal
11