1

I'm learning how to write a native module in Python 3.7. I'm struggling on how to create and return a new object. It seems using it generates segmentation faults at random points, as I illustrate below.

I've seen a lot of questions that sort of answer this. They seem to suggest using PyObject_CallObject vs PyObject_New for native object creation. It seems PyObject_New does not initialize all field members in a new object, however details on this are scant.

Unfortunately a lot of references are either 1) 10+ years or older 2) Vague and unclear.

In the below example when I replace PyObject_New with PyObject_CallObject on the type test1_obj_type I get another segmentation fault.

 PyObject_CallObject( (PyObject*) &test1_obj_type, NULL);

What is the correct way to initialize a Python object in 2019? Again there are a lot of asked-and-answered questions on this topic, however none seem to provide functioning example of correct usage of PyObject_CallObject for object creation and initialization.

test.c

#include <Python.h>

typedef struct test1_obj
{
    PyObject_HEAD

} test1_obj;

static PyObject* create_obj()
{

    static PyTypeObject test1_obj_type = {
        PyObject_HEAD_INIT(NULL)
        .tp_name = "test1_obj",
        .tp_doc = "test1_obj",
        .tp_basicsize = sizeof(test1_obj),
        .tp_itemsize = 0,
        .tp_methods = NULL,
        .tp_flags = Py_TPFLAGS_DEFAULT,
        .tp_new = PyType_GenericNew,
    };

    return (PyObject*) PyObject_New(test1_obj, &test1_obj_type);

}

PyMODINIT_FUNC PyInit_libmiketest(void)
{
    PyObject *module;

    static PyMethodDef methods[] = {
        {"create_obj", create_obj, METH_NOARGS, "doc"},
        {NULL, NULL, 0, ""}
    };

    static struct PyModuleDef moduledef = 
    {
        PyModuleDef_HEAD_INIT,
        "create_obj",
        "",
        -1,
        methods,
        NULL,
        NULL,
        NULL,
        NULL
    };

    module = PyModule_Create(&moduledef);

    return module;
}

python

>>> import libmiketest
>>> a = libmiketest.create_obj()
>>> help(a)
Segmentation fault: 11
Alec
  • 8,529
  • 8
  • 37
  • 63
Mike
  • 58,961
  • 76
  • 175
  • 221
  • `PyObject_HEAD_INIT(NULL)` is wrong - you're saying that your type object's type is `NULL`. – user2357112 Apr 28 '19 at 00:05
  • The question you've asked is a dupe of https://stackoverflow.com/questions/4163018/create-an-object-using-pythons-c-api. You can't create an instance of your class with `PyObject_CallObject` because your class is broken, a completely separate issue from the one you're asking about. – user2357112 Apr 28 '19 at 00:08
  • You said my class was broken, but in the linked example they also used `PyObject_HEAD_INIT(NULL)`. – Mike Apr 28 '19 at 00:11
  • 1
    True. If you do that, you have to call `PyType_Ready` on your type object manually, though. (Also, it should really be `PyVarObject_HEAD_INIT(NULL, 0)`, but the difference doesn't do anything when you're initializing the other fields by name.) – user2357112 Apr 28 '19 at 00:21
  • I did as you suggested, now I get `TypeError: cannot create 'test1_obj' instances` – Mike Apr 28 '19 at 00:33
  • That's strange, since it's the error message for when your class has no `tp_new`. – user2357112 Apr 28 '19 at 00:37
  • Ignore my comment, adding `PyType_Ready` resolved my problem. I appreciate your help, if you put this in an answer I will accept it. – Mike Apr 28 '19 at 00:43
  • 1
    Possible duplicate of [Create an object using Python's C API](https://stackoverflow.com/questions/4163018/create-an-object-using-pythons-c-api) – Alec Apr 28 '19 at 02:00
  • Not a dupicate. – Mike Apr 28 '19 at 02:09

0 Answers0