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.

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);
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!