我正在研究python的C扩展,其中此扩展C模块将进行远程过程调用(RPC)以访问网络服务。此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
但是我没有在我的C模块中使用变量'Py_InitModule4',我只使用Py_InitModule3。
我使用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