Search code examples
pythonc++python-c-api

Creating a basic PyTupleObject using Python's C API


I'm having difficulty with creating a PyTupleObject using the Python C api.

#include "Python.h"

int main() {
    int err;
    Py_ssize_t size = 2;
    PyObject *the_tuple = PyTuple_New(size); // this line crashes the program
    if (!the_tuple)
        std::cerr << "the tuple is null" << std::endl;
    err = PyTuple_SetItem(the_tuple, (Py_ssize_t) 0, PyLong_FromLong((long) 5.7));
    if (err < 0) {
        std::cerr << "first set item failed" << std::endl;
    }
    err = PyTuple_SetItem(the_tuple, (Py_ssize_t) 1, PyLong_FromLong((long) 5.7));
    if (err < 0) {
        std::cerr << "second set item failed" << std::endl;
    }
    return 0;

}

crashes with

Process finished with exit code -1073741819 (0xC0000005)

But so does everything else i've tried so far. Any ideas what I'm doing wrong? Not that I'm just trying to run the as a C++ program, as I'm just trying to do tests on the code before adding a swig typemap.


Solution

  • The commenter @asynts is correct in that you need to initialize the interpreter via Py_Initialize if you want to interact with Python objects (you are, in fact, embedding Python). There are a subset of functions from the API that can safely be called without initializing the interpreter, but creating Python objects do not fall within this subset.

    Py_BuildValue may "work" (as in, not creating a segfault with those specific arguments), but it will cause issues elsewhere in the code if you try to do anything with it without having initialized the interpreter.

    It seems that you're trying to extend Python rather than embed it, but you're embedding it to test the extension code. You may want to refer to the official documentation for extending Python with C/C++ to guide you through this process.