Search code examples
c++python-c-api

Python C++ api: How to access public class attribute?


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!


Solution

  • 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.