0

I have a C++ class Box that I want to wrap up using python C++ api.

The class is defined as:

class Box {
   public:
      int id;   

      Box(double l, double b, double h);

      double getVolume(void); 

      void setLength( double len );

   private:
      double length;      // Length of a box
      double breadth;     // Breadth of a box
      double height;      // Height of a box
};

In the C-API I have the following declaration of PyBox:

typedef struct 
{
    PyObject_HEAD
    Box *bx;
} PyBox;

and the following members table:

static PyMemberDef pyBox_members[] = {
    {"id", T_INT, offsetof(PyBox, bx->id), 0, "Box id"},
    {NULL}  /* Sentinel */
};

However, when I try to compile the module I get the following error message:

error: cannot apply ‘offsetof’ to a non constant address
     {"id", T_INT, offsetof(PyBox, bx->id), 0, "Box id"},
                   ^~~~~~~~

How do I specify the correct offsetof so that the member id corresponds to the public attribute bx->id?

Thanks!

1 Answer 1

1

The basic issue is that bx is a pointer, so bx->id could literally anywhere in memory relative to PyBox. Therefore offsetof can never work and thus defining the members in PyMemberDef also can never work.

One solution would be to change the class definition so Box is part of the class (and so an offset is meaningful). This may or may not make sense depending on your C++ code:

typedef struct 
{
    PyObject_HEAD
    Box *bx;
} PyBox;

The better solution would be to use PyGetSetDef instead to define property getters and setters for bx->id.

Sign up to request clarification or add additional context in comments.

4 Comments

Thanks! But how do I use the PyGetSetDef without defining PyMemberDef? The official docs do not contain that case AFAIK docs.python.org/3.5/extending/newtypes.html.
If you don't need it you just set tp_members to 0.
Thinking about it... if the attribute is public why do we need a getter/setter?
Because the getter/setter is the C++ <-> Python translation layer. Even when you use PyMemberDef then Python automatically generates a getter and setter to convert between PyObject and the C++ type. In this case the role of the getter/setter is also to figure out where bx is using the pointer.

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.