Seite 1 von 1

variable Python-Funktion über C API aufrufen

Verfasst: Sonntag 19. Februar 2006, 17:54
von Jannik
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!

Verfasst: Montag 20. Februar 2006, 23:32
von Joghurt
Schau dir mal SWIG oder Boost.Python an.