[Python-Dev] Define metatype and a type that uses it

Erik Groeneveld erik at cq2.nl
Wed Jul 8 14:43:29 CEST 2009


L.S.

I am working on an extension that allows one to open Java .jar files
and use the objects defined in it (via CNI or JNI) in Python.  It
works like a charm, but I am stuck with the definition of a metatype
for the wrappers.  I have to do this in Python now, with a helper
class.

I did find examples of how to define metatypes, but I can't find
anything on how to declare one type using this metatype.

Could anyone point me to examples or documentation or help me fix my code below?

What I have is a type JObject that has a metatype JObjectMeta, but the
objects created from it seem not properly initialized.   If I call
PyString_Str(self) in JObjectMeta_init, it seg faults.  De Python code
that initiates this is:

class MyJObject(JObject):
    pass

Below is the complete, contained code of the extension.

Thanks in advance,
Erik Groeneveld


#include <Python.h>

/*************** JObjectMeta *******************/
typedef struct {
    PyObject_HEAD
} JObjectMeta;

PyTypeObject JObjectMetaType = {
    PyObject_HEAD_INIT(NULL)
};

int JObjectMeta_init(PyObject* self, PyObject* args, PyObject *kwargs) {
    printf("before str\n");
    PyObject_Str(self);
    printf("after str\n");
    return 0;
}

PyObject* JObjectMeta_getattro(PyObject *self, PyObject *name) {
    return PyBaseObject_Type.tp_getattro(self, name);
}


/*************** JObject ***********************/
typedef struct {
    PyObject_HEAD
} JObject;

PyTypeObject JObjectType = {
    PyObject_HEAD_INIT(&JObjectMetaType)
};

int JObject_init(PyObject* self, PyObject* args, PyObject *kwargs) {
    return 0;
}

static PyMethodDef methods[] = {
    {NULL, NULL, 0, NULL}
};

/*************** INIT *******************/

PyMODINIT_FUNC
initmetaclass(void) {
    JObjectMetaType.tp_name         = "metaclass.JObjectMeta";
    JObjectMetaType.tp_basicsize    = sizeof(JObjectMeta);
    JObjectMetaType.tp_flags        = Py_TPFLAGS_DEFAULT;
    JObjectMetaType.tp_doc          = "JObject objects";
    JObjectMetaType.tp_init         = JObjectMeta_init;
    JObjectMetaType.tp_base         = &PyType_Type; // must ?
    JObjectMetaType.tp_new          = PyType_GenericNew;
    JObjectMetaType.tp_getattro     = JObjectMeta_getattro;

    JObjectType.tp_name         = "metaclass.JObject";
    JObjectType.tp_basicsize    = sizeof(JObject);
    JObjectType.tp_flags        = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE;
    JObjectType.tp_doc          = "JObjectMeta objects";
    JObjectType.tp_init         = JObject_init;
    JObjectType.tp_base         = &JObjectMetaType; // must ?
    JObjectType.tp_new          = PyType_GenericNew;

    PyObject* module = Py_InitModule3("metaclass", methods, "Metaclass
try out.");
    if (module == NULL) {
        PyErr_Print();
        exit(-1);
    }
    if (PyType_Ready(&JObjectMetaType) < 0) {
        PyErr_Print();
        exit(-1);
    }
    if (PyModule_AddObject(module, "JObjectMeta", (PyObject*)
&JObjectMetaType) < 0) {
        PyErr_Print();
        exit(-1);
    }
    if (PyType_Ready(&JObjectType) < 0) {
        PyErr_Print();
        exit(-1);
    }
    if (PyModule_AddObject(module, "JObject", (PyObject*) &JObjectType) < 0 ) {
        PyErr_Print();
        exit(-1);
    }
}


More information about the Python-Dev mailing list