2016-08-03 20 views
-1

Ich versuche, Python-Skript in einer C++ - Anwendung einzubetten. Um die Integration zu testen, habe ich einen Pilotcode:Python in C++ einbetten, Segmentierungsfehler

// c++ code 

int main(int argc, char *argv[]) 
{ 
    PyObject *pName, *pModule, *pDict, *pFunc, *pValue; 

    if (argc < 3) 
    { 
     printf("Usage: exe_name python_source function_name\n"); 
     return 1; 
    } 

    // Initialize the Python Interpreter 
    Py_Initialize(); 

    // Build the name object 
    pName = PyBytes_FromString(argv[1]); 
    //std::to_string(argv[1]).encode(

    // Load the module object 
    pModule = PyImport_Import(pName); 

    // pDict is a borrowed reference 
    pDict = PyModule_GetDict(pModule); 

    // pFunc is also a borrowed reference 
    pFunc = PyDict_GetItemString(pDict, argv[2]); 

    if (PyCallable_Check(pFunc)) 
    { 
     PyObject_CallObject(pFunc, NULL); 
    } 
    else 
    { 
     PyErr_Print(); 
    } 

    // Clean up 
    Py_DECREF(pModule); 
    Py_DECREF(pName); 

    // Finish the Python Interpreter 
    Py_Finalize(); 

    return 0; 
} 


# Python script 
def multiply(): 
    c = 12345*6789 
    print ('The result of 12345 x 6789 :' + str(c)) 

ich über die Pfosten kam, den Auftrieb verwenden vorschlagen. Ist Boost einfacher als das? Def von einfach: weniger Code, direkt, weitgehend von der Gemeinschaft verwendet.

Ich interessiere mich für diese Fragen, weil der wirkliche Code, den wir integrieren werden, ziemlich komplex ist (weil er nicht der Kodierungsethik folgt), und er muss oft mit Python-Code kommunizieren, daher gibt es auch Synchronisationsprobleme .

+0

Wo passiert der Absturz? Wie rufen Sie Ihr Programm auf (d. H. Welche Argumente übergeben Sie ihm)? Haben Sie Null-Pointer-Checks irgendwo in Ihrem tatsächlichen Code? –

+0

Code stürzt bei 'pFunc = PyDict_GetItemString (pDict, argv [2]) ab; Ja, Zeiger werden auf Nichtigkeit geprüft, alle bis pDict sind nicht null. Ich nenne es so: './test_cpp.o test_python multiplizieren 'test_python ist der Name des Python-Skripts – Adorn

+0

Liegt der Aufruf-Stack des Absturzes direkt an dieser Zeile oder irgendwo im Python? Was sind die Besonderheiten des Absturzes? – nate

Antwort

-1

Es könnte einfacher sein, oder den von Cython generierten Code zu verwenden.

Der Hauptschuldige scheint die fehlende

PySys_SetArgv(argc, wargs); 

wo wargs enthält die Argumente so breit Zeichenketten zu sein. Ohne sie funktionieren relative Importe nicht.

Der folgende Code (kompiliert mit gcc, g ++ würde einige Umwandlungen im Fall von malloc() erfordern) scheint zu funktionieren.

#include <Python.h> 
#include <string.h> 

int to_wide_args(wchar_t **argsw[], int argc, char *argv[]) 
{ 
    int i; 
    size_t len; 
    wchar_t *wstr; 
    wchar_t **tmp = NULL; 
    tmp = malloc(sizeof(wchar_t **) * argc); 

    for (i = 0; i < argc; i++) { 
     /* In case of python 3.5, see Py_DecodeLocale */ 
     len = mbstowcs(NULL, argv[i], 0); 
     wstr = malloc(sizeof(wchar_t) * (len + 1)); 
     if (len != mbstowcs(wstr, argv[i], len + 1)) { 
      return -1; 
     } 
     tmp[i] = wstr; 
    } 
    *argsw = tmp; 
    return 0; 
} 

int main(int argc, char *argv[]) 
{ 
    PyObject *dict = 0; 
    PyObject *func = 0; 
    PyObject *module = 0; 

    wchar_t **wargs = NULL; 
    int rc = 0; 

    if (argc < 3) { 
     printf("Usage: exe_name python_source function_name\n"); 
     return 1; 
    } 

    if (to_wide_args(&wargs, argc, argv) < 0) goto error; 

    Py_SetProgramName(wargs[0]); 
    Py_Initialize(); 
    PySys_SetArgv(argc, wargs); 

    if (PyErr_Occurred()) goto error; 

    module = PyImport_ImportModule(argv[1]); 
    printf("Module ptr: %p\n", module); 
    if (module == NULL || PyErr_Occurred()) goto error; 

    dict = PyModule_GetDict(module); 
    printf("Module dict ptr: %p\n", dict); 
    if (dict == NULL || PyErr_Occurred()) goto error; 

    func = PyDict_GetItemString(dict, argv[2]); 
    printf("Function ptr: %p\n", func); 
    if (func == NULL || PyErr_Occurred()) goto error; 

    if (PyCallable_Check(func)) { 
     PyObject_CallObject(func, NULL); 
    } else { 
     goto error; 
    } 
    goto ok; 

error: 
    PyErr_Print(); 
    rc = 1; 
ok: 
    Py_XDECREF(module); 
    Py_Finalize(); 

    return rc; 
}