1

I am using Python code within C++ code and trying to pass a list argument to a function written in Python. I tried the normal way of executing the Python code without passing any argument and it was all working fine but when I pass a list as an argument, I get a segmentation fault.

Here is my code:

#define PY_SSIZE_T_CLEAN

#include</usr/include/python3.6/Python.h>
#include <bits/stdc++.h>

using namespace std;

int callModuleFunc(int array[], size_t size) {

    PyObject *mymodule = PyImport_ImportModule("test");
    PyObject *myfunc = PyObject_GetAttrString(mymodule, "get_lists");
    cout<<"Imported"<<endl;

    PyObject *mylist = PyList_New(size);
    cout<<"Imported3"<<endl;
    for (size_t i = 0; i != size; ++i) {

    
        PyList_SET_ITEM(mylist, i, PyLong_FromLong(array[i]));
    }
    PyObject *arglist = Py_BuildValue("(O)", mylist);
    cout<<"Imported1"<<endl;
    PyObject *result = PyObject_CallObject(myfunc, arglist); // getting segmentation fault here
    cout<<"Imported5"<<endl;
    int retval = (int)PyLong_AsLong(result);
    Py_DECREF(result);
    Py_DECREF(arglist);
    Py_DECREF(mylist);
    Py_DECREF(myfunc);
    Py_DECREF(mymodule);
    return retval;
    }

int main(int argc, char const *argv[])
{

    wchar_t * program = Py_DecodeLocale(argv[0], NULL);
    if(!program){
        cout<<"***Error***"<<endl;
        exit(1);
    }

    Py_SetProgramName(program);
    Py_Initialize();

    PyObject *module = NULL, *result = NULL;

    PyRun_SimpleString("print('Hello from python')\n"
                   "print('Hiii')");


    int arr[5] = {1,3,4,5,6};
    callModuleFunc(arr, 5);

    if(Py_FinalizeEx() < 0){

        cout<<"***Error***"<<endl;
        exit(120);
    
    }

    PyMem_RawFree(program);

    return 0;
}

When I call PyObject_CallObject(myfunc, arglist), I get a segmentation fault.

I am totally new to it so I'm just trying stuff from the internet.

I'm using Python version 3.6 with g++ compiler 7.5.

Here is my test.py:

def get_lists(l1):
    print("Lists: ", l1)
    return 10

Please let me know how I can resolve this.

Thanks

Daniel Walker
  • 6,380
  • 5
  • 22
  • 45
ABD
  • 180
  • 11
  • [Why should I not #include ?](https://stackoverflow.com/questions/31816095/why-should-i-not-include-bits-stdc-h) – Jason Aug 18 '22 at 13:29

1 Answers1

1

The Python function get_lists is not known during execution.

Note: The test package is meant for internal use by Python only. It is documented for the benefit of the core developers of Python. Any use of this package outside of Python’s standard library is discouraged as code mentioned here can change or be removed without notice between releases of Python.

see https://docs.python.org/3/library/test.html

If the name of the imported Python file is renamed to another name (e.g. list.py) the Python function can be found.

Additional Hints

For the environment of the OP the problem is then solved. For my environment (Python 3.9.5) I need additionally replace the PyRun_SimpleString with:

    PyRun_SimpleString("import sys");
    PyRun_SimpleString("sys.path.append(\".\")");

Otherwise the module can't be imported.

Finally, it is advisable to check each function call for errors (e.g. whether it returns NULL) and to use PyErr_Print so that the actual cause of the error is printed instead of a crash due to a segmentation fault.

For example an error message could look like this:

AttributeError: module 'test' has no attribute 'get_lists'

Test

The output of the line Lists: [1, 3, 4, 5, 6] on the console shows that the Python function is called correctly when the above points are taken into account.

Stephan Schlecht
  • 26,556
  • 1
  • 33
  • 47
  • Hi @Stephan Thanks for replying. This approach won't work if I had a lot of python code. I wanted to execute the python code from some file itself. In that file, I had 4-5 functions to be called and I think using this approach, it would be quite complex to do so. Please ignore debug messages. – ABD Aug 18 '22 at 05:08
  • Hi , even after including those line, I am getting - module test has no attribute get_lists when PyObject *myfunc = PyObject_GetAttrString(mymodule, "get_lists"); is called. I checked with PyErr_Print(). – ABD Aug 18 '22 at 08:45
  • 1
    Same result if you rename test.py to list.py and adapt your import statement? Need to check later, when I‘m back at a PC. – Stephan Schlecht Aug 18 '22 at 10:14
  • Hi Stephan, I got the error. Actually my code was right too. It was issue with file name, test.py. I tested with something else name and it worked. – ABD Aug 18 '22 at 11:04
  • 1
    Hi Akhilesh, it looks like the module name `test` is reserved, see the link in my updated answer, so it should not / cannot be used for custom stuff. – Stephan Schlecht Aug 18 '22 at 13:20