7

I am trying to use Py_BuildValue() to create a list of tuples in C.

What I am trying to build would look like this:

[ (...), (...), ... ] 

I don't know the amount of tuples to create at compilation, so I can't use some static amount here.

Essentially using Py_BuildValue() with one tuple here is what it would look like for the code:

PyObject * Py_BuildValue("[(siis)]", name, num1, num2, summary);

But that would only be for one tuple. I need to have multiple tuples in the list that I could add via a for loop. How can I accomplish this?

ComputerLocus
  • 3,448
  • 10
  • 47
  • 96

1 Answers1

12

You can use PyList_New(), PyTuple_New(), PyList_Append(), and PyTuple_SetItem() to accomplish this...

const Py_ssize_t tuple_length = 4;
const unsigned some_limit = 4;

PyObject *my_list = PyList_New(0);
if(my_list == NULL) {
    // ...
}

for(unsigned i = 0; i < some_limit; i++) {
    PyObject *the_tuple = PyTuple_New(tuple_length);
    if(the_tuple == NULL) {
        // ...
    }

    for(Py_ssize_t j = 0; i < tuple_length; i++) {
        PyObject *the_object = PyLong_FromSsize_t(i * tuple_length + j);
        if(the_object == NULL) {
            // ...
        }

        PyTuple_SET_ITEM(the_tuple, j, the_object);
    }

    if(PyList_Append(my_list, the_tuple) == -1) {
        // ...
    }
}

That will create a list of the form...

[(0, 1, 2, 3), (4, 5, 6, 7), (8, 9, 10, 11), (12, 13, 14, 15)]
3442
  • 8,248
  • 2
  • 19
  • 41
  • Is there a reason to use `PyLong` vs a `PyInt`? I have some integers as seen in my example which would be `num1` and `num2`. They are not longs, but I am assuming there is a reason I would still want to use `PyLong` like you used? And for a `char * string` that is null terminated which function would I want to use? Looking in the docs there are quite a few versions of `PyString` I could use. – ComputerLocus Mar 17 '16 at 03:51
  • 2
    @Fogest: On CPython 3, `PyInt` ceases to be, and all integers are represented by `PyLong` objects instead. – 3442 Mar 17 '16 at 03:58
  • Ah, thanks for the explanation. Are there similar cases in the PyString area, or should I just pick one that works for me case? – ComputerLocus Mar 17 '16 at 04:02
  • You may want to look at [the list of changes in the API](http://python3porting.com/cextensions.html) by the transition to CPython 3. There's a whole section for strings, which where greatly changed. – 3442 Mar 17 '16 at 04:04
  • 1
    Oh wow, sounds like no PyString in CPython3. Okay I will look into using the `PyUnicode` then. Thanks for your help, I have accepted your answer as it definitely solved my question! – ComputerLocus Mar 17 '16 at 04:09
  • When trying to use the `PyTuple_SET_ITEM` I am getting a warning: `warning: implicit declaration of function ‘PyTyuple_SET_ITEM’ [-Wimplicit-function-declaration] ` – ComputerLocus Mar 17 '16 at 17:59
  • This seems odd because I do see the function in the Python 3 docs: https://docs.python.org/3/c-api/tuple.html – ComputerLocus Mar 17 '16 at 18:02
  • I am using it like this: `PyTyuple_SET_ITEM(compTuple, (Py_ssize_t) 1, propNums);` – ComputerLocus Mar 17 '16 at 18:04
  • @Fogest: Look a little better at it; it's `PyTuple`, not `PyTyuple`. – 3442 Mar 17 '16 at 22:14
  • That is embarrassing. Thanks :P – ComputerLocus Mar 18 '16 at 00:26