pythonc++python-modulepython-c-apipyobject

Is it possible to assign an C++ pointer to an attribute of a Python object, and retrieve it as a C++ pointer in another C++ function?


I'm making a C++ extension for Python, and I'm trying to do something like:

// this function assigns a C++ pointer to as attribute of a python object
void function1(PyObject* p){
    // equivalent of p.attr = cpp_attr;
    MyClass* cpp_attr = new MyClass();
    PyObject* args = PyTuple_Pack(cpp_attr);
    PyObject_SetAttrString(p, (char*)"attr", args);
}

I would like to retrieve this pointer and set it as attribute of another C++ object. I know how to get the PyObject* but after that I'm not sure what to do anymore

MySecondClass::MySecondClass(PyObject* p){
    // get the attribute from p; equivalent of cpp_attr = p.attr
    PyObject* cpp_attr = PyObject_getAttrString(p, (char*)"attr"));
    // somehow get back the pointer to MyClass object created in function1
    
}

I looked at the documentation but I couldn't find anything that returns the original type. Is there anyway to do this?

Thanks


Solution

  • Assuming your call to PyTuple_Pack is correct, then you've created a PyTupleObject which has a structure:

    typedef struct {
      PyObject_VAR_HEAD
      PyObject *ob_item[1];
    } PyTupleObject;
    

    The PyTupleObject inherits from the generic PyObject struct which has the following members:

    struct _object *_ob_next;
    struct _object *_ob_prev;
    Py_ssize_t ob_refcnt;
    struct _typeobject *ob_type;
    

    You can access the latter two with the macrosPy_REFCNT and Py_TYPE

    The ob_item[1] member should be a pointer to the memory initially allocated. Based on how Macros are written in the documentation, you should be able to access it by

    ((PyTupleObject *)cpp_attr)->ob_item

    And if you know the data type of the C++ pointer, then you should be able to cast it back. Maybe you can try

    MyClass* cpp_att_again = reinterpret_cast<MyClass*>((PyTupleObject *)cpp_attr)->ob_item
    

    Hopefully this points you in the right direction. You might be able to glean more insight from a similar question.