Add initial python bindings for the scanner and depend on python 2.5.
authorJohan Dahlin <johan@gnome.org>
Tue, 25 Mar 2008 21:47:47 +0000 (21:47 +0000)
committerJohan Dahlin <johan@src.gnome.org>
Tue, 25 Mar 2008 21:47:47 +0000 (21:47 +0000)
2008-03-25  Johan Dahlin  <johan@gnome.org>

        * configure.ac:
        * giscanner:
        * giscanner/__init__.py:
        * giscanner/giscannermodule.c:
        * giscanner/Makefile.am:

        Add initial python bindings for the scanner and
        depend on python 2.5.

svn path=/trunk/; revision=165

ChangeLog
configure.ac
giscanner/Makefile.am
giscanner/__init__.py [new file with mode: 0644]
giscanner/giscannermodule.c [new file with mode: 0644]
m4/python.m4 [new file with mode: 0644]

index 20be8f6ddfa6714a6b3e372ed4a0962900b90a39..29bb7cf65a2c27074861636410329ed1e7ddbb37 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,14 @@
+2008-03-25  Johan Dahlin  <johan@gnome.org>
+       
+       * configure.ac:
+       * giscanner:
+       * giscanner/__init__.py:
+       * giscanner/giscannermodule.c:
+       * giscanner/Makefile.am:
+
+       Add initial python bindings for the scanner and 
+       depend on python 2.5.
+
 2008-03-25  Johan Dahlin  <johan@gnome.org>
 
        * Makefile.am:
index 5ca163dff285328e097d87c55fb4e32ac083bf0f..51d44f85eee92662e7020dd59bdfd51ded35119b 100644 (file)
@@ -90,6 +90,12 @@ AC_C_CONST
 AC_FUNC_STRTOD
 AC_CHECK_FUNCS([memchr strchr strspn strstr strtol strtoull])
 
+# Python
+
+AC_MSG_CHECKING([whether Python support is requested])
+
+AM_PATH_PYTHON([2.5])
+AM_CHECK_PYTHON_HEADERS
 
 AC_CONFIG_FILES([Makefile
                  gidl/Makefile
index 30ed3352747248c89692f303262bf7643107f878..4ed31069627f05c9b9dd1d5b4ee0c72aa8189bcf 100644 (file)
@@ -22,4 +22,25 @@ libgiscanner_la_CFLAGS = $(GOBJECT_CFLAGS)
 
 GCOVSOURCES = $(libgiscanner_la_SOURCES)
 
+# Python module
+pyexec_LTLIBRARIES = _giscanner.la
+pyexec_PYTHON = __init__.py
+
+_giscanner_la_CFLAGS = \
+       $(PYTHON_INCLUDES) \
+       $(GOBJECT_CFLAGS) \
+       -I$(top_srcdir)/giscanner
+_giscanner_la_LIBADD = $(GOBJECT_LIBS) libgiscanner.la
+_giscanner_la_LDFLAGS = \
+       -module -avoid-version -export-symbols-regex init_giscanner
+_giscanner_la_SOURCES = giscannermodule.c
+
+BUILT_SOURCES += _giscanner.so
+CLEANFILES += _giscanner.so
+
+# Yuck, ugly but...
+_giscanner.so: _giscanner.la
+       ln -sf .libs/_giscanner.so .
+
+
 include $(top_srcdir)/gcov.mak
diff --git a/giscanner/__init__.py b/giscanner/__init__.py
new file mode 100644 (file)
index 0000000..aff773a
--- /dev/null
@@ -0,0 +1 @@
+from _giscanner import *
diff --git a/giscanner/giscannermodule.c b/giscanner/giscannermodule.c
new file mode 100644 (file)
index 0000000..b9245f2
--- /dev/null
@@ -0,0 +1,257 @@
+/* GObject introspection: scanner
+ *
+ * Copyright (C) 2008
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#  include "config.h"
+#endif
+#include "sourcescanner.h"
+#include <Python.h>
+
+#define NEW_CLASS(ctype, name, cname)        \
+static PyMethodDef _Py##cname##_methods[];    \
+PyTypeObject Py##cname##_Type = {             \
+    PyObject_HEAD_INIT(NULL)                  \
+    0,                                       \
+    "scanner." name,                          \
+    sizeof(ctype),                           \
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0,            \
+    0, 0, 0, 0,        0, 0,                         \
+    Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, \
+    NULL, 0, 0, 0,                           \
+    0,       \
+    0, 0,                                     \
+    0,                                        \
+    0, 0, NULL, NULL, 0, 0,                  \
+    0             \
+}
+
+#define REGISTER_TYPE(d, name, type)         \
+    type.ob_type = &PyType_Type;              \
+    type.tp_alloc = PyType_GenericAlloc;      \
+    type.tp_new = PyType_GenericNew;          \
+    if (PyType_Ready (&type))                 \
+       return;                               \
+    PyDict_SetItemString (d, name, (PyObject *)&type); \
+    Py_INCREF (&type);
+
+typedef struct {
+  PyObject_HEAD
+  GISourceType *type;
+} PyGISourceType;
+
+typedef struct {
+  PyObject_HEAD
+  GISourceSymbol *symbol;
+} PyGISourceSymbol;
+
+typedef struct {
+  PyObject_HEAD
+  GISourceScanner *scanner;
+} PyGISourceScanner;
+
+NEW_CLASS(PyGISourceSymbol, "SourceSymbol", GISourceSymbol);
+NEW_CLASS(PyGISourceType, "SourceType", GISourceType);
+NEW_CLASS(PyGISourceScanner, "SourceScanner", GISourceScanner);
+
+
+/* Symbol */
+
+static PyObject *
+symbol_get_type(PyGISourceSymbol *self,
+               void             *context)
+{
+  return PyInt_FromLong(self->symbol->type);
+}
+
+static PyObject *
+symbol_get_ident(PyGISourceSymbol *self,
+                 void            *context)
+{
+  return PyString_FromString(self->symbol->ident);
+}
+
+static PyObject *
+symbol_get_base_type(PyGISourceSymbol *self,
+                    void             *context)
+{
+  PyGISourceType *item;
+  item = (PyGISourceType *)PyObject_GC_New(PyGISourceType,
+                                          &PyGISourceType_Type);
+  item->type = self->symbol->base_type;
+  return (PyObject*)item;
+}
+
+static PyGetSetDef _PyGISourceSymbol_getsets[] = {
+  { "type", (getter)symbol_get_type, NULL, NULL},
+  { "ident", (getter)symbol_get_ident, NULL, NULL},
+  { "base_type", (getter)symbol_get_base_type, NULL, NULL},
+  { 0 }
+};
+
+
+
+/* Type */
+
+static PyObject *
+type_get_type(PyGISourceType *self,
+             void           *context)
+{
+  return PyInt_FromLong(self->type->type);
+}
+
+static PyObject *
+type_get_name(PyGISourceType *self,
+             void           *context)
+{
+  if (!self->type->name)
+    {
+      Py_INCREF(Py_None);
+      return Py_None;
+    }
+    
+  return PyString_FromString(self->type->name);
+}
+
+static PyGetSetDef _PyGISourceType_getsets[] = {
+  { "type", (getter)type_get_type, NULL, NULL},
+  { "name", (getter)type_get_name, NULL, NULL},
+  { 0 }
+};
+
+
+
+/* Scanner */
+
+static int
+pygi_source_scanner_init (PyGISourceScanner *self,
+                         PyObject          *args,
+                         PyObject          *kwargs)
+{
+  if (!PyArg_ParseTuple (args, ":SourceScanner.__init__"))
+    return -1;
+
+  self->scanner = gi_source_scanner_new ();
+
+  return 0;
+}
+
+static PyObject *
+pygi_source_scanner_parse_file (PyGISourceScanner *self,
+                               PyObject          *args)
+{
+  char *filename;
+  FILE *fp;
+  
+  if (!PyArg_ParseTuple (args, "s:SourceScanner.__init__", &filename))
+    return NULL;
+
+  fp = fopen (filename, "r");
+  if (!fp)
+    {
+      PyErr_SetFromErrnoWithFilename (PyExc_OSError, filename);
+      return NULL;
+    }
+
+  self->scanner->filenames =
+    g_list_append (self->scanner->filenames, g_strdup (filename));
+  self->scanner->current_filename = self->scanner->filenames->data;
+  
+  if (!gi_source_scanner_parse_file (self->scanner, fp))
+    {
+      g_print ("Something went wrong..\n");
+      return NULL;
+    }
+
+  fclose (fp);
+
+  Py_INCREF (Py_None);
+  return Py_None;
+}
+
+static PyObject *
+pygi_source_scanner_set_macro_scan (PyGISourceScanner *self,
+                                   PyObject          *args)
+{
+  int macro_scan;
+  
+  if (!PyArg_ParseTuple (args, "b:SourceScanner.set_macro_scan", &macro_scan))
+    return NULL;
+
+  gi_source_scanner_set_macro_scan (self->scanner, macro_scan);
+
+  Py_INCREF (Py_None);
+  return Py_None;
+}
+
+static PyObject *
+pygi_source_scanner_get_symbols (PyGISourceScanner *self)
+{
+  GSList *l, *symbols;
+  PyObject *list;
+  int i = 0;
+  
+  symbols = gi_source_scanner_get_symbols (self->scanner);
+  list = PyList_New (g_slist_length (symbols));
+  
+  for (l = symbols; l; l = l->next)
+    {
+      PyGISourceSymbol *item;
+      item = (PyGISourceSymbol *)PyObject_GC_New(PyGISourceSymbol,
+                                                &PyGISourceSymbol_Type);
+      item->symbol = l->data;
+      PyList_SetItem(list, i++, (PyObject*)item);
+    }
+  
+  return list;
+}
+
+static PyMethodDef _PyGISourceScanner_methods[] = {
+  { "get_symbols", (PyCFunction) pygi_source_scanner_get_symbols, METH_NOARGS },
+  { "parse_file", (PyCFunction) pygi_source_scanner_parse_file, METH_VARARGS },
+  { "set_macro_scan", (PyCFunction) pygi_source_scanner_set_macro_scan, METH_VARARGS },
+  { NULL, NULL, 0 }
+};
+
+
+/* Module */
+
+PyMethodDef pyscanner_functions[] = {
+  { NULL, NULL, 0, NULL }
+};
+
+DL_EXPORT(void)
+init_giscanner(void)
+{
+    PyObject *m, *d;
+
+    m = Py_InitModule ("giscanner._giscanner", pyscanner_functions);
+    d = PyModule_GetDict (m);
+
+    PyGISourceScanner_Type.tp_init = (initproc)pygi_source_scanner_init;
+    PyGISourceScanner_Type.tp_methods = _PyGISourceScanner_methods;
+    REGISTER_TYPE (d, "SourceScanner", PyGISourceScanner_Type);
+
+    PyGISourceSymbol_Type.tp_getset = _PyGISourceSymbol_getsets;
+    REGISTER_TYPE (d, "SourceSymbol", PyGISourceSymbol_Type);
+
+    PyGISourceType_Type.tp_getset = _PyGISourceType_getsets;
+    REGISTER_TYPE (d, "SourceType", PyGISourceType_Type);
+}
diff --git a/m4/python.m4 b/m4/python.m4
new file mode 100644 (file)
index 0000000..aff5537
--- /dev/null
@@ -0,0 +1,25 @@
+## this one is commonly used with AM_PATH_PYTHONDIR ...
+dnl a macro to check for ability to create python extensions
+dnl  AM_CHECK_PYTHON_HEADERS([ACTION-IF-POSSIBLE], [ACTION-IF-NOT-POSSIBLE])
+dnl function also defines PYTHON_INCLUDES
+AC_DEFUN([AM_CHECK_PYTHON_HEADERS],
+[AC_REQUIRE([AM_PATH_PYTHON])
+AC_MSG_CHECKING(for headers required to compile python extensions)
+dnl deduce PYTHON_INCLUDES
+py_prefix=`$PYTHON -c "import sys; print sys.prefix"`
+py_exec_prefix=`$PYTHON -c "import sys; print sys.exec_prefix"`
+PYTHON_INCLUDES="-I${py_prefix}/include/python${PYTHON_VERSION}"
+if test "$py_prefix" != "$py_exec_prefix"; then
+  PYTHON_INCLUDES="$PYTHON_INCLUDES -I${py_exec_prefix}/include/python${PYTHON_VERSION}"
+fi
+AC_SUBST(PYTHON_INCLUDES)
+dnl check if the headers exist:
+save_CPPFLAGS="$CPPFLAGS"
+CPPFLAGS="$CPPFLAGS $PYTHON_INCLUDES"
+AC_TRY_CPP([#include <Python.h>],dnl
+[AC_MSG_RESULT(found)
+$1],dnl
+[AC_MSG_RESULT(not found)
+$2])
+CPPFLAGS="$save_CPPFLAGS"
+])