Define metatype and a type that uses it
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
Erik Groeneveld wrote:
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.
Did you know that Andi Vajda has already created a fantastic wrapper for Java called JCC? http://pypi.python.org/pypi/JCC/2.3 Contrary to your project it doesn't create the wrappers in runtime. It analyzes the jar file(s) with JNI, created C++ templates and wraps the C++ code in Python wrappers. JCC even allows you to implement native methods of Java classes in Python. Christian
Hello,
2009/7/8 Erik Groeneveld
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? [...]
There are several changes to do in your code: - Don't define a JObjectMeta struct, use JObjectType directly instead. An instance of the metatype is the type itself! - Don't set JObjectMetaType.tp_basicsize, let it inherit from the base type (the correct value would be sizeof(PyHeapTypeObject), this is important in order to create derived classes in python) - Don't set JObjectMetaType.tp_new, let it inherit from the base type (PyType_GenericNew just allocates memory; types are more complex...) - JObjectType.tp_base = &JObjectMetaType" is wrong, it should be "JObjectType.ob_type = &JObjectMetaType;", or better to be compatible with python3: "Py_TYPE(JObjectType) = &JObjectMetaType;" In summary, I made your example work with: JObjectMetaType.tp_name = "metaclass.JObjectMeta"; JObjectMetaType.tp_flags = Py_TPFLAGS_DEFAULT; JObjectMetaType.tp_doc = "JObjectMeta objects"; JObjectMetaType.tp_init = JObjectMeta_init; JObjectMetaType.tp_base = &PyType_Type; JObjectMetaType.tp_getattro = JObjectMeta_getattro; Py_TYPE(&JObjectType) = &JObjectMetaType; JObjectType.tp_name = "metaclass.JObject"; JObjectType.tp_basicsize = sizeof(JObject); JObjectType.tp_flags = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE; JObjectType.tp_doc = "JObject objects"; JObjectType.tp_init = JObject_init; -- Amaury Forgeot d'Arc
Amaury,
Thank you very much for your detailed explanation. It helps to
understand it better, and it mostly works now. There is one thing
however:
On Wed, Jul 8, 2009 at 17:35, Amaury Forgeot d'Arc
- Don't define a JObjectMeta struct, use JObjectType directly instead. An instance of the metatype is the type itself! - Don't set JObjectMetaType.tp_basicsize, let it inherit from the base type (the correct value would be sizeof(PyHeapTypeObject), this is important in order to create derived classes in python)
I'd like to add a C pointer field to the metatype instance (the type). So, contrary to your advice, I have defined: typedef struct { PyHeapTypeObject x; void* p; } JObjectMeta; This seems the way to do it for objects, but for types, it doesn't seem right, as the p member turns out to be overwritten unexpectedly at runtime. Reading Python's object.h file it turns out that PyHeapTypeObject 'extends' PyTypeObject, which in turn has a PyObject_VAR_HEAD init macro. So mustn't: PyTypeObject JObjectMetaType = { PyObject_HEAD_INIT(NULL) }; actually be: PyTypeObject JObjectMetaType = { PyVarObject_HEAD_INIT(NULL, 1) }; with: JObjectMetaType.tp_basic_size = sizeof(JObjectMeta); JObjectMetaType.tp_itemsize = sizeof(void*); I tried this, but it doesn't keep my app from dumping core on an overwritten 'p'. My question basically is: how can I define a pointer for each type created with this metatype, such as is intended by the JObjectMeta struct? Best regards Erik Groeneveld
Hi,
2009/7/13 Erik Groeneveld
Amaury,
Thank you very much for your detailed explanation. It helps to understand it better, and it mostly works now. There is one thing however:
On Wed, Jul 8, 2009 at 17:35, Amaury Forgeot d'Arc
wrote: - Don't define a JObjectMeta struct, use JObjectType directly instead. An instance of the metatype is the type itself! - Don't set JObjectMetaType.tp_basicsize, let it inherit from the base type (the correct value would be sizeof(PyHeapTypeObject), this is important in order to create derived classes in python)
I'd like to add a C pointer field to the metatype instance (the type). So, contrary to your advice, I have defined:
typedef struct { PyHeapTypeObject x; void* p; } JObjectMeta;
This seems the way to do it for objects, but for types, it doesn't seem right, as the p member turns out to be overwritten unexpectedly at runtime.
Reading Python's object.h file it turns out that PyHeapTypeObject 'extends' PyTypeObject, which in turn has a PyObject_VAR_HEAD init macro. So mustn't:
PyTypeObject JObjectMetaType = { PyObject_HEAD_INIT(NULL) };
actually be:
PyTypeObject JObjectMetaType = { PyVarObject_HEAD_INIT(NULL, 1) };
with:
JObjectMetaType.tp_basic_size = sizeof(JObjectMeta); JObjectMetaType.tp_itemsize = sizeof(void*);
I tried this, but it doesn't keep my app from dumping core on an overwritten 'p'.
My question basically is: how can I define a pointer for each type created with this metatype, such as is intended by the JObjectMeta struct?
The best is probably to store it in the class dictionary: PyObject_SetAttrString(self, "_javatype_", PyLong_FromVoidPtr(p)); -- Amaury Forgeot d'Arc
participants (3)
-
Amaury Forgeot d'Arc
-
Christian Heimes
-
Erik Groeneveld