I am working on C extension of python where this extension C module will make a Remote Procedure Call(RPC) to access the network services. This C module will apply the method Py_BuildValue on the result (collected information) of RPC and append that to a list using PyList_Append method.Finally this list object returns to the calling Python script. We are converting this C module to the form of shared .so file to use with Python.
To solve some memory leak issue I modified the code in such a way that instead of directly appending the Py_BuildValue on RPC result to the list, I assign this Py_BuildValue result to a PyObject variable and append that variable to the list. After appending the variable to the list decrements the reference count for this PyObject variable using Py_DECREF. After this change when I execute the Python script on one machine I got the following error.
ImportError: /usr/local/support/iadrpcmodule.so: undefined symbol: Py_InitModule4
But I am not using the variable 'Py_InitModule4' in my C module where I am using only Py_InitModule3.
I compiled the code using python 2.4 and executed it on a 64 bit linux machine.
Again the interesting part is when I restarted the machine the issue disappeared..!!.
I am not getting this issue when I tried on another machine.
I saw as per PEP0353 (http://www.python.org/dev/peps/pep-0353/ ) there is a name change for 64 bit machines in the case of Python 2.5 and to prevent loading extension modules that assume a 32-bit size type into an interpreter that has a 64 bit size type, Py_InitModule4 is renamed to Py_InitModule4_64.
What may be the reason to get such an issue and how it can be resolved on restarting the machine ? is that because of my code change to fix memory leak issue and do I need any code change to be done to solve this 'import error' ? As I am not using Py_InitModule4 in my code how I can make the change of renaming it as Py_InitModule4_64 to work with 64 bit machine ?
Previous code where I applied some fixes is something similar as follows
PyList_Append(outlist,
Py_BuildValue(
"ss#" "iiiiiiiii" "iiiii" "iiiiiiiiiiiiiiiii" "IIIIIIII",
name,
ref_counter,
type,
local,
proto,
state)
);
return Py_BuildValue("O", outlist);
I changed the code something similar as follows to solve some memory leak issue.
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;
Also another function to initialize the module is there as follows where we are using 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);
}
};
This code is compiled using Python 2.4 and will be running on any 64 bit machine. The executing machine may have both Python 2.4 and Python 2.5.
My question is in order to prevent loading the extension module to Python 2.5, do I need to define and rename 'Py_InitModule4' explicitly in this module even though we are not using that ? something as below
#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