f243b12012-03-27Marcus Comstedt /* -*- c -*- || This file is part of Pike. For copyright information see COPYRIGHT. || Pike is distributed under GPL, LGPL and MPL. See the file COPYING || for more information. */ #include "global.h" #include "interpret.h" #include "module_support.h" #include "builtin_functions.h"
b71b022012-03-31Marcus Comstedt #include "bignum.h"
e9cd7d2012-03-31Marcus Comstedt #include "operators.h"
a0383e2012-10-07Marcus Comstedt #include "mapping.h"
cf94ff2012-10-22Marcus Comstedt #include "threads.h"
f243b12012-03-27Marcus Comstedt #include "gimod_config.h" DECLARATIONS #ifdef HAVE_GI #include <girepository.h>
a149202012-04-01Marcus Comstedt static GQuark object_quark;
a0383e2012-10-07Marcus Comstedt static struct mapping *magic_mapping = NULL;
a149202012-04-01Marcus Comstedt 
f243b12012-03-27Marcus Comstedt /*! @module GI */ static void throw_gerror(GError *error) { Pike_error("%s\n", error->message); }
b5f0022012-03-30Marcus Comstedt static void free_glist_full_free(void *p) { g_list_free_full(p, free); }
29e7552018-11-04Marcus Comstedt struct GI_GBoxed_struct;
f243b12012-03-27Marcus Comstedt static void push_gi_info(GIBaseInfo *info);
a0383e2012-10-07Marcus Comstedt static GObject *make_gobject_from_props(struct object *info, struct mapping *props);
29e7552018-11-04Marcus Comstedt static void make_gboxed(struct GI_GBoxed_struct *this, struct object *info, gboolean allocate);
af08e02012-10-14Marcus Comstedt static void push_gvalue(const GValue *v); static void set_gvalue_from_svalue(GValue *v, const struct svalue *s); struct signal_data { struct svalue cb; struct svalue extra_args; }; static void free_signal_data(struct signal_data *s, GClosure *gcl) { free_svalue(&s->cb); free_svalue(&s->extra_args); g_free(s); } static void marshaller(GClosure *closure, GValue *return_value, guint n_params, const GValue *param_values, gpointer invocation_hint, gpointer marshal_data) { typedef void (*marshal_func)(gpointer data1, gpointer data2, guint n_params, const GValue *param_values, GValue *return_value); marshal_func callback; GCClosure *cc=(GCClosure *)closure; gpointer data1, data2; if (G_CCLOSURE_SWAP_DATA(closure)) { data1=closure->data; data2=g_value_peek_pointer(param_values+0); } else { data1=g_value_peek_pointer(param_values+0); data2=closure->data; } callback=(marshal_func)(marshal_data? marshal_data : cc->callback); callback(data1, data2, n_params-1, param_values+1, return_value); } struct signal_wrapper_context { struct signal_data *d; guint n_params; const GValue *param_values; GValue *return_value; }; static void invoke_signal_func(void *arg) { struct signal_wrapper_context *ctx = (struct signal_wrapper_context *)arg; struct signal_data *d = ctx->d; guint n_params = ctx->n_params; const GValue *param_values = ctx->param_values; GValue *return_value = ctx->return_value; JMP_BUF recovery; unsigned int i; INT32 args = n_params; struct svalue *osp = Pike_sp; if (SETJMP(recovery)) { pop_n_elems(Pike_sp-osp); UNSETJMP(recovery); call_handle_error(); if (return_value && G_VALUE_TYPE(return_value) != 0) g_value_unset(return_value); return; } for (i=0; i<n_params; i++) { push_gvalue(&(param_values[i])); } if (TYPEOF(d->extra_args) == PIKE_T_ARRAY) { struct array *a = d->extra_args.u.array; INT32 asize = a->size; check_stack(asize); assign_svalues_no_free(Pike_sp, ITEM(a), asize, a->type_field); Pike_sp += asize; args += asize; } apply_svalue(&d->cb, args); if (return_value && G_VALUE_TYPE(return_value) != 0 ) set_gvalue_from_svalue(return_value, &Pike_sp[-1]); pop_stack(); UNSETJMP(recovery); } static void signal_func_wrapper(struct signal_data *d, gpointer go, guint n_params, const GValue *param_values, GValue *return_value) { struct signal_wrapper_context ctx = { d, n_params, param_values, return_value }; call_with_interpreter(invoke_signal_func, &ctx); }
f243b12012-03-27Marcus Comstedt 
e9cd7d2012-03-31Marcus Comstedt /*! @class GObject
f243b12012-03-27Marcus Comstedt  */
e9cd7d2012-03-31Marcus Comstedt PIKECLASS GObject { CVAR GObject *obj; INIT { THIS->obj = NULL; } EXIT { if (THIS->obj != NULL) {
a149202012-04-01Marcus Comstedt  g_object_set_qdata(THIS->obj, object_quark, NULL);
e9cd7d2012-03-31Marcus Comstedt  g_object_unref(THIS->obj); THIS->obj = NULL; } }
a0383e2012-10-07Marcus Comstedt  #ifndef tObjImpl_OBJECTINFO /* Break circular class dependency... */ #define tObjImpl_OBJECTINFO tObj #endif /*! @decl void create(ObjectInfo info, mapping(string:mixed)|void props) */ PIKEFUN void create(ObjectInfo info, mapping(string:mixed)|void props) { if (THIS->obj != NULL) Pike_error("GObject.create called twice!\n"); if (props != magic_mapping) { THIS->obj = make_gobject_from_props(info, props); g_object_set_qdata(THIS->obj, object_quark, Pike_fp->current_object); } }
af08e02012-10-14Marcus Comstedt  /*! @decl int connect(string signal_spec, function callback, mixed ... extra_args) */ PIKEFUN int connect(string signal_spec, function callback, mixed ... extra_args) { struct signal_data *b; GClosure *gc; guint sigid; GQuark detail = 0; gulong id; if (signal_spec->size_shift || !g_signal_parse_name((const gchar *)STR0(signal_spec), G_OBJECT_TYPE(THIS->obj), &sigid, &detail, TRUE)) { Pike_error("Signal \"%S\" is not defined in the '%s' class ancestry.\n", signal_spec, g_type_name(G_TYPE_FROM_INSTANCE(THIS->obj))); } b=(struct signal_data *)g_malloc0(sizeof(struct signal_data)); if (b==NULL) SIMPLE_OUT_OF_MEMORY_ERROR("connect",sizeof(struct signal_data)); assign_svalue_no_free(&b->cb, callback); if (extra_args) { f_aggregate(args-2); assign_svalue_no_free(&b->extra_args, Pike_sp-1); pop_stack(); args = 2; } else { SET_SVAL(b->extra_args, PIKE_T_INT, NUMBER_NUMBER, integer, 0); } gc=g_cclosure_new_swap(G_CALLBACK(signal_func_wrapper), b, (GClosureNotify)free_signal_data); g_closure_set_marshal(gc, marshaller); id = g_signal_connect_closure_by_id(G_OBJECT(THIS->obj), sigid, detail, gc, FALSE); RETURN id; } /*! @decl int connect_after(string signal_spec, function callback, mixed ... extra_args) */ PIKEFUN int connect_after(string signal_spec, function callback, mixed ... extra_args) { struct signal_data *b; GClosure *gc; guint sigid; GQuark detail = 0; gulong id; if (signal_spec->size_shift || !g_signal_parse_name((const gchar *)STR0(signal_spec), G_OBJECT_TYPE(THIS->obj), &sigid, &detail, TRUE)) { Pike_error("Signal \"%S\" is not defined in the '%s' class ancestry.\n", signal_spec, g_type_name(G_TYPE_FROM_INSTANCE(THIS->obj))); } b=(struct signal_data *)g_malloc0(sizeof(struct signal_data)); if (b==NULL) SIMPLE_OUT_OF_MEMORY_ERROR("connect_after",sizeof(struct signal_data)); assign_svalue_no_free(&b->cb, callback); if (extra_args) { f_aggregate(args-2); assign_svalue_no_free(&b->extra_args, Pike_sp-1); pop_stack(); args = 2; } else { SET_SVAL(b->extra_args, PIKE_T_INT, NUMBER_NUMBER, integer, 0); } gc=g_cclosure_new_swap(G_CALLBACK(signal_func_wrapper), b, (GClosureNotify)free_signal_data); g_closure_set_marshal(gc, marshaller); id = g_signal_connect_closure_by_id(G_OBJECT(THIS->obj), sigid, detail, gc, TRUE); RETURN id; }
e9cd7d2012-03-31Marcus Comstedt } /*! @endclass */
f7e06e2012-10-24Marcus Comstedt /*! @class GBoxed */ PIKECLASS GBoxed { CVAR gpointer box;
66255f2012-10-28Marcus Comstedt  CVAR GType type;
79edc92012-10-28Marcus Comstedt  CVAR gsize allocated_size;
f7e06e2012-10-24Marcus Comstedt  INIT { THIS->box = NULL;
66255f2012-10-28Marcus Comstedt  THIS->type = G_TYPE_INVALID;
79edc92012-10-28Marcus Comstedt  THIS->allocated_size = 0;
f7e06e2012-10-24Marcus Comstedt  } EXIT { if (THIS->box != NULL) {
79edc92012-10-28Marcus Comstedt  if (THIS->allocated_size) g_slice_free1(THIS->allocated_size, THIS->box);
f7e06e2012-10-24Marcus Comstedt  THIS->box = NULL; } }
79edc92012-10-28Marcus Comstedt  #ifndef tObjImpl_STRUCTINFO /* Break circular class dependency... */ #define tObjImpl_STRUCTINFO tObj #endif /*! @decl void create(StructInfo info, mapping(string:mixed)|void props) */ PIKEFUN void create(StructInfo info, mapping(string:mixed)|void props) { if (THIS->box != NULL) Pike_error("GBoxed.create called twice!\n"); make_gboxed(THIS, info, props != magic_mapping); if (THIS->box != NULL && props != NULL && m_sizeof(props) > 0) { INT32 e; struct keypair *k; NEW_MAPPING_LOOP(props->data) object_set_index(Pike_fp->current_object, 0, &k->ind, &k->val); } }
f7e06e2012-10-24Marcus Comstedt } /*! @endclass */
13f1b52012-10-06Marcus Comstedt static void push_wrapper_name_from_info(GIBaseInfo *info) { push_constant_text("GI.repository."); push_text(g_base_info_get_namespace(info)); push_constant_text("."); push_text(g_base_info_get_name(info)); f_add(4); }
19e0212012-10-22Marcus Comstedt static void push_wrapped_gobject(gpointer gobj, GIBaseInfo *info) { if (!gobj) { push_int(0); } else { struct object *obj = g_object_get_qdata(gobj, object_quark); if (obj == NULL) { GType rttype = G_OBJECT_TYPE((GObject *)gobj); GIBaseInfo *rtinfo = g_irepository_find_by_gtype (NULL, rttype); if (rtinfo != NULL) { push_wrapper_name_from_info(rtinfo); g_base_info_unref(rtinfo); } else if (info != NULL) push_wrapper_name_from_info(info); else Pike_error("Received an object of an unregistered type!\n"); APPLY_MASTER ("resolv", 1); if (TYPEOF(Pike_sp[-1]) != T_OBJECT) Pike_error("Failed to resolve GI object class.\n"); ref_push_mapping(magic_mapping); apply(Pike_sp[-2].u.object, "Instance", 1); stack_pop_keep_top(); if (TYPEOF(Pike_sp[-1]) != T_OBJECT) Pike_error("Failed to instantiate GI object class.\n"); {
29e7552018-11-04Marcus Comstedt  struct GI_GObject_struct *that = (struct GI_GObject_struct *)get_storage ((obj = Pike_sp[-1].u.object), GI_GObject_program);
19e0212012-10-22Marcus Comstedt  if (that == NULL) Pike_error("No storage for GObject!\n"); if (that->obj != NULL) Pike_error("GObject already initialized!\n"); g_object_ref ((that->obj = gobj)); g_object_set_qdata(that->obj, object_quark, obj); } } else ref_push_object(obj); } }
f7e06e2012-10-24Marcus Comstedt static void push_wrapped_boxed(gpointer gbox, GIBaseInfo *info, GType rttype) { if (!gbox) { push_int(0); } else {
66255f2012-10-28Marcus Comstedt  if (info != NULL) { push_wrapper_name_from_info(info); } else { GIBaseInfo *rtinfo = g_irepository_find_by_gtype (NULL, rttype); if (rtinfo != NULL) {
f7e06e2012-10-24Marcus Comstedt  push_wrapper_name_from_info(rtinfo); g_base_info_unref(rtinfo);
66255f2012-10-28Marcus Comstedt  } else Pike_error("Received a box of an unregistered type!\n");
f7e06e2012-10-24Marcus Comstedt  } APPLY_MASTER ("resolv", 1); if (TYPEOF(Pike_sp[-1]) != T_OBJECT) Pike_error("Failed to resolve GI box class.\n");
79edc92012-10-28Marcus Comstedt  ref_push_mapping(magic_mapping); apply(Pike_sp[-2].u.object, "Instance", 1);
f7e06e2012-10-24Marcus Comstedt  if (TYPEOF(Pike_sp[-1]) != T_OBJECT) Pike_error("Failed to instantiate GI box class.\n"); {
29e7552018-11-04Marcus Comstedt  struct GI_GBoxed_struct *that = (struct GI_GBoxed_struct *)get_storage (Pike_sp[-1].u.object, GI_GBoxed_program);
f7e06e2012-10-24Marcus Comstedt  if (that == NULL) Pike_error("No storage for GBoxed!\n"); if (that->box != NULL) Pike_error("GBoxed already initialized!\n"); that->box = gbox; } } }
e9cd7d2012-03-31Marcus Comstedt static void push_gi_argument_interface(GIArgument *arg, GIBaseInfo *info) { switch(g_base_info_get_type(info)) {
d82ed82012-04-01Marcus Comstedt  case GI_INFO_TYPE_ENUM: case GI_INFO_TYPE_FLAGS: push_int(arg->v_long); break;
e9cd7d2012-03-31Marcus Comstedt  case GI_INFO_TYPE_OBJECT:
19e0212012-10-22Marcus Comstedt  push_wrapped_gobject(arg->v_pointer, info);
e9cd7d2012-03-31Marcus Comstedt  break;
66255f2012-10-28Marcus Comstedt  case GI_INFO_TYPE_STRUCT: push_wrapped_boxed(arg->v_pointer, info, G_TYPE_NONE); break;
e9cd7d2012-03-31Marcus Comstedt  default: Pike_error("Don't know how to push a base %d\n", g_base_info_get_type(info)); } }
b71b022012-03-31Marcus Comstedt static void push_gi_argument(GIArgument *arg, GITypeInfo *info) { switch (g_type_info_get_tag(info)) { case GI_TYPE_TAG_VOID: push_int(0); break; case GI_TYPE_TAG_BOOLEAN: push_int(arg->v_boolean); break; case GI_TYPE_TAG_INT8: push_int(arg->v_int8); break; case GI_TYPE_TAG_UINT8: push_int(arg->v_uint8); break; case GI_TYPE_TAG_INT16: push_int(arg->v_int16); break; case GI_TYPE_TAG_UINT16: push_int(arg->v_uint16); break; case GI_TYPE_TAG_INT32: push_int(arg->v_int32); break; case GI_TYPE_TAG_UINT32: push_int64(arg->v_uint32); break; case GI_TYPE_TAG_INT64: push_int64(arg->v_int64); break; case GI_TYPE_TAG_UINT64: /* FIXME... */ push_int64(arg->v_uint64); break;
91d3832012-10-28Marcus Comstedt  case GI_TYPE_TAG_FLOAT: push_float(arg->v_float); break; case GI_TYPE_TAG_DOUBLE: push_float(arg->v_double); break;
b71b022012-03-31Marcus Comstedt  case GI_TYPE_TAG_UTF8: push_text(arg->v_pointer); f_utf8_to_string(1); break;
aa75a62012-10-24Marcus Comstedt  case GI_TYPE_TAG_FILENAME: push_text(arg->v_pointer); break;
e9cd7d2012-03-31Marcus Comstedt  case GI_TYPE_TAG_INTERFACE: { ONERROR onerror; GIBaseInfo *info2; info2 = g_type_info_get_interface(info); SET_ONERROR(onerror, g_base_info_unref, info2); push_gi_argument_interface(arg, info2); UNSET_ONERROR(onerror); g_base_info_unref(info2); } break;
3918352012-10-07Marcus Comstedt  case GI_TYPE_TAG_GLIST: case GI_TYPE_TAG_GSLIST: { INT32 count = 0; GSList *list = arg->v_pointer; while(list != NULL) { GIArgument item; GITypeInfo *item_info = g_type_info_get_param_type(info, 0); item.v_pointer = list->data; push_gi_argument(&item, item_info); count++; list = g_slist_next (list); } f_aggregate(count); } break;
b71b022012-03-31Marcus Comstedt  default: Pike_error("Don't know how to push a %d\n", g_type_info_get_tag(info)); } }
0625c92012-04-01Marcus Comstedt static void get_gi_argument_interface(struct svalue *s, GIArgument *arg, GIBaseInfo *info) { switch(g_base_info_get_type(info)) {
a7a3432012-04-01Marcus Comstedt  case GI_INFO_TYPE_ENUM: case GI_INFO_TYPE_FLAGS: if (TYPEOF(*s) != PIKE_T_INT) Pike_error("int expected\n"); arg->v_long = s->u.integer; break;
0625c92012-04-01Marcus Comstedt  case GI_INFO_TYPE_OBJECT: if (UNSAFE_IS_ZERO(s)) { arg->v_pointer = NULL; break; } if (TYPEOF(*s) != T_OBJECT) Pike_error("object expected\n"); else {
29e7552018-11-04Marcus Comstedt  struct GI_GObject_struct *that = (struct GI_GObject_struct *)get_storage (s->u.object, GI_GObject_program);
0625c92012-04-01Marcus Comstedt  if (that == NULL) Pike_error("argument is not a GObject\n"); if (that->obj == NULL || !g_type_is_a(G_OBJECT_TYPE(that->obj), g_registered_type_info_get_g_type(info))) Pike_error("Object is not a %s\n", g_base_info_get_name(info)); arg->v_pointer = that->obj; } break;
66255f2012-10-28Marcus Comstedt  case GI_INFO_TYPE_STRUCT: if (UNSAFE_IS_ZERO(s)) { arg->v_pointer = NULL; break; } if (TYPEOF(*s) != T_OBJECT) Pike_error("object expected\n"); else {
29e7552018-11-04Marcus Comstedt  struct GI_GBoxed_struct *that = (struct GI_GBoxed_struct *)get_storage (s->u.object, GI_GBoxed_program);
66255f2012-10-28Marcus Comstedt  if (that == NULL) Pike_error("argument is not a GBoxed\n"); if (that->box == NULL || !g_type_is_a(that->type, g_registered_type_info_get_g_type(info))) Pike_error("Object is not a %s\n", g_base_info_get_name(info)); arg->v_pointer = that->box; } break;
0625c92012-04-01Marcus Comstedt  default: Pike_error("Don't know how to get a base %d\n", g_base_info_get_type(info)); } }
2733102012-04-01Marcus Comstedt static void get_gi_argument_type(struct svalue *s, GIArgument *arg, GITypeInfo *ti)
b71b022012-03-31Marcus Comstedt {
2733102012-04-01Marcus Comstedt  switch (g_type_info_get_tag(ti)) {
b71b022012-03-31Marcus Comstedt  case GI_TYPE_TAG_VOID: Pike_error("Too many arguments\n"); case GI_TYPE_TAG_BOOLEAN: arg->v_boolean = (UNSAFE_IS_ZERO(s)? FALSE : TRUE); break;
30433a2012-04-01Marcus Comstedt  case GI_TYPE_TAG_INT8: if (TYPEOF(*s) != PIKE_T_INT) Pike_error("int expected\n"); arg->v_int8 = s->u.integer; break; case GI_TYPE_TAG_UINT8: if (TYPEOF(*s) != PIKE_T_INT) Pike_error("int expected\n"); arg->v_uint8 = s->u.integer; break; case GI_TYPE_TAG_INT16: if (TYPEOF(*s) != PIKE_T_INT) Pike_error("int expected\n"); arg->v_int16 = s->u.integer; break; case GI_TYPE_TAG_UINT16: if (TYPEOF(*s) != PIKE_T_INT) Pike_error("int expected\n"); arg->v_uint16 = s->u.integer; break; case GI_TYPE_TAG_INT32: if (TYPEOF(*s) != PIKE_T_INT) Pike_error("int expected\n"); arg->v_int32 = s->u.integer; break; case GI_TYPE_TAG_UINT32: if (TYPEOF(*s) != PIKE_T_INT) Pike_error("int expected\n"); arg->v_uint32 = s->u.integer; break;
c9e87d2012-04-01Marcus Comstedt  case GI_TYPE_TAG_FLOAT: if (TYPEOF(*s) == PIKE_T_INT) arg->v_float = s->u.integer; else if (TYPEOF(*s) == PIKE_T_FLOAT) arg->v_float = s->u.float_number; else Pike_error("float expected\n"); break; case GI_TYPE_TAG_DOUBLE: if (TYPEOF(*s) == PIKE_T_INT) arg->v_double = s->u.integer; else if (TYPEOF(*s) == PIKE_T_FLOAT) arg->v_double = s->u.float_number; else Pike_error("float expected\n"); break;
b71b022012-03-31Marcus Comstedt  case GI_TYPE_TAG_UTF8: if (TYPEOF(*s) != PIKE_T_STRING) Pike_error("Expected string\n"); ref_push_string(s->u.string); f_string_to_utf8(1); arg->v_pointer = STR0(Pike_sp[-1].u.string); break;
2733102012-04-01Marcus Comstedt 
aa75a62012-10-24Marcus Comstedt  case GI_TYPE_TAG_FILENAME: if (TYPEOF(*s) != PIKE_T_STRING) Pike_error("Expected string\n"); ref_push_string(s->u.string); arg->v_pointer = STR0(Pike_sp[-1].u.string); break;
2733102012-04-01Marcus Comstedt  case GI_TYPE_TAG_ARRAY: if (UNSAFE_IS_ZERO(s)) { arg->v_pointer = NULL; break; }
2254f92012-10-24Marcus Comstedt  if (TYPEOF(*s) != PIKE_T_ARRAY) { if (TYPEOF(*s) == PIKE_T_STRING && !s->u.string->size_shift) { GITypeInfo *itemti = g_type_info_get_param_type(ti, 0); if (g_type_info_get_tag(itemti) == GI_TYPE_TAG_UINT8) { ONERROR onerror; GArray *arr; SET_ONERROR(onerror, g_base_info_unref, itemti); arr = g_array_sized_new(g_type_info_is_zero_terminated(ti), FALSE, sizeof(guint8), s->u.string->len); g_array_insert_vals(arr, 0, STR0(s->u.string), s->u.string->len); UNSET_ONERROR(onerror); g_base_info_unref(itemti); arg->v_pointer = arr->data; break; } else g_base_info_unref(itemti); }
2733102012-04-01Marcus Comstedt  Pike_error("array expected\n");
2254f92012-10-24Marcus Comstedt  } else {
2733102012-04-01Marcus Comstedt  ONERROR onerror; INT32 i; GArray *arr; GITypeInfo *itemti = g_type_info_get_param_type(ti, 0); SET_ONERROR(onerror, g_base_info_unref, itemti); arr = g_array_sized_new(g_type_info_is_zero_terminated(ti), FALSE, sizeof(gpointer) /*FIXME*/, s->u.array->size); for (i=0; i<s->u.array->size; i++) { GIArgument a; get_gi_argument_type(&ITEM(s->u.array)[i], &a, itemti); g_array_insert_val(arr, i, a); } UNSET_ONERROR(onerror); g_base_info_unref(itemti); arg->v_pointer = arr->data; } break;
0625c92012-04-01Marcus Comstedt  case GI_TYPE_TAG_INTERFACE: { ONERROR onerror; GIBaseInfo *info; info = g_type_info_get_interface(ti); SET_ONERROR(onerror, g_base_info_unref, info); get_gi_argument_interface(s, arg, info); UNSET_ONERROR(onerror); g_base_info_unref(info); } break;
b71b022012-03-31Marcus Comstedt  default:
2733102012-04-01Marcus Comstedt  Pike_error("Don't know how to get a %d\n", g_type_info_get_tag(ti));
b71b022012-03-31Marcus Comstedt  } }
2733102012-04-01Marcus Comstedt static void get_gi_argument(struct svalue *s, GIArgument *arg, GIArgInfo *ai) { GITypeInfo ti; g_arg_info_load_type(ai, &ti); get_gi_argument_type(s, arg, &ti); }
66255f2012-10-28Marcus Comstedt static gsize get_interface_size(GIBaseInfo *info) { switch(g_base_info_get_type(info)) { case GI_INFO_TYPE_STRUCT: return g_struct_info_get_size ( (GIStructInfo *) info); default: return 0; } } static gsize get_arg_size(GIArgInfo *ai) { GITypeInfo ti; g_arg_info_load_type(ai, &ti); switch (g_type_info_get_tag(&ti)) { case GI_TYPE_TAG_INTERFACE: { GIBaseInfo *info; gsize ret; info = g_type_info_get_interface(&ti); ret = get_interface_size(info); g_base_info_unref(info); return ret; } break; default: return 0; } }
e9cd7d2012-03-31Marcus Comstedt /*! @class BaseInfo */
f243b12012-03-27Marcus Comstedt PIKECLASS BaseInfo { CVAR GIBaseInfo *info; INIT { THIS->info = NULL; } EXIT { if (THIS->info != NULL) { g_base_info_unref(THIS->info); THIS->info = NULL; } } /*! @decl string get_name() */ PIKEFUN string get_name() { pop_n_elems(args); push_text(g_base_info_get_name(THIS->info)); } /*! @decl string get_namespace() */ PIKEFUN string get_namespace() { pop_n_elems(args); push_text(g_base_info_get_namespace(THIS->info)); } /*! @decl BaseInfo get_container() */ PIKEFUN BaseInfo get_container() { GIBaseInfo *container = g_base_info_get_container(THIS->info); pop_n_elems(args); if (container) push_gi_info(container); else push_int(0); } PIKEFUN string _sprintf (int flag, ...) flags ID_STATIC; { pop_n_elems(args); if (flag != 'O' || THIS->info == NULL) push_int(0); else { push_constant_text("%O(%s)");
60a2212012-10-28Marcus Comstedt  ref_push_program(Pike_fp->current_program);
f243b12012-03-27Marcus Comstedt  push_text(g_base_info_get_name(THIS->info)); f_sprintf(3); } } } /*! @class FunctionInfo */ PIKECLASS FunctionInfo { INHERIT BaseInfo;
b71b022012-03-31Marcus Comstedt  /*! @decl mixed invoke(mixed ... args) */ PIKEFUN mixed invoke(mixed ... a) { ONERROR onerror; gboolean ok; GError *error = NULL; GIArgument retval; GITypeInfo *ti; struct svalue *mark = Pike_sp-args;
66255f2012-10-28Marcus Comstedt  int i = 0, arg_num, num_in_args = 0, num_out_args = 0, out_arg_0_num; gint num_args = g_callable_info_get_n_args(THIS->info);
19a8b62012-03-31Marcus Comstedt  GIFunctionInfoFlags flags = g_function_info_get_flags (THIS->info);
66255f2012-10-28Marcus Comstedt  GIArgument *in_args = (num_args || (flags & GI_FUNCTION_IS_METHOD)? xalloc((2 * num_args + 1) * sizeof(GIArgument)) : NULL); GIArgument out_arg_0, *out_args = (num_args? in_args+num_args+1 : NULL);
b71b022012-03-31Marcus Comstedt  SET_ONERROR(onerror, free, in_args);
19a8b62012-03-31Marcus Comstedt  if (flags & GI_FUNCTION_IS_METHOD) { if (args < 1 || TYPEOF(*mark) != T_OBJECT) Pike_error("Missing object for method call\n"); else {
743e092012-10-28Marcus Comstedt  GIBaseInfo *cont = g_base_info_get_container(THIS->info); if (g_base_info_get_type(cont) == GI_INFO_TYPE_OBJECT || g_base_info_get_type(cont) == GI_INFO_TYPE_INTERFACE) {
29e7552018-11-04Marcus Comstedt  struct GI_GObject_struct *that = (struct GI_GObject_struct *)get_storage (mark->u.object, GI_GObject_program);
743e092012-10-28Marcus Comstedt  if (that == NULL) Pike_error("Instance argument is not a GObject\n"); if (that->obj == NULL || !g_type_is_a(G_OBJECT_TYPE(that->obj), g_registered_type_info_get_g_type(cont))) Pike_error("Object is not a %s\n", g_base_info_get_name(cont)); in_args[0].v_pointer = that->obj; } else {
29e7552018-11-04Marcus Comstedt  struct GI_GBoxed_struct *that = (struct GI_GBoxed_struct *)get_storage (mark->u.object, GI_GBoxed_program);
743e092012-10-28Marcus Comstedt  if (that == NULL) Pike_error("Instance argument is not a GBoxed\n"); if (that->box == NULL || !g_type_is_a(that->type, g_registered_type_info_get_g_type(cont))) Pike_error("Boxed is not a %s\n", g_base_info_get_name(cont)); in_args[0].v_pointer = that->box; }
19a8b62012-03-31Marcus Comstedt  i++;
66255f2012-10-28Marcus Comstedt  num_in_args++;
19a8b62012-03-31Marcus Comstedt  } }
66255f2012-10-28Marcus Comstedt  for (arg_num=0; arg_num<num_args; arg_num++) {
b71b022012-03-31Marcus Comstedt  ONERROR onerror2; GIArgInfo *ai;
19a8b62012-03-31Marcus Comstedt  ai = g_callable_info_get_arg(THIS->info, arg_num);
b71b022012-03-31Marcus Comstedt  if (!ai) Pike_error("Too many arguments to function %s\n", g_base_info_get_name(THIS->info)); SET_ONERROR(onerror2, g_base_info_unref, ai);
66255f2012-10-28Marcus Comstedt  if (num_out_args == 0) out_arg_0_num = arg_num; if (g_arg_info_get_direction(ai) == GI_DIRECTION_OUT) { gsize size = get_arg_size(ai); out_args[num_out_args].v_pointer = NULL; if (size > 0) out_args[num_out_args].v_pointer = g_slice_alloc0(size);
d00c622012-04-01Marcus Comstedt  num_out_args++;
66255f2012-10-28Marcus Comstedt  } else if (i<args) { get_gi_argument(mark+i, &in_args[num_in_args++], ai); if(g_arg_info_get_direction(ai) == GI_DIRECTION_INOUT) { out_args[num_out_args] = in_args[num_in_args-1]; in_args[num_in_args-1].v_pointer = &out_args[num_out_args]; num_out_args++; } i++;
d00c622012-04-01Marcus Comstedt  }
b71b022012-03-31Marcus Comstedt  UNSET_ONERROR(onerror2); g_base_info_unref(ai); }
66255f2012-10-28Marcus Comstedt  if (i<args) Pike_error("Too many arguments to function %s\n", g_base_info_get_name(THIS->info)); ok = g_function_info_invoke(THIS->info, in_args, num_in_args,
d00c622012-04-01Marcus Comstedt  out_args, num_out_args, &retval, &error);
66255f2012-10-28Marcus Comstedt  if (num_out_args > 0) out_arg_0 = out_args[0];
b71b022012-03-31Marcus Comstedt  UNSET_ONERROR(onerror); free(in_args); if(error) throw_gerror(error); if(!ok) Pike_error("Function not invoked\n"); pop_n_elems(Pike_sp - mark); ti = g_callable_info_get_return_type(THIS->info); SET_ONERROR(onerror, g_base_info_unref, ti);
66255f2012-10-28Marcus Comstedt  if(num_out_args > 0 && g_type_info_get_tag(ti) == GI_TYPE_TAG_VOID) { GIArgInfo *ai; GITypeInfo ati; UNSET_ONERROR(onerror); g_base_info_unref(ti); ai = g_callable_info_get_arg(THIS->info, out_arg_0_num); SET_ONERROR(onerror, g_base_info_unref, ai); g_arg_info_load_type(ai, &ati); push_gi_argument(&out_arg_0, &ati); UNSET_ONERROR(onerror); g_base_info_unref(ai); } else { push_gi_argument(&retval, ti); UNSET_ONERROR(onerror); g_base_info_unref(ti); }
b71b022012-03-31Marcus Comstedt  }
f243b12012-03-27Marcus Comstedt } /*! @class CallbackInfo */ PIKECLASS CallbackInfo { INHERIT BaseInfo; }
4ae4b02012-10-28Marcus Comstedt /*! @class FieldInfo */ PIKECLASS FieldInfo { INHERIT BaseInfo;
2dfe042012-10-28Marcus Comstedt  /*! @decl mixed get_field(GBoxed box)
4ae4b02012-10-28Marcus Comstedt  */
2dfe042012-10-28Marcus Comstedt  PIKEFUN mixed get_field(GBoxed box)
4ae4b02012-10-28Marcus Comstedt  { ONERROR onerror; GIArgument value; GITypeInfo *ti; GIBaseInfo *sinfo = g_base_info_get_container(THIS->info);
29e7552018-11-04Marcus Comstedt  struct GI_GBoxed_struct *that = (struct GI_GBoxed_struct *)get_storage (box, GI_GBoxed_program);
4ae4b02012-10-28Marcus Comstedt  if (that == NULL) Pike_error("argument is not a GBoxed\n"); if (that->box == NULL || !g_type_is_a(that->type, g_registered_type_info_get_g_type(sinfo))) Pike_error("Boxed is not a %s\n", g_base_info_get_name(sinfo)); ti = g_field_info_get_type((GIFieldInfo *)THIS->info); SET_ONERROR(onerror, g_base_info_unref, ti); if (!g_field_info_get_field((GIFieldInfo *)THIS->info, that->box, &value)) Pike_error("Field can not be read\n"); push_gi_argument(&value, ti); UNSET_ONERROR(onerror); g_base_info_unref(ti); stack_pop_n_elems_keep_top(args); }
29c3392012-10-28Marcus Comstedt  /*! @decl void set_field(GBoxed box, mixed value) */ PIKEFUN void set_field(GBoxed box, mixed value) { ONERROR onerror; GIArgument val; GITypeInfo *ti; GIBaseInfo *sinfo = g_base_info_get_container(THIS->info);
29e7552018-11-04Marcus Comstedt  struct GI_GBoxed_struct *that = (struct GI_GBoxed_struct *)get_storage (box, GI_GBoxed_program);
29c3392012-10-28Marcus Comstedt  if (that == NULL) Pike_error("argument is not a GBoxed\n"); if (that->box == NULL || !g_type_is_a(that->type, g_registered_type_info_get_g_type(sinfo))) Pike_error("Boxed is not a %s\n", g_base_info_get_name(sinfo)); ti = g_field_info_get_type((GIFieldInfo *)THIS->info); SET_ONERROR(onerror, g_base_info_unref, ti); get_gi_argument_type(value, &val, ti); if (!g_field_info_set_field((GIFieldInfo *)THIS->info, that->box, &val)) Pike_error("Field can not be written\n"); UNSET_ONERROR(onerror); g_base_info_unref(ti); stack_pop_n_elems_keep_top(args); }
4ae4b02012-10-28Marcus Comstedt }
f243b12012-03-27Marcus Comstedt /*! @class StructInfo */ PIKECLASS StructInfo { INHERIT BaseInfo;
f7e06e2012-10-24Marcus Comstedt  /*! @decl array(FunctionInfo) get_methods() */ PIKEFUN array(FunctionInfo) get_methods() { ONERROR onerror, onerror2; struct array *arr; gssize i, num; num = g_struct_info_get_n_methods((GIStructInfo *)THIS->info); arr = allocate_array(num); SET_ONERROR(onerror, do_free_array, arr); for(i=0; i<num; i++) { GIBaseInfo *info; info = (GIBaseInfo *)g_struct_info_get_method((GIStructInfo *)THIS->info, i); SET_ONERROR(onerror2, g_base_info_unref, info); push_gi_info(info); UNSET_ONERROR(onerror2); g_base_info_unref(info); array_set_index_no_free(arr, i, Pike_sp-1); pop_stack(); } UNSET_ONERROR(onerror); RETURN arr; }
4ae4b02012-10-28Marcus Comstedt  /*! @decl array(FieldInfo) get_fields() */ PIKEFUN array(FieldInfo) get_fields() { ONERROR onerror, onerror2; struct array *arr; gssize i, num; num = g_struct_info_get_n_fields((GIStructInfo *)THIS->info); arr = allocate_array(num); SET_ONERROR(onerror, do_free_array, arr); for(i=0; i<num; i++) { GIBaseInfo *info; info = (GIBaseInfo *)g_struct_info_get_field((GIStructInfo *)THIS->info, i); SET_ONERROR(onerror2, g_base_info_unref, info); push_gi_info(info); UNSET_ONERROR(onerror2); g_base_info_unref(info); array_set_index_no_free(arr, i, Pike_sp-1); pop_stack(); } UNSET_ONERROR(onerror); RETURN arr; }
f243b12012-03-27Marcus Comstedt }
a187212012-04-01Marcus Comstedt /*! @class ValueInfo */ PIKECLASS ValueInfo { INHERIT BaseInfo; /*! @decl int get_value() */ PIKEFUN int get_value() { RETURN g_value_info_get_value((GIValueInfo *)THIS->info); } }
f243b12012-03-27Marcus Comstedt /*! @class EnumInfo */ PIKECLASS EnumInfo { INHERIT BaseInfo;
a187212012-04-01Marcus Comstedt  /*! @decl array(ValueInfo) get_values() */ PIKEFUN array(ValueInfo) get_values() { ONERROR onerror, onerror2; struct array *arr; gssize i, num; num = g_enum_info_get_n_values((GIEnumInfo *)THIS->info); arr = allocate_array(num); SET_ONERROR(onerror, do_free_array, arr); for(i=0; i<num; i++) { GIBaseInfo *info; info = (GIBaseInfo *)g_enum_info_get_value((GIEnumInfo *)THIS->info, i); SET_ONERROR(onerror2, g_base_info_unref, info); push_gi_info(info); UNSET_ONERROR(onerror2); g_base_info_unref(info); array_set_index_no_free(arr, i, Pike_sp-1); pop_stack(); } UNSET_ONERROR(onerror); RETURN arr; }
f243b12012-03-27Marcus Comstedt }
716ba02012-04-01Marcus Comstedt /*! @class InterfaceInfo
f243b12012-03-27Marcus Comstedt  */
716ba02012-04-01Marcus Comstedt PIKECLASS InterfaceInfo
f243b12012-03-27Marcus Comstedt { INHERIT BaseInfo; /*! @decl array(FunctionInfo) get_methods() */ PIKEFUN array(FunctionInfo) get_methods() { ONERROR onerror, onerror2; struct array *arr; gssize i, num;
716ba02012-04-01Marcus Comstedt  num = g_interface_info_get_n_methods((GIInterfaceInfo *)THIS->info);
f243b12012-03-27Marcus Comstedt  arr = allocate_array(num); SET_ONERROR(onerror, do_free_array, arr); for(i=0; i<num; i++) { GIBaseInfo *info; info =
716ba02012-04-01Marcus Comstedt  (GIBaseInfo *)g_interface_info_get_method((GIInterfaceInfo *)THIS->info, i);
f243b12012-03-27Marcus Comstedt  SET_ONERROR(onerror2, g_base_info_unref, info); push_gi_info(info); UNSET_ONERROR(onerror2); g_base_info_unref(info); array_set_index_no_free(arr, i, Pike_sp-1); pop_stack(); } UNSET_ONERROR(onerror); RETURN arr; } }
716ba02012-04-01Marcus Comstedt /*! @class ObjectInfo
f243b12012-03-27Marcus Comstedt  */
716ba02012-04-01Marcus Comstedt PIKECLASS ObjectInfo
f243b12012-03-27Marcus Comstedt { INHERIT BaseInfo;
716ba02012-04-01Marcus Comstedt  /*! @decl array(FunctionInfo) get_methods() */ PIKEFUN array(FunctionInfo) get_methods() { ONERROR onerror, onerror2; struct array *arr; gssize i, num; num = g_object_info_get_n_methods((GIObjectInfo *)THIS->info); arr = allocate_array(num); SET_ONERROR(onerror, do_free_array, arr); for(i=0; i<num; i++) { GIBaseInfo *info; info = (GIBaseInfo *)g_object_info_get_method((GIObjectInfo *)THIS->info, i); SET_ONERROR(onerror2, g_base_info_unref, info); push_gi_info(info); UNSET_ONERROR(onerror2); g_base_info_unref(info); array_set_index_no_free(arr, i, Pike_sp-1); pop_stack(); } UNSET_ONERROR(onerror); RETURN arr; } /*! @decl array(InterfaceInfo) get_interfaces() */ PIKEFUN array(InterfaceInfo) get_interfaces() { ONERROR onerror, onerror2; struct array *arr; gssize i, num; num = g_object_info_get_n_interfaces((GIObjectInfo *)THIS->info); arr = allocate_array(num); SET_ONERROR(onerror, do_free_array, arr); for(i=0; i<num; i++) { GIBaseInfo *info; info = (GIBaseInfo *)g_object_info_get_interface((GIObjectInfo *)THIS->info, i); SET_ONERROR(onerror2, g_base_info_unref, info); push_gi_info(info); UNSET_ONERROR(onerror2); g_base_info_unref(info); array_set_index_no_free(arr, i, Pike_sp-1); pop_stack(); } UNSET_ONERROR(onerror); RETURN arr; }
86d2882012-04-01Marcus Comstedt  /*! @decl ObjectInfo get_parent() */ PIKEFUN ObjectInfo get_parent() { ONERROR onerror; GIBaseInfo *info = (GIBaseInfo *)g_object_info_get_parent((GIObjectInfo *)THIS->info); if (info == NULL) { pop_n_elems(args); push_int(0); return; } SET_ONERROR(onerror, g_base_info_unref, info); pop_n_elems(args); push_gi_info(info); UNSET_ONERROR(onerror); g_base_info_unref(info); }
f243b12012-03-27Marcus Comstedt } /*! @class ConstantInfo */ PIKECLASS ConstantInfo { INHERIT BaseInfo;
6a75e92012-10-24Marcus Comstedt  struct const_value_context { GIConstantInfo *info; GIArgument *value; }; static void free_const_value_context(void *ptr) { struct const_value_context *ctx = ptr; g_constant_info_free_value(ctx->info, ctx->value); } /*! @decl mixed get() */ PIKEFUN mixed get() { ONERROR onerror, onerror2; GIArgument arg; struct const_value_context ctx = { (GIConstantInfo *)THIS->info, &arg }; GITypeInfo *info = g_constant_info_get_type(ctx.info); SET_ONERROR(onerror, g_base_info_unref, info); g_constant_info_get_value(ctx.info, &arg); SET_ONERROR(onerror2, free_const_value_context, &ctx); push_gi_argument(&arg, info); UNSET_ONERROR(onerror2); g_constant_info_free_value(ctx.info, &arg); UNSET_ONERROR(onerror); g_base_info_unref(info); stack_pop_n_elems_keep_top(args); }
f243b12012-03-27Marcus Comstedt } /*! @class UnionInfo */ PIKECLASS UnionInfo { INHERIT BaseInfo; } static void push_gi_info(GIBaseInfo *info) { struct program *p; if (info == NULL) Pike_error("Missing info\n"); switch(g_base_info_get_type(info)) { case GI_INFO_TYPE_FUNCTION:
29e7552018-11-04Marcus Comstedt  p = GI_FunctionInfo_program; break;
f243b12012-03-27Marcus Comstedt  case GI_INFO_TYPE_CALLBACK:
29e7552018-11-04Marcus Comstedt  p = GI_CallbackInfo_program; break;
f243b12012-03-27Marcus Comstedt  case GI_INFO_TYPE_STRUCT:
29e7552018-11-04Marcus Comstedt  p = GI_StructInfo_program; break;
f243b12012-03-27Marcus Comstedt  case GI_INFO_TYPE_ENUM: case GI_INFO_TYPE_FLAGS:
29e7552018-11-04Marcus Comstedt  p = GI_EnumInfo_program; break;
f243b12012-03-27Marcus Comstedt  case GI_INFO_TYPE_OBJECT:
29e7552018-11-04Marcus Comstedt  p = GI_ObjectInfo_program; break;
f243b12012-03-27Marcus Comstedt  case GI_INFO_TYPE_INTERFACE:
29e7552018-11-04Marcus Comstedt  p = GI_InterfaceInfo_program; break;
f243b12012-03-27Marcus Comstedt  case GI_INFO_TYPE_CONSTANT:
29e7552018-11-04Marcus Comstedt  p = GI_ConstantInfo_program; break;
f243b12012-03-27Marcus Comstedt  case GI_INFO_TYPE_UNION:
29e7552018-11-04Marcus Comstedt  p = GI_UnionInfo_program; break;
a187212012-04-01Marcus Comstedt  case GI_INFO_TYPE_VALUE:
29e7552018-11-04Marcus Comstedt  p = GI_ValueInfo_program; break;
4ae4b02012-10-28Marcus Comstedt  case GI_INFO_TYPE_FIELD:
29e7552018-11-04Marcus Comstedt  p = GI_FieldInfo_program; break;
f243b12012-03-27Marcus Comstedt  default: Pike_error("No class for %d\n", g_base_info_get_type(info)); } { struct object *o = clone_object(p, 0);
29e7552018-11-04Marcus Comstedt  struct GI_BaseInfo_struct *that = (struct GI_BaseInfo_struct *)get_storage (o, GI_BaseInfo_program);
f243b12012-03-27Marcus Comstedt  that->info = g_base_info_ref(info); push_object(o); } }
af08e02012-10-14Marcus Comstedt static void push_gvalue(const GValue *v) { GType gt = G_VALUE_TYPE(v); switch(G_TYPE_FUNDAMENTAL(gt)) { case G_TYPE_CHAR: push_int(g_value_get_schar(v)); break; case G_TYPE_UCHAR: push_int(g_value_get_uchar(v)); break; case G_TYPE_BOOLEAN: push_int(g_value_get_boolean(v)); break; case G_TYPE_INT: push_int(g_value_get_int(v)); break; case G_TYPE_UINT: push_int(g_value_get_uint(v)); break; case G_TYPE_LONG: push_int(g_value_get_long(v)); break; case G_TYPE_ULONG: push_int(g_value_get_ulong(v)); break; case G_TYPE_INT64: push_int64(g_value_get_int64(v)); break; case G_TYPE_UINT64: push_int64(g_value_get_uint64(v)); break; case G_TYPE_ENUM: push_int(g_value_get_enum(v)); break; case G_TYPE_FLAGS: push_int(g_value_get_flags(v)); break; case G_TYPE_FLOAT: push_float(g_value_get_float(v)); break; case G_TYPE_DOUBLE: push_float(g_value_get_double(v)); break; case G_TYPE_STRING: { const gchar *s = g_value_get_string(v); if (s == NULL) push_int(0); else { push_text(s); f_utf8_to_string(1); } break; }
19e0212012-10-22Marcus Comstedt 
f7e06e2012-10-24Marcus Comstedt  case G_TYPE_BOXED: push_wrapped_boxed(g_value_get_boxed(v), NULL, gt); break;
19e0212012-10-22Marcus Comstedt  case G_TYPE_OBJECT: push_wrapped_gobject(g_value_get_object(v), NULL); break;
af08e02012-10-14Marcus Comstedt  default: Pike_error("Don't know how to push a gvalue type %d\n", G_TYPE_FUNDAMENTAL(gt)); } }
a0383e2012-10-07Marcus Comstedt static void set_gvalue_from_svalue(GValue *v, const struct svalue *s) { GType gt = G_VALUE_TYPE(v); switch(G_TYPE_FUNDAMENTAL(gt)) { case G_TYPE_CHAR: if (TYPEOF(*s) != PIKE_T_INT) Pike_error("int expected\n"); g_value_set_schar(v, s->u.integer); break; case G_TYPE_UCHAR: if (TYPEOF(*s) != PIKE_T_INT) Pike_error("int expected\n"); g_value_set_uchar(v, s->u.integer); break; case G_TYPE_BOOLEAN: g_value_set_boolean(v, !UNSAFE_IS_ZERO(s)); break; case G_TYPE_INT: if (TYPEOF(*s) != PIKE_T_INT) Pike_error("int expected\n"); g_value_set_int(v, s->u.integer); break; case G_TYPE_UINT: if (TYPEOF(*s) != PIKE_T_INT) Pike_error("int expected\n"); g_value_set_uint(v, s->u.integer); break; case G_TYPE_LONG: if (TYPEOF(*s) != PIKE_T_INT) Pike_error("int expected\n"); g_value_set_long(v, s->u.integer); break; case G_TYPE_ULONG: if (TYPEOF(*s) != PIKE_T_INT) Pike_error("int expected\n"); g_value_set_ulong(v, s->u.integer); break; case G_TYPE_INT64: if (TYPEOF(*s) != PIKE_T_INT) Pike_error("int expected\n"); g_value_set_int64(v, s->u.integer); break; case G_TYPE_UINT64: if (TYPEOF(*s) != PIKE_T_INT) Pike_error("int expected\n"); g_value_set_uint64(v, s->u.integer); break; case G_TYPE_ENUM: if (TYPEOF(*s) != PIKE_T_INT) Pike_error("int expected\n"); g_value_set_enum(v, s->u.integer); break; case G_TYPE_FLAGS: if (TYPEOF(*s) != PIKE_T_INT) Pike_error("int expected\n"); g_value_set_flags(v, s->u.integer); break; case G_TYPE_FLOAT: if (TYPEOF(*s) == PIKE_T_INT) g_value_set_float(v, (gfloat)s->u.integer); else if (TYPEOF(*s) == PIKE_T_FLOAT) g_value_set_float(v, (gfloat)s->u.float_number); else Pike_error("float expected\n"); break; case G_TYPE_DOUBLE: if (TYPEOF(*s) == PIKE_T_INT) g_value_set_double(v, (gdouble)s->u.integer); else if (TYPEOF(*s) == PIKE_T_FLOAT) g_value_set_double(v, (gdouble)s->u.float_number); else Pike_error("float expected\n"); break; case G_TYPE_STRING: if (UNSAFE_IS_ZERO(s)) { g_value_set_string(v, NULL); break; } if (TYPEOF(*s) != PIKE_T_STRING) Pike_error("Expected string\n"); ref_push_string(s->u.string); f_string_to_utf8(1); g_value_set_string(v, (const gchar *)STR0(Pike_sp[-1].u.string)); pop_stack(); break;
097e0e2012-10-26Marcus Comstedt  case G_TYPE_OBJECT: if (UNSAFE_IS_ZERO(s)) { g_value_set_object(v, NULL); break; } if (TYPEOF(*s) != T_OBJECT) Pike_error("object expected\n"); else {
29e7552018-11-04Marcus Comstedt  struct GI_GObject_struct *that = (struct GI_GObject_struct *)get_storage (s->u.object, GI_GObject_program);
097e0e2012-10-26Marcus Comstedt  if (that == NULL) Pike_error("argument is not a GObject\n"); if (that->obj == NULL || !g_type_is_a(G_OBJECT_TYPE(that->obj), gt)) { const gchar *tn = g_type_name(gt); if (tn) Pike_error("Object is not a %s\n", tn); else Pike_error("Object is not of the correct type\n"); } g_value_set_object(v, that->obj); } break;
a0383e2012-10-07Marcus Comstedt  default: Pike_error("Don't know how to set a gvalue type %d\n", G_TYPE_FUNDAMENTAL(gt)); } } static int build_one_parameter(GObjectClass *class, GParameter *p, const struct svalue *name, const struct svalue *value) { GParamSpec *pspec; if (name == NULL || TYPEOF(*name) != PIKE_T_STRING) Pike_error("Invalid type for parameter name\n"); ref_push_string(name->u.string); f_string_to_utf8(1); p->name = g_strdup((const gchar *)STR0(Pike_sp[-1].u.string)); pop_stack(); pspec = g_object_class_find_property(class, p->name); if (pspec == NULL) Pike_error("GObject %s does not support property %S\n", G_OBJECT_CLASS_NAME(class), name->u.string); g_value_init(&p->value, G_PARAM_SPEC_VALUE_TYPE(pspec)); set_gvalue_from_svalue(&p->value, value); return 1; } static guint build_parameters_from_mapping(GType gt, struct mapping *m, guint free_space, GParameter *parms) { ONERROR onerror; INT32 e; struct keypair *k; guint count = 0; GObjectClass *class = g_type_class_ref(gt); if (class == NULL) Pike_error("Type class not available!\n"); SET_ONERROR(onerror, g_type_class_unref, class); NEW_MAPPING_LOOP(m->data) if (free_space && build_one_parameter(class, parms, &k->ind, &k->val)) { --free_space; count++; parms++; } UNSET_ONERROR(onerror); g_type_class_unref(class); return count; } struct gparams_list { guint nparam; GParameter *params; }; static void low_free_gparams(struct gparams_list *gpl) { guint i; guint nparam = gpl->nparam; GParameter *params = gpl->params; if (params) { for (i = 0; i < nparam; i++) { g_free((gchar *)params[i].name); if (G_VALUE_TYPE(&params[i].value) != G_TYPE_INVALID) g_value_unset(&params[i].value); } g_free(params); gpl->params = NULL; } } static GObject *make_gobject_from_props(struct object *info, struct mapping *props) { ONERROR onerror; GIObjectInfo *ginfo;
29e7552018-11-04Marcus Comstedt  struct GI_BaseInfo_struct *that;
a0383e2012-10-07Marcus Comstedt  GType gt; GObject *obj; struct gparams_list params = { 0, NULL }; if (info == NULL || (that =
29e7552018-11-04Marcus Comstedt  (struct GI_BaseInfo_struct *)get_storage (info, GI_BaseInfo_program))
a0383e2012-10-07Marcus Comstedt  == NULL || that->info == NULL) Pike_error("ObjectInfo missing\n"); ginfo = (GIObjectInfo *)that->info; gt = g_registered_type_info_get_g_type((GIRegisteredTypeInfo *)ginfo); if (gt == G_TYPE_NONE) Pike_error("Failed to get GType\n"); if (props != NULL && m_sizeof(props) > 0) { params.nparam = m_sizeof(props); params.params = g_new0(GParameter, params.nparam); SET_ONERROR(onerror, low_free_gparams, &params); params.nparam = build_parameters_from_mapping(gt, props, params.nparam, params.params); } obj = g_object_newv(gt, params.nparam, params.params); if (obj == NULL) Pike_error("Failed to create GObject\n"); if (params.params != NULL) { UNSET_ONERROR(onerror); low_free_gparams(&params); } if (G_IS_INITIALLY_UNOWNED(obj)) g_object_ref_sink(obj); return obj; }
29e7552018-11-04Marcus Comstedt static void make_gboxed(struct GI_GBoxed_struct *this, struct object *info, gboolean allocate)
79edc92012-10-28Marcus Comstedt {
29e7552018-11-04Marcus Comstedt  struct GI_BaseInfo_struct *that;
79edc92012-10-28Marcus Comstedt  if (info == NULL || (that =
29e7552018-11-04Marcus Comstedt  (struct GI_BaseInfo_struct *)get_storage (info, GI_BaseInfo_program))
79edc92012-10-28Marcus Comstedt  == NULL || that->info == NULL) Pike_error("StructInfo missing\n"); this->type = g_registered_type_info_get_g_type(that->info); if (allocate) { if ((this->allocated_size = get_interface_size(that->info))) this->box = g_slice_alloc0(this->allocated_size); } }
a0383e2012-10-07Marcus Comstedt 
f243b12012-03-27Marcus Comstedt /*! @class Repository */ PIKECLASS Repository { CVAR GIRepository *repository; INIT { THIS->repository = NULL; }
b5f0022012-03-30Marcus Comstedt  /*! @decl array(string) enumerate_versions(strig namespace) */ PIKEFUN array(string) enumerate_versions(string namespace) { ONERROR onerror; int count = 0; GList *item, *versions = g_irepository_enumerate_versions(THIS->repository, (gchar *)STR0(namespace)); if (versions == NULL) { pop_n_elems(args); push_int(0); return; } SET_ONERROR(onerror, free_glist_full_free, versions); pop_n_elems(args); for (item = versions; item; item = item->next) { char *version = item->data; push_text(version); f_utf8_to_string(1); count++; } UNSET_ONERROR(onerror); free_glist_full_free(versions); f_aggregate(count); } /*! @decl BaseInfo find_by_name(string namespace, string name) */ PIKEFUN BaseInfo find_by_name(string namespace, string name) { ONERROR onerror; GIBaseInfo *info = g_irepository_find_by_name(THIS->repository, (gchar *)STR0(namespace), (gchar *)STR0(name)); if (info) { SET_ONERROR(onerror, g_base_info_unref, info); pop_n_elems(args); push_gi_info(info); UNSET_ONERROR(onerror); g_base_info_unref(info); } else { pop_n_elems(args); push_int(0); } }
f243b12012-03-27Marcus Comstedt  /*! @decl array(BaseInfo) get_infos(string namespace) */ PIKEFUN array(BaseInfo) get_infos(string namespace) { ONERROR onerror, onerror2; struct array *arr; gssize i, num; num = g_irepository_get_n_infos(THIS->repository, (gchar *)STR0(namespace)); if (num < 0) Pike_error("Namespace '%S' not loaded\n", namespace); arr = allocate_array(num); SET_ONERROR(onerror, do_free_array, arr); for(i=0; i<num; i++) { GIBaseInfo *info; info = g_irepository_get_info(THIS->repository, (gchar *)STR0(namespace), i); SET_ONERROR(onerror2, g_base_info_unref, info); push_gi_info(info); UNSET_ONERROR(onerror2); g_base_info_unref(info); array_set_index_no_free(arr, i, Pike_sp-1); pop_stack(); } UNSET_ONERROR(onerror); RETURN arr; } /*! @decl void require(string namespace, string|void version, int(0..1)|void lazy) */ PIKEFUN void require(string namespace, string|void version, int(0..1)|void lazy) { GError *error = NULL; GTypelib *typelib; typelib = g_irepository_require(THIS->repository, (gchar *)STR0(namespace), (version? (gchar *)STR0(version) : NULL), ((lazy != NULL && !UNSAFE_IS_ZERO(lazy))? G_IREPOSITORY_LOAD_FLAG_LAZY : 0), &error); if(error) throw_gerror(error); pop_n_elems(args); /* Should be "RETURN;", but that is broken... */ } } /*! @endclass */ /*! @decl Repository get_default_repository() */ PIKEFUN Repository get_default_repository() { static struct object *default_repository = NULL; if (default_repository == NULL) {
29e7552018-11-04Marcus Comstedt  struct object *o = clone_object(GI_Repository_program, 0); struct GI_Repository_struct *that = (struct GI_Repository_struct *)get_storage (o, GI_Repository_program);
f243b12012-03-27Marcus Comstedt  that->repository = g_irepository_get_default(); default_repository = o; } ref_push_object(default_repository); } /*! @endmodule */ #endif PIKE_MODULE_INIT { #ifdef HAVE_GI g_type_init();
a149202012-04-01Marcus Comstedt  object_quark = g_quark_from_static_string("PikeGI::object");
a0383e2012-10-07Marcus Comstedt  magic_mapping = allocate_mapping(0);
f243b12012-03-27Marcus Comstedt  INIT #endif } PIKE_MODULE_EXIT { #ifdef HAVE_GI EXIT
a0383e2012-10-07Marcus Comstedt  if(magic_mapping) { free_mapping(magic_mapping); magic_mapping = NULL; }
f243b12012-03-27Marcus Comstedt #endif }