[C++-sig] playing with pygame

Brett Calcott brett.calcott at paradise.net.nz
Wed Jun 4 13:19:27 CEST 2003


Pygame (www.pygame.org) is a standard "C" type extension for python based on
the Simple Direct Media Layer. It is broken into several modules and exposes
the C objects to each other via a simple mechanism using a array of "slots",
that are initialised via python.

Here is the simplest class, a rect, snipped from the header pygame.h:

/* RECT */
#define PYGAMEAPI_RECT_FIRSTSLOT 20
#define PYGAMEAPI_RECT_NUMSLOTS 4
typedef struct {
 short x, y;
 short w, h;
}GAME_Rect;

typedef struct {
  PyObject_HEAD
  GAME_Rect r;
} PyRectObject;

#define PyRect_AsRect(x) (((PyRectObject*)x)->r)
#ifndef PYGAMEAPI_RECT_INTERNAL
#define PyRect_Check(x) ((x)->ob_type ==
(PyTypeObject*)PyGAME_C_API[PYGAMEAPI_RECT_FIRSTSLOT + 0])
#define PyRect_Type (*(PyTypeObject*)PyGAME_C_API[PYGAMEAPI_RECT_FIRSTSLOT +
0])
#define PyRect_New
(*(PyObject*(*)(GAME_Rect*))PyGAME_C_API[PYGAMEAPI_RECT_FIRSTSLOT + 1])
#define PyRect_New4 \

(*(PyObject*(*)(short,short,short,short))PyGAME_C_API[PYGAMEAPI_RECT_FIRSTSL
OT + 2])
#define GameRect_FromObject \
   (*(GAME_Rect*(*)(PyObject*,
GAME_Rect*))PyGAME_C_API[PYGAMEAPI_RECT_FIRSTSLOT + 3])


Here is the bit that exposes this to other modules:

#define import_pygame_rect() { \
 PyObject *module = PyImport_ImportModule("pygame.rect"); \
 if (module != NULL) { \
  PyObject *dict = PyModule_GetDict(module); \
  PyObject *c_api = PyDict_GetItemString(dict, PYGAMEAPI_LOCAL_ENTRY); \
  if(PyCObject_Check(c_api)) {\
   int i; void** localptr = (void**)PyCObject_AsVoidPtr(c_api); \
   for(i = 0; i < PYGAMEAPI_RECT_NUMSLOTS; ++i) \
    PyGAME_C_API[i + PYGAMEAPI_RECT_FIRSTSLOT] = localptr[i]; \
} Py_DECREF(module); } }
#endif

where this appears later on:

#ifndef NO_PYGAME_C_API
#define PYGAMEAPI_TOTALSLOTS 60
static void* PyGAME_C_API[PYGAMEAPI_TOTALSLOTS] = {NULL};
#endif

(Hope that makes sense)



So, I can do this:

#include <...boostpythonstuff...>
#include <pygame.h>

void look_at_rect(object o)
{
    PyObject *p = o.ptr();
    if (PyRect_Check(p))
    {
        GAME_Rect &r = PyRect_AsRect(p);
        std::cout << r.x << ',' << r.y;
    }
}

BOOST_PYTHON_MODULE(pygame_boost)
{
    import_pygame_rect();
    def("look_at_rect", look_at_rect);
}

Now the QUESTION:

I should be able to register a conversion though. I got as far as this:

lvalue_from_pytype<extract_member<PyRectObject,
    GAME_Rect, &PyRectObject::r>, &PyRect_Type>();

But, this won't compile as:
'python_type' : invalid template argument for
'boost::python::lvalue_from_pytype', constant expression expected

I think I understand the problem, but what is the solution?

Cheers,
Brett










More information about the Cplusplus-sig mailing list