variable Python-Funktion über C API aufrufen

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
Jannik
User
Beiträge: 1
Registriert: Sonntag 19. Februar 2006, 17:17

Hallo!

Verwunderlicherweise habe ich kein Unterforum zum Thema Python/C API gefunden, drum versuch ichs mal hier:

Ich möchte von meinem C++-Programm aus variablen (vom Benutzer zur Laufzeit eingegebenen) Python-Code ausführen, genauer eine Funktion, und den return-Wert wieder in C++ weiterbenutzen.

Ich halte diesen Wunsch nicht für sehr außergewöhnlich, allerdings scheint die C API dafür keine simple Lösung zu bieten. :cry:

Inzwischen habe ich mir Folgendes zusammengebastelt:

Code: Alles auswählen

CString strOut = "";
Py_Initialize();
PyObject* mainModObj;
PyObject* mainDictObj;
PyObject* pFunc;
PyObject* pValue;
PyObject* pArgs;
mainModObj = PyImport_AddModule("__main__");
if (mainModObj == NULL)
{
     return "error";
}
mainDictObj = PyModule_GetDict(mainModObj);
// der folgende übergebene String soll variabel sein, hier nur ein Beispiel
PyRun_SimpleString("def myfunc():\n a=3\n b=4\n return str(a+b)");
pFunc = PyObject_GetAttrString(mainModObj, "myfunc");
if (pFunc && PyCallable_Check(pFunc))
{
     pArgs = PyTuple_New(0);
     pValue = PyObject_CallObject(pFunc, pArgs);
     if (pValue != NULL)
     {
          // String
          if (PyString_Check(pValue)) strOut.Format("%s", PyString_AsString(pValue));
          // Integer
          if (PyInt_Check(pValue)) strOut.Format("%i", PyInt_AsLong(pValue));
          // Float
          if (PyFloat_Check(pValue)) strOut.Format("%f", PyFloat_AsDouble(pValue));
     }
     Py_XDECREF(pValue);
     Py_DECREF(pArgs);
}
Py_XDECREF(pFunc);
Py_Finalize();
return(strOut);
Jetzt die Fragen:
1. Lässt sich die Aufgabe vielleicht einfacher/eleganter lösen?
2. Ist der C API-Code einigermaßen richtig (besonders die Py_(X)DECREFs)?
3. Wäre es schädlich, den mittleren Teil (also die Funktionsdefinition und Auswertung) mehrmals auszuführen, also myfunc ständig zu überschreiben, oder führt das zu einem Speicherleck? (jedesmal Py_Initialize und Py_Finalize auszuführen ist mir eigentlich zu aufwändig ...)
4. Mein zur Zeit größtes Problem: Wenn die benutzerdefinierte Funktion einen Fehler enthält, erzeugt Py_Finalize einen Crash. (pFunc && PyCallable_Check(pFunc)) ist dann true und pValue == NULL. Wo und wie kann ich diesen Fehler vorher abfangen?

Vielen Dank für Eure Antworten!
Joghurt
User
Beiträge: 877
Registriert: Dienstag 15. Februar 2005, 15:07

Schau dir mal SWIG oder Boost.Python an.
Antworten