2009-09-13 38 views
7

私はメインのC++プログラムからPythonスクリプトで関数を呼び出そうとしています。 Python関数は引数として文字列を受け取り、何も返しません(ok .. 'None')。 関数が呼び出される前に前の呼び出しが終了していれば、完全にうまく動作します(これは簡単ではないと考えられません)。そうでなければ、pModule = PyImport_Import(pName)にアクセス違反があります。C++からPythonを呼び出してください

チュートリアルではPythonをCに埋め込む方法とその逆がありますが、その問題については何も見つかりませんでした。

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

答えて

5

あなたは「限り関数が再び呼び出される前に、前の呼び出しが完了すると、」言うとき、私は、あなたは、PythonにC++から呼び出す複数のスレッドを持っていると仮定することができます。 Pythonはスレッドセーフではないので、これは失敗するでしょう!

Pythonマニュアルの「Global Interpreter Lock(GIL)」を参照してください。おそらく、以下のリンクが役立ちます:

GILはWikipediaで言及されています。

1

ありがとうございました!

はい、そうですが、いくつかのCスレッドがあります。私はインタプリタそのもののためにミューテックスが必要だとは考えていませんでした.GILは完全に新しいコンセプトです(そして全体のチュートリアルで一度も言及されていません)。

(PyGILState_ *関数は全部多くを簡素化するものの、それがわからない最も簡単な部分のための)リファレンスを読んだ後、私は正確に通訳を初期化するために

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

機能を追加しました。 すべてのスレッドは、そのデータ構造を作成し、ロックを取得し、後で参照で示されるように解放します。

動作する必要がありますが、プロセスを終了する前にPy_Finalize()を呼び出すと、segfaultを取得します。

+2

これはあなたの問題を修正してうれしいです。 Py_Finalize()を呼び出す際に問題が発生する理由は考えられません。おそらく別の質問で問題を示す簡単な例を提供することができます。あなたは本当にPythonをきれいにシャットダウンしなければならないが、もしあなたがちょうどアプリケーションを終了しようとしているなら、あなたは大丈夫かもしれない。私はあなたがクラッシュする理由を理解することを強く勧めます。 –

+0

@DanielPaullあなたは上記の同じトピックについて簡単な実例を挙げてください。私は簡単に理解できます – lkkkk

関連する問題