9

I am writing a native function that will return multiple Python objects

PyObject *V = PyList_New(0);
PyObject *E = PyList_New(0);
PyObject *F = PyList_New(0);

return Py_BuildValue("ooo", V, E, F);

This compiles fine, however, when I call it from a Python program, I get an error:

SystemError: bad format char passed to Py_BuildValue

How can this be done correctly?

EDIT: The following works

PyObject *rslt = PyTuple_New(3);
PyTuple_SetItem(rslt, 0, V);
PyTuple_SetItem(rslt, 1, E);
PyTuple_SetItem(rslt, 2, F);
return rslt;

However, isn't there a shorter way to do this?

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
D R
  • 21,936
  • 38
  • 112
  • 149
  • You also need to remember to decrement the reference count on V, E and F (`Py_DECREF(V);`, etc.) after calling `Py_BuildValue`, since `Py_BuildValue` increments the reference count of any object used with the `O` format specifier (see http://docs.python.org/c-api/arg.html#Py_BuildValue). Otherwise, the lists will never be freed, and you have a memory leak. – jchl Aug 17 '10 at 08:30
  • 1
    Thanks for the suggestion. I am returning `Py_BuildValue("NNN", V, E, F)` which does not increment the reference count. – D R Aug 17 '10 at 23:04
  • I have a question when will V,E,F be free (equivalent Py_DECREF) after return to Python implementation? Thanks! – Chinh Nguyen Huu Feb 16 '20 at 01:41

3 Answers3

12

I think it wants upper-case O? "OOO", not "ooo".

Ned Batchelder
  • 364,293
  • 75
  • 561
  • 662
  • 1
    Maybe you have also to add parenthesis to make python understand that you want to build a tuple : return Py_BuildValue("(OOO)", V, E, F); – ThR37 Aug 17 '10 at 08:38
1

As Ned Batcheder noted Py_BuildValue requires Uppercase and paranthesis to create the Tuple

Py_BuildValue("(OOO)", V, E, F);

Another option to achieve the same results is PyTuple_Pack

PyTuple_Pack(3, V, E, F);
maxbachmann
  • 2,862
  • 1
  • 11
  • 35
-6

Use Cython.

return V, E, F
John Machin
  • 81,303
  • 11
  • 141
  • 189