1

Python 2.6 を既存の C++ アプリケーションに埋め込む作業を行っています。これまでのところ、ライブラリがリンクされており、Python インタープリターを正常に初期化でき、データを Python に転送することもできます。取得に問題があります。誰かが私を正しい方向に導いてくれることを願っています。私はこれを扱っています:

Py_Initialize();

pModule = PyImport_ImportModule("cBuffers"); // This crashes after 1st call.
pDict = PyModule_GetDict(pModule);
pClass = PyDict_GetItemString(pDict, "rf_pdf");
pMeth = PyString_FromString("main");

if (PyCallable_Check(pClass) && PyClass_Check(pClass)) {
  pInstance = PyInstance_New(pClass, NULL, NULL);
  pOutput = PyObject_CallMethodObjArgs(pInstance, pMeth, pOpts, pInput, NULL);
}

if (pOutput != NULL) {
  string pPdf = PyString_AsString(pOutput);
  Py_DECREF(pOutput);
} else {
  PyErr_Print();
}

// Cleanup
Py_DECREF(pModule);
Py_DECREF(pModule); // Has an extra reference, not positive why.
Py_DECREF(pMeth);
Py_DECREF(pInstance);
Py_DECREF(pOpts);
Py_DECREF(pInput);

Py_Finalize();

pOpts と pInput は両方ともPyString_FromString、コードの前半を使用して生成されます。私が抱えている問題は、PyString_AsString を使用して出力を取得しようとすると、戻り値が NUL Terminated になることです。残念ながら、私は PDF ドキュメントを生成しているので、NUL は許可されているだけでなく、ほぼ保証されています。遭遇した最初の NUL で終了することなく、Python から C++ に文字列データを返す方法を誰か教えてもらえますか?

追加の質問として、このコードは、受信した印刷データから PDF ドキュメントを作成するバックグラウンド サービスの一部として複数回呼び出すことができます。このコードが最初に呼び出されたときは、期待どおりに機能します。以降の呼び出しは、 の直後に示された行で失敗しますPy_Initialize()。そこで何が起こっているのかを判断する方法についてのヘルプも非常に高く評価されます。前もって感謝します、

4

1 に答える 1

1

いくつかのポイント:

  • 文字列は使用しないでください。* _StringAndSize()関数にいくつかのゆがみを加えて、ここでそれらを機能させることさえできるかもしれませんが、それはあなたが望むものではありません。単なるバイトシーケンスであるカスタムデータ構造(またはバッファー)にデータを格納する必要があります(クライアントがPythonでこのデータに対して文字列操作を実行することを本当に望んでいますか?)。オブジェクトが実際にバッファオブジェクトである場合は、BufferAPIを使用する必要があります。

  • インポートされたモジュールは、保持されているため、refcountが2になり sys.modulesます(次にインポートしようとするときの効率のため)。 所有していない参照をdecrefしないでください。そうしないと、プログラムがクラッシュします。ドキュメントの「モジュールのインポート」セクションで実際にこれをカバーする必要がありますが、そうではありません。

  • Pythonを初期化し、これらの操作を行うたびにPythonを破棄するのはかなり費用がかかります。Py_Initializeアプリケーションの起動時(またはPythonが初めて必要なとき)に1回だけ呼び出すことができるようにユースケースを再編成し、アプリケーションがPythonで確実に終了したとき、または終了したときにのみ呼び出すようPy_Finalizeにする必要があります。

  • エラーチェックに非常に怠惰です-ほとんどのPythonC/ API関数は、例外がスローされたことを示すためにNULLを返す可能性があり、この値をチェックすることはほとんどありません。何かが失敗した場合、非常に奇妙な場所でクラッシュし始めます。これについては、C/APIマニュアルの「例外処理」セクションで読むことができます。

于 2010-10-08T18:03:45.920 に答える