2

I have been working on a Python C/C++ extension, I managed to get everything working so far except a method that adds two structures called "int_obj" that have an integer inside and returns a new structure called "add_int_obj".

The extension only has two methods so far, "value" that works flawlessly and "add" that is the problematic method.

I'm testing it with the following test.py script:

import intobj
val1 = intobj.IntObj(3)
val2 = intobj.IntObj(5)
print "Val1"
print val1
print "Val1 Value"
print val1.value()
print "Val2"
print val2
print "Val2 Value"
print val2.value()
val3 = intobj.add(val1, val2)
print "Val3"
print val3
print "Val3 Value"
print val3.value()

When i execute i get the following output:

$ python test.py 
Val1
<intobj.IntObj object at 0x7faf3fc8a0f0>
Val1 Value
3
Val2
<intobj.IntObj object at 0x7faf3fc8a108>
Val2 Value
5
IntObj_add start
Int Obj Value A: 3
Int Obj Value B: 5
Int Obj Value Result: 8
IntObj_add end
Val3
Segmentation fault (core dumped)

The extension method that handles adding the two structures is:

static PyObject *IntObj_add(PyObject *self,PyObject *args)
{
    std::cout<<"IntObj_add start"<<std::endl;

    PyObject *a,*b;

    IntObj *result;

    if (!PyArg_ParseTuple(args, "OO", &a, &b))
            return NULL;

    std::cout<<"Int Obj Value A: "<<int_obj_value(((IntObj*)a)->content)<<std::endl;
    std::cout<<"Int Obj Value B: "<<int_obj_value(((IntObj*)b)->content)<<std::endl;

    result = new IntObj;

    Py_INCREF(result);

    result->content = add_int_obj(((IntObj*)a)->content,((IntObj*)b)->content);

    std::cout<<"Int Obj Value Result: "<<int_obj_value(result->content)<<std::endl;

    std::cout<<"IntObj_add end"<<std::endl;

    return (PyObject*)result;
}

Since the segmentation fault occurs only outside the method when i try to print the object and not when i try to get the value my guess is that the garbage collector is deleting the PyObject that the method is trying to return.

How can i securely return the result object?

8
  • new is a pretty suspicious way to create a Python object. Commented Oct 16, 2017 at 23:03
  • @user2357112 would you suggest that the object should be created differently? If the structure works inside the method why would this be a problem? Commented Oct 16, 2017 at 23:08
  • If by "works inside the method", you mean "doesn't crash yet", then sure, but C++ doesn't promise to crash immediately as soon as you do something wrong. There's important stuff in result that isn't getting initialized, like the refcount and the type pointer. Commented Oct 16, 2017 at 23:15
  • Interesting way to put it, I thought i was initializing it correctly by allocating memory for the object and updating the refcount with Py_INCREF(result). Is there a more standard way to initialize the object? i found Py_BuildValue looking for it but it needs a PyObject* to build from and I'm still initializing the result with new. Commented Oct 16, 2017 at 23:25
  • 1
    The simplest way would be to call the type object, just like you would as a user of the extension module. Commented Oct 16, 2017 at 23:28

1 Answer 1

0

Thanks to @user2357112's comment and some reading refreshing my C/C++ I remembered I could define the method prior to using it, this way I could solve my problem the following way:

I defined my method in the beginning of the file like this:

static PyObject *IntObj_add(PyObject *, PyObject *);

And then after the PyTypeObject is implemented I implemented the method creating the object calling the type object instead of new as follows:

static PyObject *IntObj_add(PyObject *self, PyObject *args)
{
    PyObject *a, *b;

    IntObj *result;

    if (!PyArg_ParseTuple(args, "OO", &a, &b))
        return NULL;

    result = (IntObj *)IntObjType.tp_alloc(&IntObjType, 0);

    result->content = add_int_obj(((IntObj *)a)->content, ((IntObj *)b)->content);

    return (PyObject *)result;
}
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.