私は、この拡張 C モジュールがリモート プロシージャ コール (RPC) を作成してネットワーク サービスにアクセスする Python の C 拡張に取り組んでいます。この C モジュールは、RPC の結果 (収集された情報) にメソッド Py_BuildValue を適用し、それを PyList_Append メソッドを使用してリストに追加します。最後に、このリスト オブジェクトは呼び出し元の Python スクリプトに戻ります。この C モジュールを共有 .so ファイルの形式に変換して、Python で使用できるようにします。
メモリ リークの問題を解決するために、RPC の結果の Py_BuildValue をリストに直接追加する代わりに、この Py_BuildValue の結果を PyObject 変数に割り当て、その変数をリストに追加するようにコードを修正しました。変数をリストに追加した後、Py_DECREF を使用してこの PyObject 変数の参照カウントを減らします。この変更の後、あるマシンで Python スクリプトを実行すると、次のエラーが発生しました。
ImportError: /usr/local/support/iadrpcmodule.so: 未定義のシンボル: Py_InitModule4
しかし、私は Py_InitModule3 のみを使用している C モジュールで変数 'Py_InitModule4' を使用していません。
Python 2.4 を使用してコードをコンパイルし、64 ビットの Linux マシンで実行しました。
ここでも興味深いのは、マシンを再起動したときに問題が消えたことです..!!。
別のマシンで試したとき、この問題は発生しませんでした。
PEP0353 (http://www.python.org/dev/peps/pep-0353/) に従って、Python 2.5 の場合は 64 ビット マシンの名前が変更され、32 を想定する拡張モジュールのロードを防ぐことがわかりました。 -ビットサイズの型を 64 ビットサイズの型を持つインタープリターに変換すると、Py_InitModule4 は Py_InitModule4_64 に名前が変更されます。
このような問題が発生する理由と、マシンの再起動時に解決する方法を教えてください。これは、メモリ リークの問題を修正するためにコードを変更したためであり、この「インポート エラー」を解決するためにコードを変更する必要がありますか? コードで Py_InitModule4 を使用していないため、名前を Py_InitModule4_64 に変更して 64 ビット マシンで動作させるにはどうすればよいですか?
いくつかの修正を適用した以前のコードは、次のようなものです
PyList_Append(outlist,
Py_BuildValue(
"ss#" "iiiiiiiii" "iiiii" "iiiiiiiiiiiiiiiii" "IIIIIIII",
name,
ref_counter,
type,
local,
proto,
state)
);
return Py_BuildValue("O", outlist);
メモリリークの問題を解決するために、次のようにコードを変更しました。
PyObject *hostResult = Py_BuildValue(
"ss#" "iiiiiiiii" "iiiii" "iiiiiiiiiiiiiiiii" "IIIIIIII",
name,
ref_counter,
type,
local,
proto,
state);
PyList_Append(outlist,
hostResult);
Py_DECREF(hostResult);
PyObject * arglist = Py_BuildValue("O", outlist);
Py_DECREF(outlist);
return arglist;
また、モジュールを初期化するための別の関数は、Py_InitModule3 を使用している次のとおりです。
PyMODINIT_FUNC initdrpc(void)
{
PyObject * m;
drpc_ClientType.tp_new = PyType_GenericNew;
drpc_ClientType.tp_dealloc = (destructor)Client_dealloc;
if (PyType_Ready(&drpc_ClientType) < 0) {
return;
}
m = Py_InitModule3("drpc", dRpcMethods, module_doc);
}
};
このコードは Python 2.4 を使用してコンパイルされており、任意の 64 ビット マシンで実行されます。実行マシンには、Python 2.4 と Python 2.5 の両方が含まれている場合があります。
私の質問は、拡張モジュールを Python 2.5 にロードしないようにするために、このモジュールで「Py_InitModule4」を明示的に定義して名前を変更する必要がありますか? 以下のようなもの
#if SIZEOF_**strong text**SIZE_T != SIZEOF_INT
/* On a 64-bit system, rename the Py_InitModule4 so that 2.4
modules cannot get loaded into a 2.5 interpreter */
#define Py_InitModule4 Py_InitModule4_64
#endif