2009-09-13 12 views
7

J'essaie d'appeler une fonction dans un script Python à partir de mon programme C++ principal. La fonction python prend une chaîne comme argument et ne renvoie rien (ok .. 'None'). Cela fonctionne parfaitement bien (jamais pensé que ce serait aussi facile ..) tant que l'appel précédent est terminé avant que la fonction soit appelée à nouveau, sinon il y a une violation d'accès à pModule = PyImport_Import(pName).Appelez Python à partir de C++

Il existe de nombreux tutoriels sur la façon d'intégrer Python en C et vice versa, mais je n'ai rien trouvé à propos de ce problème.

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; 
} 

Répondre

5

Quand vous dites « tant que l'appel précédent est terminé avant que la fonction est appelée à nouveau », je ne peux que supposer que vous avez plusieurs threads d'appel de C++ en Python. Le python n'est pas thread-safe, donc ça va échouer!

Lit le verrou Global Interpreter (GIL) dans le manuel Python. Peut-être les liens suivants vous aideront:

Le GIL est mentionné sur Wikipedia:

1

Nous vous remercions de votre aide!

Oui, vous avez raison, il existe plusieurs threads C. Je n'aurais jamais pensé avoir besoin de mutex pour l'interprète lui-même - le GIL est un concept complètement nouveau pour moi (et n'est même pas mentionné dans le tutoriel).

Après avoir lu la référence (bien sûr pas le plus facile, même si les PyGILState_ * fonctions simplifient le tout un lot), j'ai ajouté une fonction

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

pour initialiser l'interprète correctement. Chaque thread crée sa structure de données, acquiert le verrou et le libère ensuite comme indiqué dans la référence.

Fonctionne comme il se doit, mais lors de l'appel Py_Finalize() avant de terminer le processus, je reçois un segfault .. des problèmes avec juste le laisser?

+2

Je suis content que cela a réglé vos problèmes. Je ne peux pas penser pourquoi vous auriez des problèmes pour appeler Py_Finalize() - peut-être pourriez-vous fournir un exemple simplifié qui montre le problème dans une autre question. Vous devriez vraiment fermer Python proprement, mais si vous voulez simplement quitter l'application, ça pourrait aller ... Je vous suggère fortement de réfléchir à la raison pour laquelle il se bloque. –

+0

@DanielPaull pouvez-vous s'il vous plaît donner un exemple de travail simple pour le même sujet ci-dessus.Alors je peux comprendre facilement – lkkkk

Questions connexes