Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Python Embedding in C++ : ImportError: No module named pyfunction

Tags:

c++

python

Hi I'm trying to embed python (2.7) into C++ (g++ 4.8.2) and hence call a python function from C++. This is the basic code provided in python documentation for embedding:

This is my file call_function.cpp

#include <Python.h>

int main(int argc, char *argv[])
{
    PyObject *pName, *pModule, *pDict, *pFunc;
    PyObject *pArgs, *pValue;
    int i;

    if (argc < 3) {
        fprintf(stderr,"Usage: call pythonfile funcname [args]\n");
        return 1;
    }
   /* char pySearchPath[] = "/usr/include/python2.7";
    Py_SetPythonHome(pySearchPath);*/
    Py_Initialize();
    pName = PyString_FromString(argv[1]);
    /* Error checking of pName left out */

    pModule = PyImport_Import(pName);
    Py_DECREF(pName);

    if (pModule != NULL) {
        pFunc = PyObject_GetAttrString(pModule, argv[2]);
        /* pFunc is a new reference */

        if (pFunc && PyCallable_Check(pFunc)) {
            pArgs = PyTuple_New(argc - 3);
            for (i = 0; i < argc - 3; ++i) {
                pValue = PyInt_FromLong(atoi(argv[i + 3]));
                if (!pValue) {
                    Py_DECREF(pArgs);
                    Py_DECREF(pModule);
                    fprintf(stderr, "Cannot convert argument\n");
                    return 1;
                }
                /* pValue reference stolen here: */
                PyTuple_SetItem(pArgs, i, pValue);
            }
            pValue = PyObject_CallObject(pFunc, pArgs);
            Py_DECREF(pArgs);
            if (pValue != NULL) {
                printf("Result of call: %ld\n", PyInt_AsLong(pValue));
                Py_DECREF(pValue);
            }
            else {
                Py_DECREF(pFunc);
                Py_DECREF(pModule);
                PyErr_Print();
                fprintf(stderr,"Call failed\n");
                return 1;
            }
        }
        else {
            if (PyErr_Occurred())
                PyErr_Print();
            fprintf(stderr, "Cannot find function \"%s\"\n", argv[2]);
        }
        Py_XDECREF(pFunc);
        Py_DECREF(pModule);
    }
    else {
        PyErr_Print();
        fprintf(stderr, "Failed to load \"%s\"\n", argv[1]);
        return 1;
    }
    Py_Finalize();
    return 0;
}

Now my python script is saved as pyfunction.py placed in the same folder as call_function.cpp.

This is pyfunction.py :

def multiply(a,b):
    print "Will compute", a, "times", b
    c = 0
    for i in range(0, a):
        c = c + b
    return c

Now using the Terminal I'm calling :

$ g++ call_function.cpp -I/usr/include/python2.7 -lpython2.7 -o call_function

(Compiles successfully without any errors) (Running the program)

$ ./call_function pyfunction multiply 2 3

(I get this ERROR):

ImportError: No module named pyfunction    
Failed to load "pyfunction"

I don't understand how this is possible. I've followed the documentation and still I'm getting the error.

How can it not find pyfunction.py when it is placed in the same directory.

like image 543
user3000805 Avatar asked Jun 30 '14 14:06

user3000805


3 Answers

Put the following in the C/C++ code, just after Py_Initialize();

PyRun_SimpleString("import sys");
PyRun_SimpleString("sys.path.append(\".\")");
like image 84
Antonello Avatar answered Nov 13 '22 17:11

Antonello


Try this one:

 $ PYTHONPATH=. ./call_function pyfunction multiply 2 3

if this won't work, try to make __init__.py file in this directory and try again.

UPDATE:

I think that PYTHONPATH is temporary solution, to test stuff. If you want to have a directory when all your embedded modules lives you have to put in your embedded interpreter something equilevant to this:

import sys
sys.path.insert(0, "./path/to/your/modules/")

You can do it probably in python in your interpreter or on C level. This will add search path in very similar manner as PYTHONPATH but it is more persistant and elegant (IMHO).

like image 41
spinus Avatar answered Nov 13 '22 17:11

spinus


Hi to all those facing the same problem, I found the solution! setenv() is a function defined in stdlib.h which sets the environment variable. Just have to run it!

setenv("PYTHONPATH",".",1);

for more info on setenv:

$ man setenv

All the best :) Also, thanks to @spinus

like image 7
user3000805 Avatar answered Nov 13 '22 16:11

user3000805