Embedded Python Variablen an C zurückgeben

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
Lufia
User
Beiträge: 83
Registriert: Samstag 13. Mai 2006, 10:04
Wohnort: Berlin

Hallo, ich komme mal wieder nicht weiter :(
ich rufe Python von C aus auf und und übergebe dabei eine Liste von Variablen.
Bei der Übergabe bekommt Python ein tuple in dem die Liste steckt.

Nun würde ich von Python gerne nicht nur eine Variable zurück geben sondern am liebsten eine Liste. In allen Beispielen die ich gefunden habe werden immer nur einzelne Variablen zurückgegeben.

Geht es ein Objekt von Python über return zurückzugeben und dann im C-Programm in C-Datentypen umzuwandeln ? Auf die an Python im Tupel übergebenen Variablen zu schreiben geht ja leider nicht.


Danke

C - Code

Code: Alles auswählen

int pythonflow(double time)
{
 
    PyObject *pName, *pModule, *pDict, *pFunc;
    PyObject *pArgs, *pValue, *pList;
    int i,test;
    char modul[] = "multi";
    char funkname[] = "multi";
    char progname[]= "multi";
    const char *p_modul = modul;
    const char *p_funkt = funkname;
    const char *p_name = progname;    
    
    // Initialisierung
    Py_Initialize();
    
    // damit python im richtigen verzecihniss sucht
    PyRun_SimpleString("import sys");
    PyRun_SimpleString("sys.path.insert(0, '')");
    

    //***************************************************************/

    
    pName = PyString_FromString("multi");
    /* Error checking of pName left out */

    pModule = PyImport_Import(pName);
    Py_DECREF(pName);

    if (pModule != NULL) {
        pFunc = PyObject_GetAttrString(pModule,"multi");
                
        /* pFunc is a new reference */
        pArgs = PyTuple_New(1);

        if (pFunc && PyCallable_Check(pFunc)) {
            pList = PyList_New(23);
            for (i = 0; i <23 ; ++i) {
                pValue = PyFloat_FromDouble(pw_list[i]);
                if (!pValue) {
                    Py_DECREF(pArgs);
                    Py_DECREF(pModule);
                    fprintf(stderr, "Cannot convert argument\n");
                    return 1;
                }
                /* pValue reference stolen here: */
                PyList_SetItem(pList, i, pValue);
            }
            PyTuple_SetItem(pArgs, 0, pList);
            pValue = PyObject_CallObject(pFunc, pArgs);

            
                
            Py_DECREF(pArgs);
            if (pValue != NULL) {
                printf("Result of call: %f \n", PyFloat_AsDouble(pValue));
                Py_DECREF(pValue);
                Py_DECREF(pList);
            }
            else {
                Py_DECREF(pFunc);
                Py_DECREF(pModule);
                PyErr_Print();
                fprintf(stderr,"Call failed\n");
                return 1;
            }
        }
        else {
            if (PyErr_Occurred())
                PyErr_Print();
            fprintf(stderr, "Cannot find function ");
        }
        Py_XDECREF(pFunc);
        Py_DECREF(pModule);
    }
    else {
        PyErr_Print();
        fprintf(stderr, "Failed to load ");
        return 1;
    }
    Py_Finalize();
    
    return 0;
}

Python-Code

Code: Alles auswählen

def multi(list):
    
    print list
    print "\n"
    return 1
Benutzeravatar
birkenfeld
Python-Forum Veteran
Beiträge: 1603
Registriert: Montag 20. März 2006, 15:29
Wohnort: Die aufstrebende Universitätsstadt bei München

Du bekommst von PyObject_CallObject ja ein PyObject* zurück.
Das kann jedes beliebige Python-Objekt repräsentieren (oder NULL sein, wenn eine Exception auftritt).

Wenn du eine Liste zurückgibst (den Typ des Rückgabewerts solltest du immer testen), kannst du sie mit dem C-API für Listen bearbeiten: PyList_GetItem etc.
Dann lieber noch Vim 7 als Windows 7.

http://pythonic.pocoo.org/
Lufia
User
Beiträge: 83
Registriert: Samstag 13. Mai 2006, 10:04
Wohnort: Berlin

vielen Dank, so klappt es jetzt perfekt :D

Jetzt ist mir das ganze klar, PyList_GetItem macht genau das was ich brauche.
Das ist ja echt elegant Daten zwischen Python und C hin/her zu schicken, klar die C-API und die Fehlerkontrolle ist ziemlich komplex.
Das muß ich aber nur einmal machen um von Python nach C zu kommen und wieder zurück, der Rest ist dann ja eher einfach (Objekte hin und her schicken).

Die Performance ist wohl nicht die schnellste aber ich denke für meine Zwecke reicht das gerade noch aus. Es ist auf jeden Fall immernoch besser als alles in C programmieren zu müssen.
Antworten