Question

I'm trying to extend the Python interpreter in my C++ program, my problem is as follows.
When I'm trying to call a function, explained in the code below, I get a NameError, from the Python interpreter. The error is

Traceback (most recent call last):
File "", line 3, in module
NameError: name 'func' is not defined

I used the following code to bind it, according to the Python wiki for version 3.3.2, which I'm using here

double func( int a )
{
    return a*a-0.5;
}

static PyObject *TestError;
static PyObject * func_test(PyObject * self, PyObject *args)
{
    const int * command;
    double sts;
    if( !PyArg_ParseTuple(args, "i", &command) )
        return NULL;
    sts = func( *command );
    return PyFloat_FromDouble(sts);
}

static PyMethodDef TestMethods[] = {
    {"func",  func_test, METH_VARARGS,
     "Thing."},
    {NULL, NULL, 0, NULL}        /* Sentinel */
};

static struct PyModuleDef testmodule = {
   PyModuleDef_HEAD_INIT,
   "test",   /* name of module */
   NULL, /* module documentation, may be NULL */
   -1,       /* size of per-interpreter state of the module,
            or -1 if the module keeps state in global variables. */
   TestMethods
};

PyMODINIT_FUNC PyInit_test()
{
    PyObject *m;
    m = PyModule_Create(&testmodule);
    if (m == NULL)
        return NULL;
    TestError = PyErr_NewException("test.error", NULL, NULL);
    Py_INCREF(TestError);
    PyModule_AddObject(m, "error", TestError);
    return m;
}


Then I'm calling PyImport_AppendInittab("test", PyInit_test);
Py_Initialize();, and then I'm trying to run a simple test, with

    PyRun_SimpleString("import test\n"
                       "print('Hi!')\n"
                       "b = func(5)\n"
                       "print(b)\n");

Yet, I keep getting the error. Can someone please explain, what am I doing wrong here?

Was it helpful?

Solution

PyRun_SimpleString("import test\n"
                   "print('Hi!')\n"
                   "b = test.func(5)\n"   # <--
                   "print(b)\n");

EDIT: Another problem:

int command;   // not "int *"
double sts;
if( !PyArg_ParseTuple(args, "i", &command) )

Note that I'd recommend using CFFI if you're not familiar yet with how to write a CPython C extension module.

OTHER TIPS

I agree with all the fixes by Armin Rigo and I would add this one:
PyImport_AppendInittab("test", &PyInit_test);

Pass the address of the function to PyImport_AppendInittab.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top