sashoalm sashoalm - 3 months ago 7
C++ Question

SystemError: error return without exception set

I'm learning about embedding Python, and in my test program I'm calling Python code from my C application, and then the Python code calls a method I've provided:

#include <Python.h>

// The callback function.
extern "C" PyObject * printHello(PyObject *self, PyObject *args) {
printf("hello from C\n");
return 0;
}

PyMethodDef methods [] = {
{ "printHello", printHello, METH_NOARGS, "docs docs docs" },
{ 0, 0, 0, 0 },
};

int main(int argc, char *argv[])
{
Py_Initialize();
Py_InitModule("emb", methods);
PyRun_SimpleString(
"import emb\n"
"emb.printHello()\n"
);
Py_Finalize();
return 0;
}


The program runs and my function is called, but upon returning I get an exception:

hello from C
Traceback (most recent call last):
File "", line 2, in
SystemError: error return without exception set


I assume this has something to do with the calling convention, or signature of my callback function.

In particular, is it because I'm returning 0? My function doesn't really need to return anything, that's why I return 0. I would have used
void printHello()
, but
PyCFunction
requires the signature to be
PyObject * func(PyObject *self, PyObject *args);

Answer

You're correct that your function doesn't really need to return anything (in this case), but, in Python, "not returning anything" means returning None. Try replacing

return 0;

in your printHello function with

Py_INCREF(Py_None);
return Py_None;

The first line increments the refcount of None, and the second line returns it.

Even better, just use Py_RETURN_NONE (which is shorthand for the same):

extern "C" PyObject * printHello(PyObject *self, PyObject *args) {
    printf("hello from C\n");
    Py_RETURN_NONE;
}