2

我正在研究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

但是我没有在我只使用 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
4

0 回答 0