1

I want to call a Python function from C++ code in OMNeT++ simple module.

I debugged the code using gdb. It passes all lines fine, but at the end the segmentation fault occurs after Py_Finalize();.

Segmentation fault error

I found the following issue on GitHub that describes the same problem. But it did not help me to resolve the problem.

double result=0;
// 1) Initialise python interpretator
if (!Py_IsInitialized()) {
    Py_Initialize();
        //Py_AtExit(Py_Finalize);
}
// 2) Initialise python thread mechanism
if (!PyEval_ThreadsInitialized()) {
        PyEval_InitThreads();
        assert(PyEval_ThreadsInitialized());
}

PyGILState_STATE s = PyGILState_Ensure();
PyRun_SimpleString("import sys; sys.path.append('/home/mypath/')");
PyObject *pName = PyUnicode_DecodeFSDefault((char*)"integrationTest");
PyObject* pModule = PyImport_Import(pName);

if (pModule != NULL)
{
    PyObject* pFunction = PyObject_GetAttrString(pModule, (char*)"calculateExecutionTime");
    /// changement will be held in this level Args and function result.
    PyObject* pArgs = PyTuple_Pack(2,PyFloat_FromDouble(2.0),PyFloat_FromDouble(8.0));
    PyObject* pResult = PyObject_CallObject(pFunction, pArgs);
    result = (double)PyFloat_AsDouble(pResult);
    ///////
}
// Clean up
PyGILState_Release(s);
Py_DECREF(pName);
Py_DECREF(pModule);
Py_Finalize();
Mouna
  • 11
  • 2
  • 2
    `PyObject_GetAttrString(pModule (char*)"calculateExecutionTime");` shouldn't be legal. Does your real code have a comma in there, or is the compiler accepting something truly strange? Also, you're not checking your return values for `NULL` (especially important on the `PyObject_CallObject` call, where you're ignoring any exception raised and trying to interpret a possibly `NULL` return as a legal pointer to `PyFloat`) or other error returns (e.g. `PyFloat_AsDouble` returns `-1.0` and sets an exception on failure). – ShadowRanger May 29 '19 at 13:36
  • Additional problem: You're `Py_DECREF`ing after releasing the GIL. The primary purpose of the GIL is to protect reference count manipulation; if you don't hold the GIL, you aren't allowed to modify reference counts in any way. Admittedly unlikely to be a problem if no threads are involved, but it's just one more possible source of problems. – ShadowRanger May 29 '19 at 13:41
  • My real code contains a comma in PyObject_GetAttrString(pModule,(char*)"calculateExecutionTime");. I will check my return value. Thanks for your comments. – Mouna May 29 '19 at 13:54

1 Answers1

0

The problem occurs after the first initialization/uninitialization of python interpreter. What happens during the OmneT++ simulation is initializing/uninitializing/re-initializing/... the Python interpreter. However, Numpy doesn't support this;

So, I resolved this problem by initializing python interpreter just one time in the beginning of the simulation in initialize() method. Then, I called Py_Finalize(); in the destructor.

Mouna
  • 11
  • 2
  • Ok. But there's no clue in your question that your might be initializing and finalizing Python multiple times (and the github issue you linked to and which you said "didn't help" actually said that this wasn't supported). Please read the help on asking [mcve] and follow it next time – DavidW May 31 '19 at 06:07
  • That's right, because i am using python embedded code in particular case of OmneT++ simulation. It is not classical C++ program. It is controlled by simulation events, and after that I understood the problem and then the github link was helpful. At the beginning, I wasn't aware about the python interpreter mechanism. Thank you for the link, I will follow it next time. – Mouna May 31 '19 at 14:02