summaryrefslogtreecommitdiff
path: root/lang_ext
diff options
context:
space:
mode:
authorJoshua Haberman <joshua@reverberate.org>2009-08-16 12:00:32 -0700
committerJoshua Haberman <joshua@reverberate.org>2009-08-16 12:00:32 -0700
commita223f9af30738cf00c313fabee8de75d04fb9a1a (patch)
treedd8ad3fe6f8280995f69babc83c59666c854186c /lang_ext
parentf00091f340122f3fc0a3c6d7da2aff8a83f5506d (diff)
More work on Python extension, build libupb PIC.
Diffstat (limited to 'lang_ext')
-rw-r--r--lang_ext/python/definition.c148
-rw-r--r--lang_ext/python/setup.py4
2 files changed, 107 insertions, 45 deletions
diff --git a/lang_ext/python/definition.c b/lang_ext/python/definition.c
index 04e377a..6a788ab 100644
--- a/lang_ext/python/definition.c
+++ b/lang_ext/python/definition.c
@@ -22,6 +22,7 @@
#include "definition.h"
#include "upb_context.h"
+#include "upb_msg.h"
#if PY_MAJOR_VERSION > 3
const char *bytes_format = "y#";
@@ -32,17 +33,39 @@ const char *bytes_format = "s#";
/* upb.def.MessageDefinition **************************************************/
-#if 0
+typedef struct {
+ PyObject_HEAD
+ struct upb_msgdef *def;
+} PyUpb_MsgDef;
+
+PyTypeObject PyUpb_MsgDefType; /* forward decl. */
+
/* Not implemented yet, but these methods will expose information about the
* message definition (the upb_msgdef). */
-static PyMethodDef PyUpb_MessageDefinitionMethods[] = {
+static PyMethodDef msgdef_methods[] = {
+ {NULL, NULL}
};
-PyTypeObject PyUpb_MessageDefinitionType = {
+static PyObject *msgdef_new(struct upb_msgdef *m)
+{
+ PyUpb_MsgDef *md_obj = (void*)PyType_GenericAlloc(&PyUpb_MsgDefType, 0);
+ md_obj->def = m;
+ upb_msgdef_ref(md_obj->def);
+ return (void*)md_obj;
+}
+
+static void msgdef_dealloc(PyObject *obj)
+{
+ PyUpb_MsgDef *md_obj = (void*)obj;
+ upb_msgdef_unref(md_obj->def);
+ obj->ob_type->tp_free(obj);
+}
+
+PyTypeObject PyUpb_MsgDefType = {
PyObject_HEAD_INIT(NULL)
0, /* ob_size */
"upb.definition.MessageDefinition", /* tp_name */
- sizeof(PyUpb_MessageDefinition), /* tp_basicsize */
+ sizeof(PyUpb_MsgDef), /* tp_basicsize */
0, /* tp_itemsize */
msgdef_dealloc, /* tp_dealloc */
0, /* tp_print */
@@ -80,13 +103,13 @@ PyTypeObject PyUpb_MessageDefinitionType = {
0, /* Can't be created in Python. */ /* tp_new */
0, /* tp_free */
};
-#endif
/* upb.Context ****************************************************************/
typedef struct {
PyObject_HEAD
struct upb_context *context;
+ PyObject *created_defs;
} PyUpb_Context;
static PyTypeObject PyUpb_ContextType; /* forward decl. */
@@ -115,37 +138,70 @@ static PyObject *context_parsefds(PyObject *_context, PyObject *args)
Py_RETURN_NONE;
}
-//static PyObject *context_lookup(PyObject *self, PyObject *args)
-//{
-// PyUpb_Context *context = CheckContext(self);
-// struct upb_string str;
-// if(!PyArg_ParseTuple(args, "s#", &str.ptr, &str.byte_len))
-// return NULL;
-// str.byte_size = 0; /* We don't own that mem. */
-//
-// struct upb_symtab_entry e;
-// if(upb_context_lookup(context->context, &str, &e)) {
-// return get_or_create_def(&e);
-// } else {
-// Py_RETURN_NONE;
-// }
-//}
-//
-//static PyObject *context_resolve(PyObject *self, PyObject *args)
-//{
-// PyUpb_Context *context = CheckContext(self);
-// struct upb_string str;
-// if(!PyArg_ParseTuple(args, "s#", &str.ptr, &str.byte_len))
-// return NULL;
-// str.byte_size = 0; /* We don't own that mem. */
-//
-// struct upb_symtab_entry e;
-// if(upb_context_resolve(context->context, &str, &e)) {
-// return get_or_create_def(&e);
-// } else {
-// Py_RETURN_NONE;
-// }
-//}
+static PyObject *get_or_create_def(PyUpb_Context *context,
+ struct upb_symtab_entry *e)
+{
+ /* Check out internal dictionary of Python classes we have already created
+ * (keyed by the address of the obj we are referencing). */
+#if PY_MAJOR_VERSION > 3
+ PyObject *str = PyBytes_FromStringAndSize((char*)&e->ref, sizeof(void*));
+#else
+ PyObject *str = PyString_FromStringAndSize((char*)&e->ref, sizeof(void*));
+#endif
+ /* Would use PyDict_GetItemStringAndSize() if it existed, but only
+ * PyDict_GetItemString() exists, and pointers could have NULL bytes. */
+ PyObject *def = PyDict_GetItem(context->created_defs, str);
+ if(!def) {
+ switch(e->type) {
+ case UPB_SYM_MESSAGE:
+ def = msgdef_new(e->ref.msg);
+ break;
+ case UPB_SYM_ENUM:
+ case UPB_SYM_SERVICE:
+ case UPB_SYM_EXTENSION:
+ default:
+ def = NULL;
+ break;
+ }
+ if(def) PyDict_SetItem(context->created_defs, str, def);
+ }
+ Py_DECREF(str);
+ return def;
+}
+
+static PyObject *context_lookup(PyObject *self, PyObject *args)
+{
+ PyUpb_Context *context = CheckContext(self);
+ struct upb_string str;
+ if(!PyArg_ParseTuple(args, "s#", &str.ptr, &str.byte_len))
+ return NULL;
+ str.byte_size = 0; /* We don't own that mem. */
+
+ struct upb_symtab_entry e;
+ if(upb_context_lookup(context->context, &str, &e)) {
+ return get_or_create_def(context, &e);
+ } else {
+ Py_RETURN_NONE;
+ }
+}
+
+static PyObject *context_resolve(PyObject *self, PyObject *args)
+{
+ PyUpb_Context *context = CheckContext(self);
+ struct upb_string str;
+ struct upb_string base;
+ if(!PyArg_ParseTuple(args, "s#s#", &base.ptr, &base.byte_len,
+ &str.ptr, &str.byte_len))
+ return NULL;
+ str.byte_size = 0; /* We don't own that mem. */
+
+ struct upb_symtab_entry e;
+ if(upb_context_resolve(context->context, &base, &str, &e)) {
+ return get_or_create_def(context, &e);
+ } else {
+ Py_RETURN_NONE;
+ }
+}
static void add_string(void *udata, struct upb_symtab_entry *entry)
{
@@ -154,6 +210,7 @@ static void add_string(void *udata, struct upb_symtab_entry *entry)
/* TODO: check return. */
PyObject *str = PyString_FromStringAndSize(s->ptr, s->byte_len);
PyList_Append(list, str);
+ Py_DECREF(str);
}
static PyObject *context_symbols(PyObject *self, PyObject *args)
@@ -169,13 +226,13 @@ static PyMethodDef context_methods[] = {
"Parses a string containing a serialized FileDescriptorSet and adds its "
"definitions to the context."
},
- //{"lookup", context_lookup, METH_VARARGS,
- // "Finds a symbol by fully-qualified name (eg. foo.bar.MyType)."
- //},
- //{"resolve", context_resolve, METH_VARARGS,
- // "Finds a symbol by a possibly-relative name, which will be interpreted "
- // "in the context of the given base."
- //}
+ {"lookup", context_lookup, METH_VARARGS,
+ "Finds a symbol by fully-qualified name (eg. foo.bar.MyType)."
+ },
+ {"resolve", context_resolve, METH_VARARGS,
+ "Finds a symbol by a possibly-relative name, which will be interpreted "
+ "in the context of the given base."
+ },
{"symbols", context_symbols, METH_NOARGS,
"Returns a list of symbol names that are defined in this context."
},
@@ -187,6 +244,7 @@ static PyObject *context_new(PyTypeObject *subtype,
{
PyUpb_Context *obj = (void*)subtype->tp_alloc(subtype, 0);
obj->context = upb_context_new();
+ obj->created_defs = PyDict_New();
return (void*)obj;
}
@@ -194,6 +252,8 @@ static void context_dealloc(PyObject *obj)
{
PyUpb_Context *c = (void*)obj;
upb_context_unref(c->context);
+ Py_DECREF(c->created_defs);
+ obj->ob_type->tp_free(obj);
}
static PyTypeObject PyUpb_ContextType = {
@@ -247,6 +307,8 @@ initdefinition(void)
{
if(PyType_Ready(&PyUpb_ContextType) < 0) return;
Py_INCREF(&PyUpb_ContextType); /* TODO: necessary? */
+ if(PyType_Ready(&PyUpb_MsgDefType) < 0) return;
+ Py_INCREF(&PyUpb_MsgDefType); /* TODO: necessary? */
PyObject *mod = Py_InitModule("upb.definition", methods);
PyModule_AddObject(mod, "Context", (PyObject*)&PyUpb_ContextType);
diff --git a/lang_ext/python/setup.py b/lang_ext/python/setup.py
index de937c4..66862f3 100644
--- a/lang_ext/python/setup.py
+++ b/lang_ext/python/setup.py
@@ -2,10 +2,10 @@ from distutils.core import setup, Extension
setup(name='upb',
version='0.1',
ext_modules=[Extension('upb.definition', ['definition.c'],
- include_dirs=['../../src'],
+ include_dirs=['../../src', '../../descriptor'],
define_macros=[("UPB_USE_PTHREADS", 1),
("UPB_UNALIGNED_READS_OK", 1)],
library_dirs=['../../src'],
- libraries=['upb']
+ libraries=['upb_pic']
)],
)
generated by cgit on debian on lair
contact matthew@masot.net with questions or feedback