Rock Rock - 3 months ago 30
Python Question

C++ embedded python PyArg_ParseTuple fails with string args

I'm trying to add embedded python to a OpenGL/SDL application.
So far everything works fine, like entering a string via SDL keyboard events and executing it with the embedded python interpreter.
I'm now into adding functions to call C/C++ functions like

void set_iterations(int c);

is invoked on the python interpreter with

>>> test.iterations(23)

The parsing of the integer parameter works like charm

static PyObject* test_iterations(PyObject *self, PyObject *args) {
int iterations;

return Py_None;

But when I try this:
>>> test.addignore('something')

static PyObject* test_addignore(PyObject *self, PyObject *args) {

char* ignorestring;
add_global_ignore(ignorestring); // C function

return Py_None;

Python gives me this error:

Traceback (most recent call last):
File "<string>", line 1, in <module>
UnicodeDecodeError: 'utf8' codec can't decode bytes in position 0-3: invalid data

The string should be UTF-8, as SDL is set to grab UNICODE from the keyboard, and everything else works perfectly.

Does anyone have an idea on what I might be doing wrong here?

I also inspected the args object passed to the function with

std::string args_str;

PyObject* repr = PyObject_Repr(args);
if (repr != NULL) {
args_str = PyBytes_AsString(PyUnicode_AsEncodedString(repr, "utf-8", "Error"));
std::cout << args_str << "\n";

And it gives me this:

The error pointed out by rodrigo, was originally causing be believe that my debug code that should print the resulting string as PyObject was wrong. But the problem was that I was passing the parser the wrong pointer, leading to said undefined behaviour in the memory and therefore leading me to believe the parser was the problem.
The occurring last parser error was then the debug output itself, which was pointing to the wrong memory address.
Thanks rodrigo, since your answer lead to solving the problem: accepted. Thank you for your help and patience.



static PyObject* test_addignore(PyObject *self, PyObject *args) {
    char* ignorestring;
    if (!PyArg_ParseTuple(args,"s", &ignorestring)) //Note the &
        return NULL;                                //Never ignore errors

    Py_RETURN_NONE;  //Always use helper macros