static void *
_get_func(GIObjectInfo *info,
          SymbolGetter getter)
{
  const char* symbol;
  GSList *parents = NULL, *l;
  GIObjectInfo *parent_info;
  gpointer func = NULL;

  parent_info = g_base_info_ref (info);
  while (parent_info != NULL)
    {
      parents = g_slist_prepend (parents, parent_info);
      parent_info = g_object_info_get_parent (parent_info);
    }

  for (l = parents; l; l = l->next)
    {
      parent_info = l->data;
      symbol = getter (parent_info);
      if (symbol == NULL)
        continue;

      g_typelib_symbol (((GIRealInfo *)parent_info)->typelib, symbol, (gpointer*) &func);
      if (func)
        break;
    }

  g_slist_free_full (parents, (GDestroyNotify) g_base_info_unref);
  return func;
}
Exemple #2
0
static GIBaseInfo *
struct_get_info (PyTypeObject *type)
{
    PyObject *py_info;
    GIBaseInfo *info = NULL;

    py_info = PyObject_GetAttrString ((PyObject *)type, "__info__");
    if (py_info == NULL) {
        return NULL;
    }
    if (!PyObject_TypeCheck (py_info, &PyGIStructInfo_Type) &&
            !PyObject_TypeCheck (py_info, &PyGIUnionInfo_Type)) {
        PyErr_Format (PyExc_TypeError, "attribute '__info__' must be %s or %s, not %s",
                      PyGIStructInfo_Type.tp_name,
                      PyGIUnionInfo_Type.tp_name,
                      Py_TYPE(py_info)->tp_name);
        goto out;
    }

    info = ( (PyGIBaseInfo *) py_info)->info;
    g_base_info_ref (info);

out:
    Py_DECREF (py_info);

    return info;
}
GIBaseInfo *
_pygi_object_get_gi_info (PyObject     *object,
                          PyTypeObject *type)
{
    PyObject *py_info;
    GIBaseInfo *info = NULL;

    py_info = PyObject_GetAttrString (object, "__info__");
    if (py_info == NULL) {
        return NULL;
    }
    if (!PyObject_TypeCheck (py_info, type)) {
        PyErr_Format (PyExc_TypeError, "attribute '__info__' must be %s, not %s",
                      type->tp_name, Py_TYPE(&py_info)->tp_name);
        goto out;
    }

    info = ( (PyGIBaseInfo *) py_info)->info;
    g_base_info_ref (info);

out:
    Py_DECREF (py_info);

    return info;
}
Exemple #4
0
PyGICClosure*
_pygi_make_native_closure (GICallableInfo* info,
                           GIArgInfo* arg_info,
                           PyObject *py_function,
                           gpointer py_user_data)
{
    PyGICClosure *closure;
    ffi_closure *fficlosure;

    /* Begin by cleaning up old async functions */
    g_slist_foreach(async_free_list, (GFunc)_pygi_invoke_closure_free, NULL);
    g_slist_free(async_free_list);
    async_free_list = NULL;

    /* Build the closure itself */
    closure = g_slice_new0(PyGICClosure);
    closure->info = (GICallableInfo *) g_base_info_ref ((GIBaseInfo *) info);
    closure->function = py_function;
    closure->user_data = py_user_data;

    Py_INCREF(py_function);
    if (closure->user_data)
        Py_INCREF(closure->user_data);

    fficlosure =
        g_callable_info_prepare_closure (info, &closure->cif, _pygi_closure_handle,
                                         closure);
    closure->closure = fficlosure;

    /* Give the closure the information it needs to determine when
       to free itself later */
    closure->scope = g_arg_info_get_scope(arg_info);

    return closure;
}
static GPerlI11nPerlCallbackInfo *
create_perl_callback_closure (GICallableInfo *cb_info, SV *code)
{
	GPerlI11nPerlCallbackInfo *info;

	info = g_new0 (GPerlI11nPerlCallbackInfo, 1);
	if (!gperl_sv_is_defined (code))
		return info;

	info->interface = g_base_info_ref (cb_info);
	info->cif = g_new0 (ffi_cif, 1);
	info->closure =
		g_callable_info_prepare_closure (info->interface, info->cif,
		                                 invoke_perl_code, info);
	/* FIXME: This should most likely use SvREFCNT_inc instead of
	 * newSVsv. */
	info->code = newSVsv (code);
	info->sub_name = NULL;

	/* These are only relevant for signal marshalling; if needed, they get
	 * set in invoke_perl_signal_handler. */
	info->swap_data = FALSE;
	info->args_converter = NULL;

#ifdef PERL_IMPLICIT_CONTEXT
	info->priv = aTHX;
#endif

	return info;
}
Exemple #6
0
PyObject *
_pygi_ccallback_new (GCallback callback,
                     gpointer user_data,
                     GIScopeType scope,
                     GIFunctionInfo *info,
                     GDestroyNotify destroy_notify)
{
    PyGICCallback *self;

    if (!callback) {
        Py_RETURN_NONE;
    }

    self = (PyGICCallback *) PyGICCallback_Type.tp_alloc (&PyGICCallback_Type, 0);
    if (self == NULL) {
        return NULL;
    }

    self->callback = (GCallback) callback;
    self->user_data = user_data;
    self->scope = scope;
    self->destroy_notify_func = destroy_notify;
    self->info = g_base_info_ref( (GIBaseInfo *) info);

    return (PyObject *) self;
}
Exemple #7
0
JSObject*
gjs_boxed_from_c_struct(JSContext             *context,
                        GIStructInfo          *info,
                        void                  *gboxed,
                        GjsBoxedCreationFlags  flags)
{
    JSObject *obj;
    JSObject *proto;
    Boxed *priv;
    Boxed *proto_priv;

    if (gboxed == NULL)
        return NULL;

    gjs_debug_marshal(GJS_DEBUG_GBOXED,
                      "Wrapping struct %s %p with JSObject",
                      g_base_info_get_name((GIBaseInfo *)info), gboxed);

    proto = gjs_lookup_boxed_prototype(context, info);
    proto_priv = priv_from_js(context, proto);

    obj = JS_NewObjectWithGivenProto(context,
                                     JS_GET_CLASS(context, proto), proto,
                                     gjs_get_import_global (context));

    GJS_INC_COUNTER(boxed);
    priv = g_slice_new0(Boxed);

    *priv = *proto_priv;
    g_base_info_ref( (GIBaseInfo*) priv->info);

    JS_SetPrivate(context, obj, priv);

    if ((flags & GJS_BOXED_CREATION_NO_COPY) != 0) {
        /* we need to create a JS Boxed which references the
         * original C struct, not a copy of it. Used for
         * G_SIGNAL_TYPE_STATIC_SCOPE
         */
        priv->gboxed = gboxed;
        priv->not_owning_gboxed = TRUE;
    } else {
        if (priv->gtype != G_TYPE_NONE && g_type_is_a (priv->gtype, G_TYPE_BOXED)) {
            priv->gboxed = g_boxed_copy(priv->gtype, gboxed);
        } else if (priv->gtype == G_TYPE_VARIANT) {
            priv->gboxed = g_variant_ref_sink (gboxed);
        } else if (priv->can_allocate_directly) {
            boxed_new_direct(priv);
            memcpy(priv->gboxed, gboxed, g_struct_info_get_size (priv->info));
        } else {
            gjs_throw(context,
                      "Can't create a Javascript object for %s; no way to copy",
                      g_base_info_get_name( (GIBaseInfo*) priv->info));
        }
    }

    return obj;
}
Exemple #8
0
void
gjs_define_error_class(JSContext    *context,
                       JSObject     *in_object,
                       GIEnumInfo   *info)
{
    const char *constructor_name;
    GIBoxedInfo *glib_error_info;
    JSObject *prototype, *parent_proto;
    JSObject *constructor;
    Error *priv;

    /* See the comment in gjs_define_boxed_class() for an
     * explanation of how this all works; Error is pretty much the
     * same as Boxed (except that we inherit from GLib.Error).
     */

    constructor_name = g_base_info_get_name( (GIBaseInfo*) info);

    g_irepository_require(NULL, "GLib", "2.0", (GIRepositoryLoadFlags) 0, NULL);
    glib_error_info = (GIBoxedInfo*) g_irepository_find_by_name(NULL, "GLib", "Error");
    parent_proto = gjs_lookup_generic_prototype(context, glib_error_info);
    g_base_info_unref((GIBaseInfo*)glib_error_info);

    if (!gjs_init_class_dynamic(context, in_object,
                                parent_proto,
                                g_base_info_get_namespace( (GIBaseInfo*) info),
                                constructor_name,
                                &gjs_error_class,
                                gjs_error_constructor, 1,
                                /* props of prototype */
                                &gjs_error_proto_props[0],
                                /* funcs of prototype */
                                &gjs_error_proto_funcs[0],
                                /* props of constructor, MyConstructor.myprop */
                                NULL,
                                /* funcs of constructor, MyConstructor.myfunc() */
                                &gjs_error_constructor_funcs[0],
                                &prototype,
                                &constructor)) {
        gjs_log_exception(context);
        g_error("Can't init class %s", constructor_name);
    }

    GJS_INC_COUNTER(gerror);
    priv = g_slice_new0(Error);
    priv->info = info;
    g_base_info_ref( (GIBaseInfo*) priv->info);
    priv->domain = g_quark_from_string (g_enum_info_get_error_domain(priv->info));

    JS_SetPrivate(prototype, priv);

    gjs_debug(GJS_DEBUG_GBOXED, "Defined class %s prototype is %p class %p in object %p",
              constructor_name, prototype, JS_GetClass(prototype), in_object);

    gjs_define_enum_values(context, constructor, priv->info);
    gjs_define_enum_static_methods(context, constructor, priv->info);
}
Exemple #9
0
static JSBool
get_nested_interface_object (JSContext   *context,
                             JSObject    *parent_obj,
                             Boxed       *parent_priv,
                             GIFieldInfo *field_info,
                             GITypeInfo  *type_info,
                             GIBaseInfo  *interface_info,
                             jsval       *value)
{
    JSObject *obj;
    JSObject *proto;
    int offset;
    Boxed *priv;
    Boxed *proto_priv;

    if (!struct_is_simple ((GIStructInfo *)interface_info)) {
        gjs_throw(context, "Reading field %s.%s is not supported",
                  g_base_info_get_name ((GIBaseInfo *)parent_priv->info),
                  g_base_info_get_name ((GIBaseInfo *)field_info));

        return JS_FALSE;
    }

    proto = gjs_lookup_boxed_prototype(context, (GIBoxedInfo*) interface_info);
    proto_priv = priv_from_js(context, proto);

    offset = g_field_info_get_offset (field_info);

    obj = JS_NewObjectWithGivenProto(context,
                                     JS_GET_CLASS(context, proto), proto,
                                     gjs_get_import_global (context));

    if (obj == NULL)
        return JS_FALSE;

    GJS_INC_COUNTER(boxed);
    priv = g_slice_new0(Boxed);
    JS_SetPrivate(context, obj, priv);
    priv->info = (GIBoxedInfo*) interface_info;
    g_base_info_ref( (GIBaseInfo*) priv->info);
    priv->gtype = g_registered_type_info_get_g_type ((GIRegisteredTypeInfo*) interface_info);
    priv->can_allocate_directly = proto_priv->can_allocate_directly;

    /* A structure nested inside a parent object; doesn't have an independent allocation */
    priv->gboxed = ((char *)parent_priv->gboxed) + offset;
    priv->not_owning_gboxed = TRUE;

    /* We never actually read the reserved slot, but we put the parent object
     * into it to hold onto the parent object.
     */
    JS_SetReservedSlot(context, obj, 0,
                       OBJECT_TO_JSVAL (parent_obj));

    *value = OBJECT_TO_JSVAL(obj);
    return JS_TRUE;
}
Exemple #10
0
/*
 * Set up prototype and constructor for structs. Same semantics as objects
 * except
 * for the type.
 */
static void
seed_gi_importer_handle_struct(JSContextRef ctx,
                               JSObjectRef namespace_ref,
                               GIStructInfo* info,
                               JSValueRef* exception)
{
    JSObjectRef struct_ref;
    JSObjectRef proto;
    gint i, n_methods;
    GIFunctionInfo* finfo;

    struct_ref = JSObjectMake(ctx, seed_struct_constructor_class, info);
    g_base_info_ref(info);

    n_methods = g_struct_info_get_n_methods(info);

    for (i = 0; i < n_methods; i++) {
        GIFunctionInfoFlags flags;
        finfo = g_struct_info_get_method(info, i);

        flags = g_function_info_get_flags(finfo);

        if (flags & GI_FUNCTION_IS_CONSTRUCTOR) {
            JSObjectRef constructor
              = JSObjectMake(ctx, gobject_named_constructor_class, finfo);
            const gchar* fname = g_base_info_get_name((GIBaseInfo*) finfo);
            if (g_strrstr(fname, "new_") == fname) {
                // To be compatible with gjs, we need to have a method with
                // new_, too.
                seed_object_set_property(ctx, struct_ref, fname, constructor);
                fname += 4;
            }

            else if (!g_strcmp0(fname, "new")) {
                // To be compatible with gjs, we need to have new as function,
                // too.
                seed_object_set_property(ctx, struct_ref, fname, constructor);
                fname = "c_new";
            }

            seed_object_set_property(ctx, struct_ref, fname, constructor);
        } else if (flags & GI_FUNCTION_IS_METHOD)
            g_base_info_unref((GIBaseInfo*) finfo);
        else
            seed_gobject_define_property_from_function_info(ctx, finfo,
                                                            struct_ref, FALSE);
    }

    proto = seed_struct_prototype(ctx, (GIBaseInfo*) info);
    seed_object_set_property(ctx, struct_ref, "prototype", proto);

    seed_object_set_property(ctx, namespace_ref,
                             g_base_info_get_name((GIBaseInfo*) info),
                             struct_ref);
}
Exemple #11
0
JSObject*
gjs_error_from_gerror(JSContext             *context,
                      GError                *gerror,
                      gboolean               add_stack)
{
    JSObject *obj;
    JSObject *proto;
    Error *priv;
    Error *proto_priv;
    GIEnumInfo *info;

    if (gerror == NULL)
        return NULL;

    info = find_error_domain_info(gerror->domain);

    if (!info) {
        /* We don't have error domain metadata */
        /* Marshal the error as a plain GError */
        GIBaseInfo *glib_boxed;
        JSObject *retval;

        glib_boxed = g_irepository_find_by_name(NULL, "GLib", "Error");
        retval = gjs_boxed_from_c_struct(context, glib_boxed, gerror, 0);

        g_base_info_unref(glib_boxed);
        return retval;
    }

    gjs_debug_marshal(GJS_DEBUG_GBOXED,
                      "Wrapping struct %s %p with JSObject",
                      g_base_info_get_name((GIBaseInfo *)info), gboxed);

    proto = gjs_lookup_error_prototype(context, info);
    proto_priv = priv_from_js(context, proto);

    obj = JS_NewObjectWithGivenProto(context,
                                     JS_GET_CLASS(context, proto), proto,
                                     gjs_get_import_global (context));

    GJS_INC_COUNTER(gerror);
    priv = g_slice_new0(Error);
    JS_SetPrivate(context, obj, priv);
    priv->info = info;
    priv->domain = proto_priv->domain;
    g_base_info_ref( (GIBaseInfo*) priv->info);
    priv->gerror = g_error_copy(gerror);

    if (add_stack)
        define_error_properties(context, obj);

    return obj;
}
Exemple #12
0
bool
gjs_define_interface_class(JSContext              *context,
                           JS::HandleObject        in_object,
                           GIInterfaceInfo        *info,
                           GType                   gtype,
                           JS::MutableHandleObject constructor)
{
    Interface *priv;
    const char *constructor_name;
    const char *ns;
    JS::RootedObject prototype(context);

    ns = gjs_get_names_from_gtype_and_gi_info(gtype, (GIBaseInfo *) info,
                                              &constructor_name);

    if (!gjs_init_class_dynamic(context, in_object,
                                JS::NullPtr(),
                                ns,
                                constructor_name,
                                &gjs_interface_class,
                                gjs_interface_constructor, 0,
                                /* props of prototype */
                                &gjs_interface_proto_props[0],
                                /* funcs of prototype */
                                &gjs_interface_proto_funcs[0],
                                /* props of constructor, MyConstructor.myprop */
                                NULL,
                                /* funcs of constructor, MyConstructor.myfunc() */
                                NULL,
                                &prototype,
                                constructor)) {
        g_error("Can't init class %s", constructor_name);
    }

    GJS_INC_COUNTER(interface);
    priv = g_slice_new0(Interface);
    priv->info = info == NULL ? NULL : g_base_info_ref((GIBaseInfo *) info);
    priv->gtype = gtype;
    priv->vtable = (GTypeInterface *) g_type_default_interface_ref(gtype);
    JS_SetPrivate(prototype, priv);

    /* If we have no GIRepository information, then this interface was defined
     * from within GJS and therefore has no C static methods to be defined. */
    if (priv->info)
        gjs_define_static_methods(context, constructor, priv->gtype, priv->info);

    JS::RootedObject gtype_obj(context,
        gjs_gtype_create_gtype_wrapper(context, priv->gtype));
    JS_DefineProperty(context, constructor, "$gtype", gtype_obj, JSPROP_PERMANENT);

    return true;
}
static GPerlI11nCCallbackInfo *
create_c_callback_closure (GIBaseInfo *interface, gpointer func)
{
	GPerlI11nCCallbackInfo *info;

	info = g_new0 (GPerlI11nCCallbackInfo, 1);
	if (!func)
		return info;

	info->interface = interface;
	g_base_info_ref (interface);
	info->func = func;

	return info;
}
Exemple #14
0
static void
seed_gi_importer_handle_function(JSContextRef ctx,
                                 JSObjectRef namespace_ref,
                                 GIFunctionInfo* info,
                                 JSValueRef* exception)
{
    if (!seed_gi_importer_is_init(info))
        seed_gobject_define_property_from_function_info(ctx,
                                                        (GIFunctionInfo*) info,
                                                        namespace_ref, FALSE);
    else {
        JSObjectRef init_method;

        init_method = JSObjectMake(ctx, gobject_init_method_class,
                                   g_base_info_ref((GIBaseInfo*) info));
        seed_object_set_property(ctx, namespace_ref, "init", init_method);
    }
}
/* assumes ownership of sub_name */
static GPerlI11nPerlCallbackInfo *
create_perl_callback_closure_for_named_sub (GICallableInfo *cb_info, gchar *sub_name)
{
	GPerlI11nPerlCallbackInfo *info;

	info = g_new0 (GPerlI11nPerlCallbackInfo, 1);
	info->interface = g_base_info_ref (cb_info);
	info->cif = g_new0 (ffi_cif, 1);
	info->closure =
		g_callable_info_prepare_closure (info->interface, info->cif,
		                                 invoke_perl_code, info);
	info->sub_name = sub_name;
	info->code = NULL;
	info->data = NULL;

#ifdef PERL_IMPLICIT_CONTEXT
	info->priv = aTHX;
#endif

	return info;
}
/**
 * g_object_info_find_vfunc_using_interfaces:
 * @info: a #GIObjectInfo
 * @name: name of method to obtain
 * @implementor: (out) (transfer full): The implementor of the interface
 *
 * Locate a virtual function slot with name @name, searching both the object
 * @info and any interfaces it implements.  Note that the namespace for
 * virtuals is distinct from that of methods; there may or may not be a
 * concrete method associated for a virtual. If there is one, it may be
 * retrieved using g_vfunc_info_get_invoker(), otherwise %NULL will be
 * returned.
 *
 * Note that this function does *not* search parent classes; you will have
 * to chain up if that's desired.
 *
 * Returns: (transfer full): the #GIFunctionInfo. Free the struct by calling
 * g_base_info_unref() when done.
 */
GIVFuncInfo *
g_object_info_find_vfunc_using_interfaces (GIObjectInfo  *info,
                                           const gchar   *name,
                                           GIObjectInfo **implementor)
{
  GIVFuncInfo *result = NULL;
  GIObjectInfo *implementor_result = NULL;

  result = g_object_info_find_vfunc (info, name);
  if (result)
    implementor_result = g_base_info_ref ((GIBaseInfo*) info);

  if (result == NULL)
    {
      int n_interfaces;
      int i;

      n_interfaces = g_object_info_get_n_interfaces (info);
      for (i = 0; i < n_interfaces; ++i)
	{
	  GIInterfaceInfo *iface_info;

	  iface_info = g_object_info_get_interface (info, i);

	  result = g_interface_info_find_vfunc (iface_info, name);

	  if (result != NULL)
	    {
	      implementor_result = iface_info;
	      break;
	    }
	  g_base_info_unref ((GIBaseInfo*) iface_info);
	}
    }
  if (implementor)
    *implementor = implementor_result;
  else if (implementor_result != NULL)
    g_base_info_unref ((GIBaseInfo*) implementor_result);
  return result;
}
Exemple #17
0
static void
seed_gi_importer_handle_union(JSContextRef ctx,
                              JSObjectRef namespace_ref,
                              GIUnionInfo* info,
                              JSValueRef* exception)
{
    JSObjectRef union_ref;
    JSObjectRef proto;
    guint i, n_methods;
    GIFunctionInfo* finfo;

    union_ref = JSObjectMake(ctx, seed_struct_constructor_class, info);
    g_base_info_ref(info);

    n_methods = g_union_info_get_n_methods(info);

    for (i = 0; i < n_methods; i++) {
        GIFunctionInfoFlags flags;
        finfo = g_union_info_get_method(info, i);

        flags = g_function_info_get_flags(finfo);

        if (flags & GI_FUNCTION_IS_METHOD)
            g_base_info_unref((GIBaseInfo*) finfo);
        else
            seed_gobject_define_property_from_function_info(ctx, finfo,
                                                            union_ref, FALSE);
    }

    proto = seed_union_prototype(ctx, (GIBaseInfo*) info);
    seed_object_set_property(ctx, union_ref, "prototype", proto);

    seed_object_set_property(ctx, namespace_ref,
                             g_base_info_get_name((GIBaseInfo*) info),
                             union_ref);
}
Exemple #18
0
JSBool
gjs_define_fundamental_class(JSContext     *context,
                             JSObject      *in_object,
                             GIObjectInfo  *info,
                             JSObject     **constructor_p,
                             JSObject     **prototype_p)
{
    const char *constructor_name;
    JSObject *prototype;
    jsval value;
    jsid js_constructor_name = JSID_VOID;
    JSObject *parent_proto;
    Fundamental *priv;
    JSObject *constructor;
    GType parent_gtype;
    GType gtype;
    GIFunctionInfo *constructor_info;
    /* See the comment in gjs_define_object_class() for an explanation
     * of how this all works; Fundamental is pretty much the same as
     * Object.
     */

    constructor_name = g_base_info_get_name((GIBaseInfo *) info);
    constructor_info = find_fundamental_constructor(context, info,
                                                    &js_constructor_name);

    gtype = g_registered_type_info_get_g_type (info);
    parent_gtype = g_type_parent(gtype);
    parent_proto = NULL;
    if (parent_gtype != G_TYPE_INVALID)
        parent_proto = gjs_lookup_fundamental_prototype_from_gtype(context,
                                                                   parent_gtype);

    if (!gjs_init_class_dynamic(context, in_object,
                                /* parent prototype JSObject* for
                                 * prototype; NULL for
                                 * Object.prototype
                                 */
                                parent_proto,
                                g_base_info_get_namespace((GIBaseInfo *) info),
                                constructor_name,
                                &gjs_fundamental_instance_class,
                                gjs_fundamental_instance_constructor,
                                /* number of constructor args (less can be passed) */
                                constructor_info != NULL ? g_callable_info_get_n_args((GICallableInfo *) constructor_info) : 0,
                                /* props of prototype */
                                parent_proto ? NULL : &gjs_fundamental_instance_proto_props[0],
                                /* funcs of prototype */
                                parent_proto ? NULL : &gjs_fundamental_instance_proto_funcs[0],
                                /* props of constructor, MyConstructor.myprop */
                                NULL,
                                /* funcs of constructor, MyConstructor.myfunc() */
                                NULL,
                                &prototype,
                                &constructor)) {
        gjs_log_exception(context);
        g_error("Can't init class %s", constructor_name);
    }

    /* Put the info in the prototype */
    priv = g_slice_new0(Fundamental);
    g_assert(priv != NULL);
    g_assert(priv->info == NULL);
    priv->info = g_base_info_ref((GIBaseInfo *) info);
    priv->gtype = gtype;
    priv->constructor_name = js_constructor_name;
    priv->constructor_info = constructor_info;
    priv->ref_function = g_object_info_get_ref_function_pointer(info);
    g_assert(priv->ref_function != NULL);
    priv->unref_function = g_object_info_get_unref_function_pointer(info);
    g_assert(priv->unref_function != NULL);
    priv->set_value_function = g_object_info_get_set_value_function_pointer(info);
    g_assert(priv->set_value_function != NULL);
    priv->get_value_function = g_object_info_get_get_value_function_pointer(info);
    g_assert(priv->get_value_function != NULL);
    JS_SetPrivate(prototype, priv);

    gjs_debug(GJS_DEBUG_GFUNDAMENTAL,
              "Defined class %s prototype is %p class %p in object %p constructor %s.%s.%s",
              constructor_name, prototype, JS_GetClass(prototype),
              in_object,
              constructor_info != NULL ? g_base_info_get_namespace(constructor_info) : "unknown",
              constructor_info != NULL ? g_base_info_get_name(g_base_info_get_container(constructor_info)) : "unknown",
              constructor_info != NULL ? g_base_info_get_name(constructor_info) : "unknown");

    if (g_object_info_get_n_fields(priv->info) > 0) {
        gjs_debug(GJS_DEBUG_GFUNDAMENTAL,
                  "Fundamental type '%s.%s' apparently has accessible fields. "
                  "Gjs has no support for this yet, ignoring these.",
                  g_base_info_get_namespace((GIBaseInfo *)priv->info),
                  g_base_info_get_name ((GIBaseInfo *)priv->info));
    }

    gjs_object_define_static_methods(context, constructor, gtype, info);

    value = OBJECT_TO_JSVAL(gjs_gtype_create_gtype_wrapper(context, gtype));
    JS_DefineProperty(context, constructor, "$gtype", value,
                      NULL, NULL, JSPROP_PERMANENT);

    if (constructor_p)
        *constructor_p = constructor;
    if (prototype_p)
        *prototype_p = prototype;

    return JS_TRUE;
}
Exemple #19
0
JSBool
gjs_define_error_class(JSContext    *context,
                       JSObject     *in_object,
                       GIEnumInfo   *info,
                       JSObject    **constructor_p,
                       JSObject    **prototype_p)
{
    const char *constructor_name;
    GIBoxedInfo *glib_error_info;
    JSObject *prototype, *parent_proto;
    JSObject *constructor;
    jsval value;
    Error *priv;

    /* See the comment in gjs_define_boxed_class() for an
     * explanation of how this all works; Error is pretty much the
     * same as Boxed (except that we inherit from GLib.Error).
     */

    constructor_name = g_base_info_get_name( (GIBaseInfo*) info);

    if (gjs_object_get_property(context, in_object, constructor_name, &value)) {
        JSObject *constructor;

        if (!JSVAL_IS_OBJECT(value)) {
            gjs_throw(context, "Existing property '%s' does not look like a constructor",
                         constructor_name);
            return JS_FALSE;
        }

        constructor = JSVAL_TO_OBJECT(value);

        gjs_object_get_property(context, constructor, "prototype", &value);
        if (!JSVAL_IS_OBJECT(value)) {
            gjs_throw(context, "error %s prototype property does not appear to exist or has wrong type", constructor_name);
            return JS_FALSE;
        } else {
            if (prototype_p)
                *prototype_p = JSVAL_TO_OBJECT(value);
            if (constructor_p)
                *constructor_p = constructor;

            return JS_TRUE;
        }
    }

    g_irepository_require(NULL, "GLib", "2.0", 0, NULL);
    glib_error_info = (GIBoxedInfo*) g_irepository_find_by_name(NULL, "GLib", "Error");
    parent_proto = gjs_lookup_boxed_prototype(context, glib_error_info);
    g_base_info_unref((GIBaseInfo*)glib_error_info);

    prototype = gjs_init_class_dynamic(context, in_object,
                                          parent_proto,
                                          g_base_info_get_namespace( (GIBaseInfo*) info),
                                          constructor_name,
                                          &gjs_error_class,
                                          gjs_error_constructor,
                                          /* number of constructor args (less can be passed) */
                                          1,
                                          /* props of prototype */
                                          &gjs_error_proto_props[0],
                                          /* funcs of prototype */
                                          &gjs_error_proto_funcs[0],
                                          /* props of constructor, MyConstructor.myprop */
                                          NULL,
                                          /* funcs of constructor, MyConstructor.myfunc() */
                                          &gjs_error_constructor_funcs[0]);
    if (prototype == NULL) {
        gjs_log_exception(context, NULL);
        gjs_fatal("Can't init class %s", constructor_name);
    }

    g_assert(gjs_object_has_property(context, in_object, constructor_name));

    GJS_INC_COUNTER(gerror);
    priv = g_slice_new0(Error);
    priv->info = info;
    g_base_info_ref( (GIBaseInfo*) priv->info);
    priv->domain = g_quark_from_string (g_enum_info_get_error_domain(priv->info));

    JS_SetPrivate(context, prototype, priv);

    gjs_debug(GJS_DEBUG_GBOXED, "Defined class %s prototype is %p class %p in object %p",
              constructor_name, prototype, JS_GET_CLASS(context, prototype), in_object);

    constructor = NULL;
    gjs_object_get_property(context, in_object, constructor_name, &value);
    if (!JSVAL_IS_VOID(value)) {
        if (!JSVAL_IS_OBJECT(value)) {
            gjs_throw(context, "Property '%s' does not look like a constructor",
                      constructor_name);
            return JS_FALSE;
        }
    }

    constructor = JSVAL_TO_OBJECT(value);

    gjs_define_enum_values(context, constructor, priv->info);

    if (constructor_p)
        *constructor_p = constructor;

    if (prototype_p)
        *prototype_p = prototype;

    return JS_TRUE;
}
Exemple #20
0
static gboolean
pygi_arg_callback_setup_from_info (PyGICallbackCache  *arg_cache,
                                   GITypeInfo         *type_info,
                                   GIArgInfo          *arg_info,   /* may be null */
                                   GITransfer          transfer,
                                   PyGIDirection       direction,
                                   GIInterfaceInfo    *iface_info,
                                   PyGICallableCache  *callable_cache)
{
    PyGIArgCache *cache = (PyGIArgCache *)arg_cache;
    gssize child_offset = 0;

    if (!pygi_arg_base_setup ((PyGIArgCache *)arg_cache,
                              type_info,
                              arg_info,
                              transfer,
                              direction)) {
        return FALSE;
    }

    if (callable_cache != NULL)
        child_offset = callable_cache->args_offset;

    ( (PyGIArgCache *)arg_cache)->destroy_notify = (GDestroyNotify)_callback_cache_free_func;

    arg_cache->user_data_index = g_arg_info_get_closure (arg_info);
    if (arg_cache->user_data_index != -1)
        arg_cache->user_data_index += child_offset;

    arg_cache->destroy_notify_index = g_arg_info_get_destroy (arg_info);
    if (arg_cache->destroy_notify_index != -1)
        arg_cache->destroy_notify_index += child_offset;

    if (arg_cache->user_data_index >= 0) {
        PyGIArgCache *user_data_arg_cache = pygi_arg_cache_alloc ();
        user_data_arg_cache->meta_type = PYGI_META_ARG_TYPE_CHILD_WITH_PYARG;
        user_data_arg_cache->direction = direction;
        user_data_arg_cache->has_default = TRUE; /* always allow user data with a NULL default. */
        _pygi_callable_cache_set_arg (callable_cache, arg_cache->user_data_index,
                                      user_data_arg_cache);
    }

    if (arg_cache->destroy_notify_index >= 0) {
        PyGIArgCache *destroy_arg_cache = pygi_arg_cache_alloc ();
        destroy_arg_cache->meta_type = PYGI_META_ARG_TYPE_CHILD;
        destroy_arg_cache->direction = direction;
        _pygi_callable_cache_set_arg (callable_cache, arg_cache->destroy_notify_index,
                                      destroy_arg_cache);
    }

    arg_cache->scope = g_arg_info_get_scope (arg_info);
    g_base_info_ref( (GIBaseInfo *)iface_info);
    arg_cache->interface_info = iface_info;

    if (direction & PYGI_DIRECTION_FROM_PYTHON) {
        cache->from_py_marshaller = _pygi_marshal_from_py_interface_callback;
        cache->from_py_cleanup = _pygi_marshal_cleanup_from_py_interface_callback;
    }

    if (direction & PYGI_DIRECTION_TO_PYTHON) {
        cache->to_py_marshaller = _pygi_marshal_to_py_interface_callback;
    }

    return TRUE;
}
PyObject *
_pygi_info_new (GIBaseInfo *info)
{
    GIInfoType info_type;
    PyTypeObject *type = NULL;
    PyGIBaseInfo *self;

    info_type = g_base_info_get_type (info);

    switch (info_type)
    {
        case GI_INFO_TYPE_INVALID:
            PyErr_SetString (PyExc_RuntimeError, "Invalid info type");
            return NULL;
        case GI_INFO_TYPE_FUNCTION:
            type = &PyGIFunctionInfo_Type;
            break;
        case GI_INFO_TYPE_CALLBACK:
            type = &PyGICallbackInfo_Type;
            break;
        case GI_INFO_TYPE_STRUCT:
            type = &PyGIStructInfo_Type;
            break;
        case GI_INFO_TYPE_BOXED:
            type = &PyGIBoxedInfo_Type;
            break;
        case GI_INFO_TYPE_ENUM:
        case GI_INFO_TYPE_FLAGS:
            type = &PyGIEnumInfo_Type;
            break;
        case GI_INFO_TYPE_OBJECT:
            type = &PyGIObjectInfo_Type;
            break;
        case GI_INFO_TYPE_INTERFACE:
            type = &PyGIInterfaceInfo_Type;
            break;
        case GI_INFO_TYPE_CONSTANT:
            type = &PyGIConstantInfo_Type;
            break;
        case GI_INFO_TYPE_UNION:
            type = &PyGIUnionInfo_Type;
            break;
        case GI_INFO_TYPE_VALUE:
            type = &PyGIValueInfo_Type;
            break;
        case GI_INFO_TYPE_SIGNAL:
            type = &PyGISignalInfo_Type;
            break;
        case GI_INFO_TYPE_VFUNC:
            type = &PyGIVFuncInfo_Type;
            break;
        case GI_INFO_TYPE_PROPERTY:
            type = &PyGIPropertyInfo_Type;
            break;
        case GI_INFO_TYPE_FIELD:
            type = &PyGIFieldInfo_Type;
            break;
        case GI_INFO_TYPE_ARG:
            type = &PyGIArgInfo_Type;
            break;
        case GI_INFO_TYPE_TYPE:
            type = &PyGITypeInfo_Type;
            break;
        case GI_INFO_TYPE_UNRESOLVED:
            type = &PyGIUnresolvedInfo_Type;
            break;
        default:
            g_assert_not_reached();
            break;
    }

    self = (PyGIBaseInfo *) type->tp_alloc (type, 0);
    if (self == NULL) {
        return NULL;
    }

    self->info = g_base_info_ref (info);

    return (PyObject *) self;
}
Exemple #22
0
JSBool
gjs_define_interface_class(JSContext       *context,
                           JSObject        *in_object,
                           GIInterfaceInfo *info,
                           JSObject       **prototype_p)
{
    Interface *priv;
    const char *constructor_name;
    JSObject *constructor;
    JSObject *prototype;
    jsval value;

    constructor_name = g_base_info_get_name((GIBaseInfo*)info);

    gjs_object_get_property(context, in_object, constructor_name, &value);
    if (!JSVAL_IS_VOID(value)) {
        JSObject *constructor;

        if (!JSVAL_IS_OBJECT(value)) {
            gjs_throw(context, "Existing property '%s' does not look like a constructor",
                      constructor_name);
            return JS_FALSE;
        }

        constructor = JSVAL_TO_OBJECT(value);

        gjs_object_get_property(context, constructor, "prototype", &value);
        if (!JSVAL_IS_OBJECT(value)) {
            gjs_throw(context, "prototype property does not appear to exist or has wrong type");
            return JS_FALSE;
        } else {
            if (prototype_p)
                *prototype_p = JSVAL_TO_OBJECT(value);

            return JS_TRUE;
        }

        return JS_TRUE;
    }

    if (!gjs_init_class_dynamic(context, in_object,
                                NULL,
                                g_base_info_get_namespace((GIBaseInfo*)info),
                                constructor_name,
                                &gjs_interface_class,
                                gjs_interface_constructor, 0,
                                /* props of prototype */
                                &gjs_interface_proto_props[0],
                                /* funcs of prototype */
                                &gjs_interface_proto_funcs[0],
                                /* props of constructor, MyConstructor.myprop */
                                NULL,
                                /* funcs of constructor, MyConstructor.myfunc() */
                                NULL,
                                &prototype,
                                &constructor)) {
        gjs_fatal("Can't init class %s", constructor_name);
    }

    GJS_INC_COUNTER(interface);
    priv = g_slice_new0(Interface);
    priv->info = info;
    priv->gtype = g_registered_type_info_get_g_type(priv->info);
    g_base_info_ref((GIBaseInfo*)priv->info);
    JS_SetPrivate(context, prototype, priv);

    gjs_define_static_methods(context, constructor, priv->gtype, priv->info);

    value = OBJECT_TO_JSVAL(gjs_gtype_create_gtype_wrapper(context, priv->gtype));
    JS_DefineProperty(context, constructor, "$gtype", value,
                      NULL, NULL, JSPROP_PERMANENT);

    if (prototype_p)
        *prototype_p = prototype;

    return JS_TRUE;
}
Exemple #23
0
JSBool
gjs_define_boxed_class(JSContext    *context,
                          JSObject     *in_object,
                          GIBoxedInfo  *info,
                          JSObject    **constructor_p,
                          JSObject    **prototype_p)
{
    const char *constructor_name;
    JSObject *prototype;
    JSObject *constructor;
    jsval value;
    Boxed *priv;

    /* See the comment in gjs_define_object_class() for an
     * explanation of how this all works; Boxed is pretty much the
     * same as Object.
     */

    constructor_name = g_base_info_get_name( (GIBaseInfo*) info);

    if (gjs_object_get_property(context, in_object, constructor_name, &value)) {
        JSObject *constructor;

        if (!JSVAL_IS_OBJECT(value)) {
            gjs_throw(context, "Existing property '%s' does not look like a constructor",
                      constructor_name);
            return JS_FALSE;
        }

        constructor = JSVAL_TO_OBJECT(value);

        gjs_object_get_property(context, constructor, "prototype", &value);
        if (!JSVAL_IS_OBJECT(value)) {
            gjs_throw(context, "boxed %s prototype property does not appear to exist or has wrong type", constructor_name);
            return JS_FALSE;
        } else {
            if (prototype_p)
                *prototype_p = JSVAL_TO_OBJECT(value);
            if (constructor_p)
                *constructor_p = constructor;

            return JS_TRUE;
        }
    }

    if (!gjs_init_class_dynamic(context, in_object,
                                NULL, /* parent prototype */
                                g_base_info_get_namespace( (GIBaseInfo*) info),
                                constructor_name,
                                &gjs_boxed_class,
                                gjs_boxed_constructor, 1,
                                /* props of prototype */
                                &gjs_boxed_proto_props[0],
                                /* funcs of prototype */
                                &gjs_boxed_proto_funcs[0],
                                /* props of constructor, MyConstructor.myprop */
                                NULL,
                                /* funcs of constructor, MyConstructor.myfunc() */
                                NULL,
                                &prototype,
                                &constructor)) {
        gjs_log_exception(context, NULL);
        gjs_fatal("Can't init class %s", constructor_name);
    }

    GJS_INC_COUNTER(boxed);
    priv = g_slice_new0(Boxed);
    priv->info = info;
    boxed_fill_prototype_info(priv);

    g_base_info_ref( (GIBaseInfo*) priv->info);
    priv->gtype = g_registered_type_info_get_g_type ((GIRegisteredTypeInfo*) priv->info);
    JS_SetPrivate(context, prototype, priv);

    gjs_debug(GJS_DEBUG_GBOXED, "Defined class %s prototype is %p class %p in object %p",
              constructor_name, prototype, JS_GET_CLASS(context, prototype), in_object);

    priv->can_allocate_directly = struct_is_simple (priv->info);

    define_boxed_class_fields (context, priv, prototype);
    gjs_define_static_methods (context, constructor, priv->gtype, priv->info);

    value = OBJECT_TO_JSVAL(gjs_gtype_create_gtype_wrapper(context, priv->gtype));
    JS_DefineProperty(context, constructor, "$gtype", value,
                      NULL, NULL, JSPROP_PERMANENT);

    if (constructor_p)
        *constructor_p = constructor;

    if (prototype_p)
        *prototype_p = prototype;

    return JS_TRUE;
}