0

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.

CiaranWelsh
  • 7,014
  • 10
  • 53
  • 106
  • 1
    I don't know anything about Python's C API, but I assume that you have to initialize the runtime somehow, a quick search shows `Py_Initialize`: https://docs.python.org/3/extending/embedding.html – asynts Mar 22 '21 at 14:38
  • Yes, I saw that. However I *think this is only necessary when you're actually embedding Python. I'm only trying to get the tuple created in C++ because I'll immediately pass it to swig which will do the heavy lifting. Also, using the function `PyObject* obj = Py_BuildValue("i",1, 2);` works from main without Py_Initialize being called - only when I try to create a tuple I get a segfault. – CiaranWelsh Mar 22 '21 at 14:53
  • 1
    The API has to provide some sort of garbage collection or reference counting mechanism since it's possible to pass these objects to python, that surely needs some initialization. – asynts Mar 22 '21 at 15:15

1 Answers1

1

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.

QMetaObject
  • 65
  • 1
  • 6