2009-09-13 10 views
7

Próbuję wywołać funkcję w skrypcie w języku Python z mojego głównego programu C++. Funkcja python pobiera ciąg jako argument i nic nie zwraca (ok .. "Brak"). Działa to doskonale (nigdy nie myślałem, że będzie to łatwe ...), o ile poprzednie połączenie zostanie zakończone, zanim funkcja zostanie ponownie wywołana, w przeciwnym razie nastąpi naruszenie dostępu pod numerem pModule = PyImport_Import(pName).Wywołanie Pythona z C++

Istnieje wiele tutoriali, jak osadzić Pythona w C i na odwrót, ale nie znalazłem nic o tym problemie.

int callPython(TCHAR* title){ 
    PyObject *pName, *pModule, *pFunc; 
    PyObject *pArgs, *pValue; 

Py_Initialize(); 
    pName = PyUnicode_FromString("Main"); 
    /* Name of Pythonfile */ 

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

if (pModule != NULL) { 
     pFunc = PyObject_GetAttrString(pModule, "writeLyricToFile"); 
     /* function name. pFunc is a new reference */ 
     if (pFunc && PyCallable_Check(pFunc)) { 
      pArgs = PyTuple_New(1); 

    pValue = PyUnicode_FromWideChar(title, -1); 

    if (!pValue) { 
     Py_DECREF(pArgs); 
       Py_DECREF(pModule); 
     showErrorBox(_T("pValue is false")); 
     return 1; 
      } 
    PyTuple_SetItem(pArgs, 0, pValue); 

      pValue = PyObject_CallObject(pFunc, pArgs); 
      Py_DECREF(pArgs); 

      if (pValue != NULL) { 
       //worked as it should! 
       Py_DECREF(pValue); 
      } 
      else { 
       Py_DECREF(pFunc); 
       Py_DECREF(pModule); 
       PyErr_Print(); 
     showErrorBox(_T("pValue is null")); 
     return 1; 
      } 
     } 
     else { 
      if (PyErr_Occurred()) PyErr_Print(); 
      showErrorBox(_T("pFunc null or not callable")); 
     return 1; 
     } 
     Py_XDECREF(pFunc); 
     Py_DECREF(pModule); 
    } 
    else { 
     PyErr_Print(); 
     showErrorBox(_T("pModule is null")); 
    return 1; 
    } 
    Py_Finalize(); 
    return 0; 
} 

Odpowiedz

5

Kiedy mówisz „tak długo jak poprzedni zakończeniu połączenia, zanim funkcja nazywa się ponownie”, mogę tylko przypuszczać, że masz wiele wątków wywoływanie z C++ w Pythonie. Python nie jest bezpieczny dla wątków, więc to się nie uda!

Czytaj na globalnej blokadzie interpretera (GIL) w podręczniku Python. Być może poniższe linki pomogą:

Gil jest wymienione na Wikipedii:

1

Dziękuję za pomoc!

Tak, masz rację, jest kilka wątków w języku C. Nigdy nie przypuszczałem, że będę potrzebował muteksa dla samego tłumacza - GIL jest dla mnie zupełnie nową koncepcją (i nie jest nawet wspomniany w całym tutorialu).

Po przeczytaniu odniesienia (na pewno nie najłatwiejszy części, chociaż PyGILState_ * Funkcje uprościć całość dużo), dodałem funkcję

void initPython(){ 
    PyEval_InitThreads(); 
    Py_Initialize(); 
    PyEval_ReleaseLock(); 
} 

poprawnie zainicjować interpretera. Każdy wątek tworzy swoją strukturę danych, nabywa blokadę i zwalnia ją później, jak pokazano w odnośniku.

Działa tak, jak powinna, ale podczas wywoływania Py_Finalize() przed zakończeniem procesu otrzymuję błąd segfault .. jakiekolwiek problemy z pozostawieniem go?

+2

Cieszę się, że rozwiązało to twoje problemy. Nie mogę się domyślić, dlaczego miałbyś problemy z wywołaniem Py_Finalize() - może mógłbyś podać uproszczony przykład, który pokazuje problem w innym pytaniu. Naprawdę powinieneś całkowicie wyłączyć Pythona, ale jeśli zamierzasz wyjść z aplikacji, możesz być w porządku ... Zdecydowanie sugeruję, żebyś się rozwalił. –

+0

@ DanielPaull czy możesz podać prosty przykład dla tego samego tematu. Więc mogę łatwo zrozumieć – lkkkk