/* -*- Mode: C; c-basic-offset: 4 -*- */ #ifdef HAVE_CONFIG_H # include #endif #include "pygobject-private.h" static PyObject *gerror_exc = NULL; /* -------------- GDK threading hooks ---------------------------- */ static void pyg_set_thread_block_funcs (PyGThreadBlockFunc block_threads_func, PyGThreadBlockFunc unblock_threads_func) { g_return_if_fail(pygobject_api_functions.block_threads == NULL && pygobject_api_functions.unblock_threads == NULL); pygobject_api_functions.block_threads = block_threads_func; pygobject_api_functions.unblock_threads = unblock_threads_func; } static void object_free(PyObject *op) { PyObject_FREE(op); } void pyg_destroy_notify(gpointer user_data) { PyObject *obj = (PyObject *)user_data; pyg_block_threads(); Py_DECREF(obj); pyg_unblock_threads(); } /* -------------- GParamSpec objects ---------------------------- */ static int pyg_param_spec_compare(PyGParamSpec *self, PyGParamSpec *v) { if (self->pspec == v->pspec) return 0; if (self->pspec > v->pspec) return -1; return 1; } static long pyg_param_spec_hash(PyGParamSpec *self) { return (long)self->pspec; } static PyObject * pyg_param_spec_repr(PyGParamSpec *self) { char buf[80]; g_snprintf(buf, sizeof(buf), "<%s '%s'>", G_PARAM_SPEC_TYPE_NAME(self->pspec), g_param_spec_get_name(self->pspec)); return PyString_FromString(buf); } static void pyg_param_spec_dealloc(PyGParamSpec *self) { g_param_spec_unref(self->pspec); PyObject_DEL(self); } static PyObject * pyg_param_spec_getattr(PyGParamSpec *self, const gchar *attr) { if (!strcmp(attr, "__members__")) { return Py_BuildValue("[ssssssss]", "__doc__", "__gtype__", "blurb", "flags", "name", "nick", "owner_type", "value_type"); } else if (!strcmp(attr, "__gtype__")) { return pyg_type_wrapper_new(G_PARAM_SPEC_TYPE(self->pspec)); } else if (!strcmp(attr, "name")) { const gchar *name = g_param_spec_get_name(self->pspec); if (name) return PyString_FromString(name); Py_INCREF(Py_None); return Py_None; } else if (!strcmp(attr, "nick")) { const gchar *nick = g_param_spec_get_nick(self->pspec); if (nick) return PyString_FromString(nick); Py_INCREF(Py_None); return Py_None; } else if (!strcmp(attr, "blurb") || !strcmp(attr, "__doc__")) { const gchar *blurb = g_param_spec_get_blurb(self->pspec); if (blurb) return PyString_FromString(blurb); Py_INCREF(Py_None); return Py_None; } else if (!strcmp(attr, "flags")) { return PyInt_FromLong(self->pspec->flags); } else if (!strcmp(attr, "value_type")) { return pyg_type_wrapper_new(self->pspec->value_type); } else if (!strcmp(attr, "owner_type")) { return pyg_type_wrapper_new(self->pspec->owner_type); } PyErr_SetString(PyExc_AttributeError, attr); return NULL; } PyTypeObject PyGParamSpec_Type = { PyObject_HEAD_INIT(NULL) 0, "gobject.GParamSpec", sizeof(PyGParamSpec), 0, (destructor)pyg_param_spec_dealloc, (printfunc)0, (getattrfunc)pyg_param_spec_getattr, (setattrfunc)0, (cmpfunc)pyg_param_spec_compare, (reprfunc)pyg_param_spec_repr, 0, 0, 0, (hashfunc)pyg_param_spec_hash, (ternaryfunc)0, (reprfunc)0, 0L,0L,0L,0L, NULL }; PyObject * pyg_param_spec_new(GParamSpec *pspec) { PyGParamSpec *self; self = (PyGParamSpec *)PyObject_NEW(PyGParamSpec, &PyGParamSpec_Type); if (self == NULL) return NULL; self->pspec = g_param_spec_ref(pspec); return (PyObject *)self; } /* ---------------- GBoxed functions -------------------- */ GType PY_TYPE_OBJECT = 0; static gpointer pyobject_copy(gpointer boxed) { PyObject *object = boxed; Py_INCREF(object); return object; } static void pyobject_free(gpointer boxed) { PyObject *object = boxed; Py_DECREF(object); } /* ---------------- GInterface functions -------------------- */ static int pyg_interface_init(PyObject *self, PyObject *args, PyObject *kwargs) { gchar buf[512]; if (!PyArg_ParseTuple(args, ":GInterface.__init__")) return -1; g_snprintf(buf, sizeof(buf), "%s can not be constructed", self->ob_type->tp_name); PyErr_SetString(PyExc_NotImplementedError, buf); return -1; } static PyTypeObject PyGInterface_Type = { PyObject_HEAD_INIT(NULL) 0, /* ob_size */ "gobject.GInterface", /* tp_name */ sizeof(PyObject), /* tp_basicsize */ 0, /* tp_itemsize */ /* methods */ (destructor)0, /* tp_dealloc */ (printfunc)0, /* tp_print */ (getattrfunc)0, /* tp_getattr */ (setattrfunc)0, /* tp_setattr */ (cmpfunc)0, /* tp_compare */ (reprfunc)0, /* tp_repr */ 0, /* tp_as_number */ 0, /* tp_as_sequence */ 0, /* tp_as_mapping */ (hashfunc)0, /* tp_hash */ (ternaryfunc)0, /* tp_call */ (reprfunc)0, /* tp_str */ (getattrofunc)0, /* tp_getattro */ (setattrofunc)0, /* tp_setattro */ 0, /* tp_as_buffer */ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ NULL, /* Documentation string */ (traverseproc)0, /* tp_traverse */ (inquiry)0, /* tp_clear */ (richcmpfunc)0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ (getiterfunc)0, /* tp_iter */ (iternextfunc)0, /* tp_iternext */ 0, /* tp_methods */ 0, /* tp_members */ 0, /* tp_getset */ (PyTypeObject *)0, /* tp_base */ (PyObject *)0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ (initproc)pyg_interface_init, /* tp_init */ PyType_GenericAlloc, /* tp_alloc */ PyType_GenericNew, /* tp_new */ object_free, /* tp_free */ (inquiry)0, /* tp_is_gc */ (PyObject *)0, /* tp_bases */ }; static void pyg_register_interface(PyObject *dict, const gchar *class_name, GType gtype, PyTypeObject *type) { PyObject *o; type->ob_type = &PyType_Type; type->tp_base = &PyGInterface_Type; if (PyType_Ready(type) < 0) { g_warning("could not ready `%s'", type->tp_name); return; } if (gtype) { o = pyg_type_wrapper_new(gtype); PyDict_SetItemString(type->tp_dict, "__gtype__", o); Py_DECREF(o); } PyDict_SetItemString(dict, (char *)class_name, (PyObject *)type); } /* ---------------- gobject module functions -------------------- */ static PyObject * pyg_type_name (PyObject *self, PyObject *args) { PyObject *gtype; GType type; const gchar *name; if (!PyArg_ParseTuple(args, "O:gobject.type_name", >ype)) return NULL; if ((type = pyg_type_from_object(gtype)) == 0) return NULL; name = g_type_name(type); if (name) return PyString_FromString(name); PyErr_SetString(PyExc_RuntimeError, "unknown typecode"); return NULL; } static PyObject * pyg_type_from_name (PyObject *self, PyObject *args) { const gchar *name; GType type; if (!PyArg_ParseTuple(args, "s:gobject.type_from_name", &name)) return NULL; type = g_type_from_name(name); if (type != 0) return pyg_type_wrapper_new(type); PyErr_SetString(PyExc_RuntimeError, "unknown type name"); return NULL; } static PyObject * pyg_type_parent (PyObject *self, PyObject *args) { PyObject *gtype; GType type, parent; if (!PyArg_ParseTuple(args, "O:gobject.type_parent", >ype)) return NULL; if ((type = pyg_type_from_object(gtype)) == 0) return NULL; parent = g_type_parent(type); if (parent != 0) return pyg_type_wrapper_new(parent); PyErr_SetString(PyExc_RuntimeError, "no parent for type"); return NULL; } static PyObject * pyg_type_is_a (PyObject *self, PyObject *args) { PyObject *gtype, *gparent; GType type, parent; if (!PyArg_ParseTuple(args, "OO:gobject.type_is_a", >ype, &gparent)) return NULL; if ((type = pyg_type_from_object(gtype)) == 0) return NULL; if ((parent = pyg_type_from_object(gparent)) == 0) return NULL; return PyInt_FromLong(g_type_is_a(type, parent)); } static PyObject * pyg_type_children (PyObject *self, PyObject *args) { PyObject *gtype, *list; GType type, *children; guint n_children, i; if (!PyArg_ParseTuple(args, "O:gobject.type_children", >ype)) return NULL; if ((type = pyg_type_from_object(gtype)) == 0) return NULL; children = g_type_children(type, &n_children); if (children) { list = PyList_New(0); for (i = 0; i < n_children; i++) { PyObject *o; PyList_Append(list, o=pyg_type_wrapper_new(children[i])); Py_DECREF(o); } g_free(children); return list; } PyErr_SetString(PyExc_RuntimeError, "invalid type, or no children"); return NULL; } static PyObject * pyg_type_interfaces (PyObject *self, PyObject *args) { PyObject *gtype, *list; GType type, *interfaces; guint n_interfaces, i; if (!PyArg_ParseTuple(args, "O:gobject.type_interfaces", >ype)) return NULL; if ((type = pyg_type_from_object(gtype)) == 0) return NULL; interfaces = g_type_interfaces(type, &n_interfaces); if (interfaces) { list = PyList_New(0); for (i = 0; i < n_interfaces; i++) { PyObject *o; PyList_Append(list, o=pyg_type_wrapper_new(interfaces[i])); Py_DECREF(o); } g_free(interfaces); return list; } PyErr_SetString(PyExc_RuntimeError, "invalid type, or no interfaces"); return NULL; } static void pyg_object_set_property (GObject *object, guint property_id, const GValue *value, GParamSpec *pspec) { PyObject *object_wrapper, *retval; PyObject *py_pspec, *py_value; object_wrapper = pygobject_new(object); g_return_if_fail(object_wrapper != NULL); py_pspec = pyg_param_spec_new(pspec); py_value = pyg_value_as_pyobject (value, TRUE); retval = PyObject_CallMethod(object_wrapper, "do_set_property", "OO", py_pspec, py_value); if (retval) { Py_DECREF(retval); } else { PyErr_Print(); PyErr_Clear(); } Py_DECREF(py_pspec); Py_DECREF(py_value); } static void pyg_object_get_property (GObject *object, guint property_id, GValue *value, GParamSpec *pspec) { PyObject *object_wrapper, *retval; PyObject *py_pspec; object_wrapper = pygobject_new(object); g_return_if_fail(object_wrapper != NULL); py_pspec = pyg_param_spec_new(pspec); retval = PyObject_CallMethod(object_wrapper, "do_get_property", "O", py_pspec); if (retval == NULL || pyg_value_from_pyobject(value, retval) < 0) { PyErr_Print(); PyErr_Clear(); } Py_XDECREF(retval); Py_DECREF(py_pspec); } static void pyg_object_class_init(GObjectClass *class, PyObject *py_class) { class->set_property = pyg_object_set_property; class->get_property = pyg_object_get_property; } static gboolean create_signal (GType instance_type, const gchar *signal_name, PyObject *tuple) { GSignalFlags signal_flags; PyObject *py_return_type, *py_param_types; GType return_type; guint n_params, i; GType *param_types; guint signal_id; if (!PyArg_ParseTuple(tuple, "iOO", &signal_flags, &py_return_type, &py_param_types)) { gchar buf[128]; PyErr_Clear(); g_snprintf(buf, sizeof(buf), "value for __gsignals__['%s'] not in correct format", signal_name); PyErr_SetString(PyExc_TypeError, buf); return FALSE; } return_type = pyg_type_from_object(py_return_type); if (!return_type) return FALSE; if (!PySequence_Check(py_param_types)) { gchar buf[128]; g_snprintf(buf, sizeof(buf), "third element of __gsignals__['%s'] tuple must be a sequence", signal_name); PyErr_SetString(PyExc_TypeError, buf); return FALSE; } n_params = PySequence_Length(py_param_types); param_types = g_new(GType, n_params); for (i = 0; i < n_params; i++) { PyObject *item = PySequence_GetItem(py_param_types, i); param_types[i] = pyg_type_from_object(item); if (param_types[i] == 0) { Py_DECREF(item); g_free(param_types); return FALSE; } Py_DECREF(item); } signal_id = g_signal_newv(signal_name, instance_type, signal_flags, pyg_signal_class_closure_get(), (GSignalAccumulator)0, NULL, (GSignalCMarshaller)0, return_type, n_params, param_types); g_free(param_types); if (signal_id == 0) { gchar buf[128]; g_snprintf(buf, sizeof(buf), "could not create signal for %s", signal_name); PyErr_SetString(PyExc_RuntimeError, buf); return FALSE; } return TRUE; } static gboolean override_signal(GType instance_type, const gchar *signal_name) { guint signal_id; signal_id = g_signal_lookup(signal_name, instance_type); if (!signal_id) { gchar buf[128]; g_snprintf(buf, sizeof(buf), "could not look up %s", signal_name); PyErr_SetString(PyExc_TypeError, buf); return FALSE; } g_signal_override_class_closure(signal_id, instance_type, pyg_signal_class_closure_get()); return TRUE; } static gboolean add_signals (GType instance_type, PyObject *signals) { gboolean ret = TRUE; GObjectClass *oclass; int pos = 0; PyObject *key, *value; oclass = g_type_class_ref(instance_type); while (PyDict_Next(signals, &pos, &key, &value)) { const gchar *signal_name; if (!PyString_Check(key)) { PyErr_SetString(PyExc_TypeError, "__gsignals__ keys must be strings"); ret = FALSE; break; } signal_name = PyString_AsString (key); if (value == Py_None || (PyString_Check(value) && !strcmp(PyString_AsString(value), "override"))) { ret = override_signal(instance_type, signal_name); } else { ret = create_signal(instance_type, signal_name, value); } if (!ret) break; } g_type_class_unref(oclass); return ret; } static gboolean create_property (GObjectClass *oclass, const gchar *prop_name, GType prop_type, const gchar *nick, const gchar *blurb, PyObject *args, GParamFlags flags) { GParamSpec *pspec = NULL; switch (G_TYPE_FUNDAMENTAL(prop_type)) { case G_TYPE_CHAR: { gchar minimum, maximum, default_value; if (!PyArg_ParseTuple(args, "ccc", &minimum, &maximum, &default_value)) return FALSE; pspec = g_param_spec_char (prop_name, nick, blurb, minimum, maximum, default_value, flags); } break; case G_TYPE_UCHAR: { gchar minimum, maximum, default_value; if (!PyArg_ParseTuple(args, "ccc", &minimum, &maximum, &default_value)) return FALSE; pspec = g_param_spec_uchar (prop_name, nick, blurb, minimum, maximum, default_value, flags); } break; case G_TYPE_BOOLEAN: { gboolean default_value; if (!PyArg_ParseTuple(args, "i", &default_value)) return FALSE; pspec = g_param_spec_boolean (prop_name, nick, blurb, default_value, flags); } break; case G_TYPE_INT: { gint minimum, maximum, default_value; if (!PyArg_ParseTuple(args, "iii", &minimum, &maximum, &default_value)) return FALSE; pspec = g_param_spec_int (prop_name, nick, blurb, minimum, maximum, default_value, flags); } break; case G_TYPE_UINT: { guint minimum, maximum, default_value; if (!PyArg_ParseTuple(args, "iii", &minimum, &maximum, &default_value)) return FALSE; pspec = g_param_spec_uint (prop_name, nick, blurb, minimum, maximum, default_value, flags); } break; case G_TYPE_LONG: { glong minimum, maximum, default_value; if (!PyArg_ParseTuple(args, "lll", &minimum, &maximum, &default_value)) return FALSE; pspec = g_param_spec_long (prop_name, nick, blurb, minimum, maximum, default_value, flags); } break; case G_TYPE_ULONG: { gulong minimum, maximum, default_value; if (!PyArg_ParseTuple(args, "lll", &minimum, &maximum, &default_value)) return FALSE; pspec = g_param_spec_ulong (prop_name, nick, blurb, minimum, maximum, default_value, flags); } break; case G_TYPE_INT64: { gint64 minimum, maximum, default_value; if (!PyArg_ParseTuple(args, "LLL", &minimum, &maximum, &default_value)) return FALSE; pspec = g_param_spec_int64 (prop_name, nick, blurb, minimum, maximum, default_value, flags); } break; case G_TYPE_UINT64: { guint64 minimum, maximum, default_value; if (!PyArg_ParseTuple(args, "LLL", &minimum, &maximum, &default_value)) return FALSE; pspec = g_param_spec_uint64 (prop_name, nick, blurb, minimum, maximum, default_value, flags); } break; case G_TYPE_ENUM: { gint default_value; if (!PyArg_ParseTuple(args, "i", &default_value)) return FALSE; pspec = g_param_spec_enum (prop_name, nick, blurb, prop_type, default_value, flags); } break; case G_TYPE_FLAGS: { guint default_value; if (!PyArg_ParseTuple(args, "i", &default_value)) return FALSE; pspec = g_param_spec_flags (prop_name, nick, blurb, prop_type, default_value, flags); } break; case G_TYPE_FLOAT: { gfloat minimum, maximum, default_value; if (!PyArg_ParseTuple(args, "fff", &minimum, &maximum, &default_value)) return FALSE; pspec = g_param_spec_float (prop_name, nick, blurb, minimum, maximum, default_value, flags); } break; case G_TYPE_DOUBLE: { gdouble minimum, maximum, default_value; if (!PyArg_ParseTuple(args, "ddd", &minimum, &maximum, &default_value)) return FALSE; pspec = g_param_spec_double (prop_name, nick, blurb, minimum, maximum, default_value, flags); } break; case G_TYPE_STRING: { const gchar *default_value; if (!PyArg_ParseTuple(args, "z", &default_value)) return FALSE; pspec = g_param_spec_string (prop_name, nick, blurb, default_value, flags); } break; case G_TYPE_PARAM: if (!PyArg_ParseTuple(args, "")) return FALSE; pspec = g_param_spec_param (prop_name, nick, blurb, prop_type, flags); break; case G_TYPE_BOXED: if (!PyArg_ParseTuple(args, "")) return FALSE; pspec = g_param_spec_boxed (prop_name, nick, blurb, prop_type, flags); break; case G_TYPE_POINTER: if (!PyArg_ParseTuple(args, "")) return FALSE; pspec = g_param_spec_pointer (prop_name, nick, blurb, flags); break; case G_TYPE_OBJECT: if (!PyArg_ParseTuple(args, "")) return FALSE; pspec = g_param_spec_object (prop_name, nick, blurb, prop_type, flags); break; default: /* unhandled pspec type ... */ break; } if (!pspec) { char buf[128]; g_snprintf(buf, sizeof(buf), "could not create param spec for type %s", g_type_name(prop_type)); PyErr_SetString(PyExc_TypeError, buf); return FALSE; } g_object_class_install_property(oclass, 1, pspec); return TRUE; } static gboolean add_properties (GType instance_type, PyObject *properties) { gboolean ret = TRUE; GObjectClass *oclass; int pos = 0; PyObject *key, *value; oclass = g_type_class_ref(instance_type); while (PyDict_Next(properties, &pos, &key, &value)) { const gchar *prop_name; GType prop_type; const gchar *nick, *blurb; GParamFlags flags; gint val_length; PyObject *slice, *item, *py_prop_type; /* values are of format (type,nick,blurb, type_specific_args, flags) */ if (!PyString_Check(key)) { PyErr_SetString(PyExc_TypeError, "__gproperties__ keys must be strings"); ret = FALSE; break; } prop_name = PyString_AsString (key); if (!PyTuple_Check(value)) { PyErr_SetString(PyExc_TypeError, "__gproperties__ values must be tuples"); ret = FALSE; break; } val_length = PyTuple_Size(value); if (val_length < 4) { PyErr_SetString(PyExc_TypeError, "__gproperties__ values must be at least 4 elements long"); ret = FALSE; break; } slice = PySequence_GetSlice(value, 0, 3); if (!slice) { ret = FALSE; break; } if (!PyArg_ParseTuple(slice, "Ozz", &py_prop_type, &nick, &blurb)) { Py_DECREF(slice); ret = FALSE; break; } Py_DECREF(slice); prop_type = pyg_type_from_object(py_prop_type); if (!prop_type) { ret = FALSE; break; } item = PyTuple_GetItem(value, val_length-1); if (!PyInt_Check(item)) { PyErr_SetString(PyExc_TypeError, "last element in __gproperties__ value tuple must be an int"); ret = FALSE; break; } flags = PyInt_AsLong(item); /* slice is the extra items in the tuple */ slice = PySequence_GetSlice(value, 3, val_length-1); ret = create_property(oclass, prop_name, prop_type, nick, blurb, slice, flags); Py_DECREF(slice); if (!ret) break; } g_type_class_unref(oclass); return ret; } static PyObject * pyg_type_register(PyObject *self, PyObject *args) { PyObject *gtype, *module, *gsignals, *gproperties; PyTypeObject *class; GType parent_type, instance_type; gchar *type_name = NULL; gint i; GTypeQuery query; GTypeInfo type_info = { 0, /* class_size */ (GBaseInitFunc) NULL, (GBaseFinalizeFunc) NULL, (GClassInitFunc) pyg_object_class_init, (GClassFinalizeFunc) NULL, NULL, /* class_data */ 0, /* instance_size */ 0, /* n_preallocs */ (GInstanceInitFunc) NULL }; if (!PyArg_ParseTuple(args, "O:gobject.type_register", &class)) return NULL; if (!PyType_IsSubtype(class, &PyGObject_Type)) { PyErr_SetString(PyExc_TypeError,"argument must be a GObject subclass"); return NULL; } /* find the GType of the parent */ parent_type = pyg_type_from_object((PyObject *)class); if (!parent_type) { return NULL; } /* make name for new widget */ module = PyObject_GetAttrString((PyObject *)class, "__module__"); if (module && PyString_Check(module)) { type_name = g_strconcat(PyString_AsString(module), ".", class->tp_name, NULL); } else { if (module) Py_DECREF(module); else PyErr_Clear(); type_name = g_strdup(class->tp_name); } /* convert '.' in type name to '+', which isn't banned (grumble) */ for (i = 0; type_name[i] != '\0'; i++) if (type_name[i] == '.') type_name[i] = '+'; /* set class_data that will be passed to the class_init function. */ type_info.class_data = class; /* fill in missing values of GTypeInfo struct */ g_type_query(parent_type, &query); type_info.class_size = query.class_size; type_info.instance_size = query.instance_size; /* create new typecode */ instance_type = g_type_register_static(parent_type, type_name, &type_info, 0); g_free(type_name); if (instance_type == 0) { PyErr_SetString(PyExc_RuntimeError, "could not create new GType"); return NULL; } /* store pointer to the class with the GType */ Py_INCREF(class); g_type_set_qdata(instance_type, g_quark_from_string("PyGObject::class"), class); /* set new value of __gtype__ on class */ gtype = pyg_type_wrapper_new(instance_type); PyDict_SetItemString(class->tp_dict, "__gtype__", gtype); Py_DECREF(gtype); /* if no __doc__, set it to the auto doc descriptor */ if (PyDict_GetItemString(class->tp_dict, "__doc__") == NULL) { PyDict_SetItemString(class->tp_dict, "__doc__", pyg_object_descr_doc_get()); } /* we look this up in the instance dictionary, so we don't * accidentally get a parent type's __gsignals__ attribute. */ gsignals = PyDict_GetItemString(class->tp_dict, "__gsignals__"); if (gsignals) { if (!PyDict_Check(gsignals)) { PyErr_SetString(PyExc_TypeError, "__gsignals__ attribute not a dict!"); Py_DECREF(gsignals); return NULL; } if (!add_signals(instance_type, gsignals)) { Py_DECREF(gsignals); return NULL; } PyDict_DelItemString(class->tp_dict, "__gsignals__"); Py_DECREF(gsignals); } else { PyErr_Clear(); } /* we look this up in the instance dictionary, so we don't * accidentally get a parent type's __gsignals__ attribute. */ gproperties = PyDict_GetItemString(class->tp_dict, "__gproperties__"); if (gproperties) { if (!PyDict_Check(gproperties)) { PyErr_SetString(PyExc_TypeError, "__gproperties__ attribute not a dict!"); Py_DECREF(gproperties); return NULL; } if (!add_properties(instance_type, gproperties)) { Py_DECREF(gproperties); return NULL; } PyDict_DelItemString(class->tp_dict, "__gproperties__"); Py_DECREF(gproperties); } else { PyErr_Clear(); } Py_INCREF(Py_None); return Py_None; } static PyObject * pyg_signal_new(PyObject *self, PyObject *args) { gchar *signal_name; PyObject *py_type; GSignalFlags signal_flags; GType return_type; PyObject *py_return_type, *py_param_types; GType instance_type = 0; guint n_params, i; GType *param_types; guint signal_id; if (!PyArg_ParseTuple(args, "sOiOO:gobject.signal_new", &signal_name, &py_type, &signal_flags, &py_return_type, &py_param_types)) return NULL; instance_type = pyg_type_from_object(py_type); if (!instance_type) return NULL; return_type = pyg_type_from_object(py_return_type); if (!return_type) return NULL; if (!PySequence_Check(py_param_types)) { PyErr_SetString(PyExc_TypeError, "argument 5 must be a sequence of GType codes"); return NULL; } n_params = PySequence_Length(py_param_types); param_types = g_new(GType, n_params); for (i = 0; i < n_params; i++) { PyObject *item = PySequence_GetItem(py_param_types, i); param_types[i] = pyg_type_from_object(item); if (param_types[i] == 0) { PyErr_Clear(); Py_DECREF(item); PyErr_SetString(PyExc_TypeError, "argument 5 must be a sequence of GType codes"); return NULL; } Py_DECREF(item); } signal_id = g_signal_newv(signal_name, instance_type, signal_flags, pyg_signal_class_closure_get(), (GSignalAccumulator)0, NULL, (GSignalCMarshaller)0, return_type, n_params, param_types); g_free(param_types); if (signal_id != 0) return PyInt_FromLong(signal_id); PyErr_SetString(PyExc_RuntimeError, "could not create signal"); return NULL; } static PyObject * pyg_signal_list_names (PyObject *self, PyObject *args) { PyObject *py_itype, *list; GObjectClass *class; GType itype; guint n; guint *ids; guint i; if (!PyArg_ParseTuple(args, "O:gobject.signal_list_names", &py_itype)) return NULL; if ((itype = pyg_type_from_object(py_itype)) == 0) return NULL; if (!G_TYPE_IS_INSTANTIATABLE(itype) && !G_TYPE_IS_INTERFACE(itype)) { PyErr_SetString(PyExc_TypeError, "type must be instantiable or an interface"); return NULL; } class = g_type_class_ref(itype); if (!class) { PyErr_SetString(PyExc_RuntimeError, "could not get a reference to type class"); return NULL; } ids = g_signal_list_ids(itype, &n); list = PyTuple_New((gint)n); if (list == NULL) { g_free(ids); g_type_class_unref(class); return NULL; } for (i = 0; i < n; i++) PyTuple_SetItem(list, i, PyString_FromString(g_signal_name(ids[i]))); g_free(ids); g_type_class_unref(class); return list; } static PyObject * pyg_object_class_list_properties (PyObject *self, PyObject *args) { GParamSpec **specs; PyObject *py_itype, *list; GType itype; GObjectClass *class; guint nprops; guint i; if (!PyArg_ParseTuple(args, "O:gobject.list_properties", &py_itype)) return NULL; if ((itype = pyg_type_from_object(py_itype)) == 0) return NULL; if (!g_type_is_a(itype, G_TYPE_OBJECT)) { PyErr_SetString(PyExc_TypeError, "type must be derived from GObject"); return NULL; } class = g_type_class_ref(itype); if (!class) { PyErr_SetString(PyExc_RuntimeError, "could not get a reference to type class"); return NULL; } specs = g_object_class_list_properties(class, &nprops); list = PyTuple_New(nprops); if (list == NULL) { g_free(specs); g_type_class_unref(class); return NULL; } for (i = 0; i < nprops; i++) { PyTuple_SetItem(list, i, pyg_param_spec_new(specs[i])); } g_free(specs); g_type_class_unref(class); return list; } static PyObject * pyg_object_new (PyGObject *self, PyObject *args, PyObject *kwargs) { PyObject *pytype; GType type; GObject *obj = NULL; GObjectClass *class; PyObject *value; PyObject *key; int pos=0, num_params=0, i; GParameter *params; if (!PyArg_ParseTuple (args, "O:gobject.new", &pytype)) { return NULL; } if ((type = pyg_type_from_object (pytype)) == 0) return NULL; if ((class = g_type_class_ref (type)) == NULL) { PyErr_SetString(PyExc_TypeError, "could not get a reference to type class"); return NULL; } params = g_new0(GParameter, PyDict_Size(kwargs)); while (kwargs && PyDict_Next (kwargs, &pos, &key, &value)) { GParamSpec *pspec; gchar *key_str = g_strdup(PyString_AsString (key)); pspec = g_object_class_find_property (class, key_str); if (!pspec) { gchar buf[512]; g_snprintf(buf, sizeof(buf), "gobject `%s' doesn't support property `%s'", g_type_name(type), key_str); PyErr_SetString(PyExc_TypeError, buf); goto cleanup; } g_value_init(¶ms[num_params].value, G_PARAM_SPEC_VALUE_TYPE(pspec)); if (pyg_value_from_pyobject(¶ms[num_params].value, value)) { gchar buf[512]; g_snprintf(buf, sizeof(buf), "could not convert value for property `%s'", key_str); PyErr_SetString(PyExc_TypeError, buf); goto cleanup; } params[num_params].name = key_str; num_params++; } obj = g_object_newv(type, num_params, params); if (!obj) PyErr_SetString (PyExc_RuntimeError, "could not create object"); cleanup: for (i = 0; i < num_params; i++) { g_free((gchar *) params[i].name); g_value_unset(¶ms[i].value); } g_free(params); g_type_class_unref(class); if (obj) return pygobject_new ((GObject *)obj); return NULL; } static PyMethodDef pygobject_functions[] = { { "type_name", pyg_type_name, METH_VARARGS }, { "type_from_name", pyg_type_from_name, METH_VARARGS }, { "type_parent", pyg_type_parent, METH_VARARGS }, { "type_is_a", pyg_type_is_a, METH_VARARGS }, { "type_children", pyg_type_children, METH_VARARGS }, { "type_interfaces", pyg_type_interfaces, METH_VARARGS }, { "type_register", pyg_type_register, METH_VARARGS }, { "signal_new", pyg_signal_new, METH_VARARGS }, { "signal_list_names", pyg_signal_list_names, METH_VARARGS }, { "list_properties", pyg_object_class_list_properties, METH_VARARGS }, { "new", (PyCFunction)pyg_object_new, METH_VARARGS|METH_KEYWORDS }, { NULL, NULL, 0 } }; /* ----------------- Constant extraction ------------------------ */ static char * pyg_constant_strip_prefix(gchar *name, const gchar *strip_prefix) { gint prefix_len; guint j; prefix_len = strlen(strip_prefix); /* strip off prefix from value name, while keeping it a valid * identifier */ for (j = prefix_len; j >= 0; j--) { if (g_ascii_isalpha(name[j]) || name[j] == '_') { return &name[j]; } } return name; } static void pyg_enum_add_constants(PyObject *module, GType enum_type, const gchar *strip_prefix) { GEnumClass *eclass; guint i; /* a more useful warning */ if (!G_TYPE_IS_ENUM(enum_type)) { g_warning("`%s' is not an enum type", g_type_name(enum_type)); return; } g_return_if_fail (strip_prefix != NULL); eclass = G_ENUM_CLASS(g_type_class_ref(enum_type)); for (i = 0; i < eclass->n_values; i++) { gchar *name = eclass->values[i].value_name; gint value = eclass->values[i].value; PyModule_AddIntConstant(module, pyg_constant_strip_prefix(name, strip_prefix), (long) value); } g_type_class_unref(eclass); } static void pyg_flags_add_constants(PyObject *module, GType flags_type, const gchar *strip_prefix) { GFlagsClass *fclass; guint i; /* a more useful warning */ if (!G_TYPE_IS_FLAGS(flags_type)) { g_warning("`%s' is not an flags type", g_type_name(flags_type)); return; } g_return_if_fail (strip_prefix != NULL); fclass = G_FLAGS_CLASS(g_type_class_ref(flags_type)); for (i = 0; i < fclass->n_values; i++) { gchar *name = fclass->values[i].value_name; guint value = fclass->values[i].value; PyModule_AddIntConstant(module, pyg_constant_strip_prefix(name, strip_prefix), (long) value); } g_type_class_unref(fclass); } static gboolean pyg_error_check(GError **error) { g_return_val_if_fail(error != NULL, FALSE); if (*error != NULL) { PyObject *exc_instance; PyObject *d; exc_instance = PyObject_CallFunction(gerror_exc, "z", (*error)->message); PyObject_SetAttrString(exc_instance, "domain", d=PyString_FromString(g_quark_to_string((*error)->domain))); Py_DECREF(d); PyObject_SetAttrString(exc_instance, "code", d=PyInt_FromLong((*error)->code)); Py_DECREF(d); if ((*error)->message) { PyObject_SetAttrString(exc_instance, "message", d=PyString_FromString((*error)->message)); Py_DECREF(d); } else { PyObject_SetAttrString(exc_instance, "message", Py_None); } PyErr_SetObject(gerror_exc, exc_instance); Py_DECREF(exc_instance); g_clear_error(error); return TRUE; } return FALSE; } /* ----------------- gobject module initialisation -------------- */ struct _PyGObject_Functions pygobject_api_functions = { pygobject_register_class, pygobject_register_wrapper, pygobject_lookup_class, pygobject_new, pyg_closure_new, pyg_destroy_notify, pyg_type_from_object, pyg_type_wrapper_new, pyg_enum_get_value, pyg_flags_get_value, pyg_register_boxed_custom, pyg_value_from_pyobject, pyg_value_as_pyobject, pyg_register_interface, &PyGBoxed_Type, pyg_register_boxed, pyg_boxed_new, &PyGPointer_Type, pyg_register_pointer, pyg_pointer_new, pyg_enum_add_constants, pyg_flags_add_constants, pyg_constant_strip_prefix, pyg_error_check, pyg_set_thread_block_funcs, (PyGThreadBlockFunc)0, /* block_threads */ (PyGThreadBlockFunc)0, /* unblock_threads */ }; DL_EXPORT(void) initgobject(void) { PyObject *m, *d, *o, *tuple; PyGTypeWrapper_Type.ob_type = &PyType_Type; PyGParamSpec_Type.ob_type = &PyType_Type; m = Py_InitModule("gobject", pygobject_functions); d = PyModule_GetDict(m); #ifdef ENABLE_PYGTK_THREADING if (!g_threads_got_initialized) g_thread_init(NULL); #endif g_type_init(); PY_TYPE_OBJECT = g_boxed_type_register_static("PyObject", pyobject_copy, pyobject_free); gerror_exc = PyErr_NewException("gobject.GError", PyExc_RuntimeError,NULL); PyDict_SetItemString(d, "GError", gerror_exc); pygobject_register_class(d, "GObject", G_TYPE_OBJECT, &PyGObject_Type, NULL); PyDict_SetItemString(PyGObject_Type.tp_dict, "__gdoc__", pyg_object_descr_doc_get()); PyGInterface_Type.ob_type = &PyType_Type; if (PyType_Ready(&PyGInterface_Type)) return; PyDict_SetItemString(d, "GInterface", (PyObject *)&PyGInterface_Type); PyDict_SetItemString(PyGInterface_Type.tp_dict, "__gtype__", o=pyg_type_wrapper_new(G_TYPE_INTERFACE)); Py_DECREF(o); PyDict_SetItemString(PyGInterface_Type.tp_dict, "__doc__", pyg_object_descr_doc_get()); PyDict_SetItemString(PyGInterface_Type.tp_dict, "__gdoc__", pyg_object_descr_doc_get()); PyGBoxed_Type.ob_type = &PyType_Type; if (PyType_Ready(&PyGBoxed_Type)) return; PyDict_SetItemString(d, "GBoxed", (PyObject *)&PyGBoxed_Type); PyDict_SetItemString(PyGBoxed_Type.tp_dict, "__gtype__", o=pyg_type_wrapper_new(G_TYPE_BOXED)); Py_DECREF(o); PyGPointer_Type.ob_type = &PyType_Type; if (PyType_Ready(&PyGPointer_Type)) return; PyDict_SetItemString(d, "GPointer", (PyObject *)&PyGPointer_Type); PyDict_SetItemString(PyGPointer_Type.tp_dict, "__gtype__", o=pyg_type_wrapper_new(G_TYPE_POINTER)); Py_DECREF(o); tuple = Py_BuildValue ("(iii)", glib_major_version, glib_minor_version, glib_micro_version); PyDict_SetItemString(d, "glib_version", tuple); Py_DECREF(tuple); /* for addon libraries ... */ PyDict_SetItemString(d, "_PyGObject_API", o=PyCObject_FromVoidPtr(&pygobject_api_functions,NULL)); Py_DECREF(o); /* some constants */ PyModule_AddIntConstant(m, "SIGNAL_RUN_FIRST", G_SIGNAL_RUN_FIRST); PyModule_AddIntConstant(m, "SIGNAL_RUN_LAST", G_SIGNAL_RUN_LAST); PyModule_AddIntConstant(m, "SIGNAL_RUN_CLEANUP", G_SIGNAL_RUN_CLEANUP); PyModule_AddIntConstant(m, "SIGNAL_NO_RECURSE", G_SIGNAL_NO_RECURSE); PyModule_AddIntConstant(m, "SIGNAL_DETAILED", G_SIGNAL_DETAILED); PyModule_AddIntConstant(m, "SIGNAL_ACTION", G_SIGNAL_ACTION); PyModule_AddIntConstant(m, "SIGNAL_NO_HOOKS", G_SIGNAL_NO_HOOKS); PyModule_AddIntConstant(m, "PARAM_READABLE", G_PARAM_READABLE); PyModule_AddIntConstant(m, "PARAM_WRITABLE", G_PARAM_WRITABLE); PyModule_AddIntConstant(m, "PARAM_CONSTRUCT", G_PARAM_CONSTRUCT); PyModule_AddIntConstant(m, "PARAM_CONSTRUCT_ONLY", G_PARAM_CONSTRUCT_ONLY); PyModule_AddIntConstant(m, "PARAM_LAX_VALIDATION", G_PARAM_LAX_VALIDATION); PyModule_AddIntConstant(m, "PARAM_READWRITE", G_PARAM_READWRITE); PyModule_AddObject(m, "TYPE_INVALID", pyg_type_wrapper_new(G_TYPE_INVALID)); PyModule_AddObject(m, "TYPE_NONE", pyg_type_wrapper_new(G_TYPE_NONE)); PyModule_AddObject(m, "TYPE_INTERFACE", pyg_type_wrapper_new(G_TYPE_INTERFACE)); PyModule_AddObject(m, "TYPE_CHAR", pyg_type_wrapper_new(G_TYPE_CHAR)); PyModule_AddObject(m, "TYPE_UCHAR", pyg_type_wrapper_new(G_TYPE_UCHAR)); PyModule_AddObject(m, "TYPE_BOOLEAN", pyg_type_wrapper_new(G_TYPE_BOOLEAN)); PyModule_AddObject(m, "TYPE_INT", pyg_type_wrapper_new(G_TYPE_INT)); PyModule_AddObject(m, "TYPE_UINT", pyg_type_wrapper_new(G_TYPE_UINT)); PyModule_AddObject(m, "TYPE_LONG", pyg_type_wrapper_new(G_TYPE_LONG)); PyModule_AddObject(m, "TYPE_ULONG", pyg_type_wrapper_new(G_TYPE_ULONG)); PyModule_AddObject(m, "TYPE_INT64", pyg_type_wrapper_new(G_TYPE_INT64)); PyModule_AddObject(m, "TYPE_UINT64", pyg_type_wrapper_new(G_TYPE_UINT64)); PyModule_AddObject(m, "TYPE_ENUM", pyg_type_wrapper_new(G_TYPE_ENUM)); PyModule_AddObject(m, "TYPE_FLAGS", pyg_type_wrapper_new(G_TYPE_FLAGS)); PyModule_AddObject(m, "TYPE_FLOAT", pyg_type_wrapper_new(G_TYPE_FLOAT)); PyModule_AddObject(m, "TYPE_DOUBLE", pyg_type_wrapper_new(G_TYPE_DOUBLE)); PyModule_AddObject(m, "TYPE_STRING", pyg_type_wrapper_new(G_TYPE_STRING)); PyModule_AddObject(m, "TYPE_POINTER", pyg_type_wrapper_new(G_TYPE_POINTER)); PyModule_AddObject(m, "TYPE_BOXED", pyg_type_wrapper_new(G_TYPE_BOXED)); PyModule_AddObject(m, "TYPE_PARAM", pyg_type_wrapper_new(G_TYPE_PARAM)); PyModule_AddObject(m, "TYPE_OBJECT", pyg_type_wrapper_new(G_TYPE_OBJECT)); PyModule_AddObject(m, "TYPE_PYOBJECT", pyg_type_wrapper_new(PY_TYPE_OBJECT)); if (PyErr_Occurred()) { PyErr_Print(); Py_FatalError("can't initialise module gobject"); } }