GClosure* gjs_closure_new(JSContext *context, JSObject *callable, const char *description, gboolean root_function) { Closure *c; c = (Closure*) g_closure_new_simple(sizeof(Closure), NULL); c->runtime = JS_GetRuntime(context); /* The saved context is used for lifetime management, so that the closure will * be torn down with the context that created it. The context could be attached to * the default context of the runtime using if we wanted the closure to survive * the context that created it. */ c->context = context; JS_BeginRequest(context); c->obj = callable; c->unref_on_global_object_finalized = FALSE; GJS_INC_COUNTER(closure); /* the finalize notifier right now is purely to track the counter * of how many closures are alive. */ g_closure_add_finalize_notifier(&c->base, NULL, closure_finalized); if (root_function) { /* Fully manage closure lifetime if so asked */ gjs_keep_alive_add_global_child(context, global_context_finalized, c->obj, c); g_closure_add_invalidate_notifier(&c->base, NULL, closure_invalidated); } else { /* Only mark the closure as invalid if memory is managed outside (i.e. by object.c for signals) */ g_closure_add_invalidate_notifier(&c->base, NULL, closure_set_invalid); } gjs_debug_closure("Create closure %p which calls object %p '%s'", c, c->obj, description); JS_EndRequest(context); return &c->base; }
/** * pyg_closure_new: * callback: a Python callable object * extra_args: a tuple of extra arguments, or None/NULL. * swap_data: an alternative python object to pass first. * * Creates a GClosure wrapping a Python callable and optionally a set * of additional function arguments. This is needed to attach python * handlers to signals, for instance. * * Returns: the new closure. */ GClosure * pyg_closure_new(PyObject *callback, PyObject *extra_args, PyObject *swap_data) { GClosure *closure; g_return_val_if_fail(callback != NULL, NULL); closure = g_closure_new_simple(sizeof(PyGClosure), NULL); g_closure_add_invalidate_notifier(closure, NULL, pyg_closure_invalidate); g_closure_set_marshal(closure, pyg_closure_marshal); Py_INCREF(callback); ((PyGClosure *)closure)->callback = callback; if (extra_args && extra_args != Py_None) { Py_INCREF(extra_args); if (!PyTuple_Check(extra_args)) { PyObject *tmp = PyTuple_New(1); PyTuple_SetItem(tmp, 0, extra_args); extra_args = tmp; } ((PyGClosure *)closure)->extra_args = extra_args; } if (swap_data) { Py_INCREF(swap_data); ((PyGClosure *)closure)->swap_data = swap_data; closure->derivative_flag = TRUE; } return closure; }
static void g_object_connect_property (GObject *object, GParamSpec *spec, GCallback func, gpointer data, GObject *alive_object) { GClosure *closure; gchar *with_detail; DisconnectData *dd; if (is_child_property (spec)) with_detail = g_strconcat ("child-notify::", spec->name, NULL); else with_detail = g_strconcat ("notify::", spec->name, NULL); dd = g_new (DisconnectData, 1); closure = g_cclosure_new (func, data, NULL); g_closure_add_invalidate_notifier (closure, dd, signal_removed); dd->id = g_signal_connect_closure (object, with_detail, closure, FALSE); dd->instance = object; dd->alive_object = alive_object; g_object_set_data_full (G_OBJECT (alive_object), "alive-object-data", dd, disconnect_func); g_free (with_detail); }
GClosure * gtk2hs_closure_new(HsStablePtr callback) { GClosure *closure; WHEN_DEBUG(g_debug("gtk2hs_closure_new: enter, callback=%p", callback)); closure = g_closure_new_simple(sizeof(Gtk2HsClosure), NULL); /* TODO: check if we should be using invalidate or finalise notifier */ g_closure_add_invalidate_notifier(closure, NULL, gtk2hs_closure_invalidate); g_closure_set_marshal(closure, gtk2hs_closure_marshal); ((Gtk2HsClosure *)closure)->callback = callback; WHEN_DEBUG(g_debug("gtk2hs_closure_new: leave")); return closure; }
GClosure * pygi_signal_closure_new (PyGObject *instance, GType g_type, const gchar *signal_name, PyObject *callback, PyObject *extra_args, PyObject *swap_data) { GClosure *closure = NULL; PyGISignalClosure *pygi_closure = NULL; GISignalInfo *signal_info = NULL; g_return_val_if_fail(callback != NULL, NULL); signal_info = _pygi_lookup_signal_from_g_type (g_type, signal_name); if (signal_info == NULL) return NULL; closure = g_closure_new_simple(sizeof(PyGISignalClosure), NULL); g_closure_add_invalidate_notifier(closure, NULL, pygi_signal_closure_invalidate); g_closure_set_marshal(closure, pygi_signal_closure_marshal); pygi_closure = (PyGISignalClosure *)closure; pygi_closure->signal_info = signal_info; Py_INCREF(callback); pygi_closure->pyg_closure.callback = callback; if (extra_args != NULL && extra_args != Py_None) { Py_INCREF(extra_args); if (!PyTuple_Check(extra_args)) { PyObject *tmp = PyTuple_New(1); PyTuple_SetItem(tmp, 0, extra_args); extra_args = tmp; } pygi_closure->pyg_closure.extra_args = extra_args; } if (swap_data) { Py_INCREF(swap_data); pygi_closure->pyg_closure.swap_data = swap_data; closure->derivative_flag = TRUE; } return closure; }
static JSBool gjs_timeout_add(JSContext *context, JSObject *obj, uintN argc, jsval *argv, jsval *retval) { GClosure *closure; JSObject *callback; guint32 interval; guint id; /* Best I can tell, there is no way to know if argv[1] is really * callable other than to just try it. Checking whether it's a * function will not detect native objects that provide * JSClass::call, for example. */ if (!gjs_parse_args(context, "timeout_add", "uo", argc, argv, "interval", &interval, "callback", &callback)) return JS_FALSE; closure = gjs_closure_new(context, callback, "timeout"); if (closure == NULL) return JS_FALSE; g_closure_ref(closure); g_closure_sink(closure); id = g_timeout_add_full(G_PRIORITY_DEFAULT, interval, closure_source_func, closure, closure_destroy_notify); /* this is needed to remove the timeout if the JSContext is * destroyed. */ g_closure_add_invalidate_notifier(closure, GUINT_TO_POINTER(id), closure_invalidated); if (!JS_NewNumberValue(context, id, retval)) return JS_FALSE; return JS_TRUE; }
/* This is workaround for missing glib function, which should look like this: void g_closure_set_marshal_with_data (GClosure *closure, GClosureMarshal marshal, gpointer user_data, GDestroyNotify destroy_notify); Such method would be introspectable. */ static int marshal_closure_set_marshal (lua_State *L) { GClosure *closure; gpointer user_data; GClosureMarshal marshal; GIBaseInfo *ci; ci = g_irepository_find_by_name (NULL, "GObject", "ClosureMarshal"); lgi_type_get_repotype (L, G_TYPE_CLOSURE, NULL); lgi_record_2c (L, 1, &closure, FALSE, FALSE, FALSE, FALSE); user_data = lgi_closure_allocate (L, 1); lgi_callable_create (L, ci, NULL); marshal = lgi_closure_create (L, user_data, 2, FALSE); g_closure_set_marshal (closure, marshal); g_closure_add_invalidate_notifier (closure, user_data, gclosure_destroy); return 0; }
/** * g_source_set_closure: * @source: the source * @closure: a #GClosure * * Set the callback for a source as a #GClosure. * * If the source is not one of the standard GLib types, the @closure_callback * and @closure_marshal fields of the #GSourceFuncs structure must have been * filled in with pointers to appropriate functions. */ void g_source_set_closure (GSource *source, GClosure *closure) { g_return_if_fail (source != NULL); g_return_if_fail (closure != NULL); if (!source->source_funcs->closure_callback && #ifdef G_OS_UNIX source->source_funcs != &g_unix_fd_source_funcs && source->source_funcs != &g_unix_signal_funcs && #endif source->source_funcs != &g_child_watch_funcs && source->source_funcs != &g_io_watch_funcs && source->source_funcs != &g_timeout_funcs && source->source_funcs != &g_idle_funcs) { g_critical (G_STRLOC ": closure cannot be set on GSource without GSourceFuncs::closure_callback\n"); return; } g_closure_ref (closure); g_closure_sink (closure); g_source_set_callback_indirect (source, closure, &closure_callback_funcs); g_closure_add_invalidate_notifier (closure, source, closure_invalidated); if (G_CLOSURE_NEEDS_MARSHAL (closure)) { GClosureMarshal marshal = (GClosureMarshal)source->source_funcs->closure_marshal; if (marshal) g_closure_set_marshal (closure, marshal); else if (source->source_funcs == &g_idle_funcs || #ifdef G_OS_UNIX source->source_funcs == &g_unix_signal_funcs || #endif source->source_funcs == &g_timeout_funcs) g_closure_set_marshal (closure, source_closure_marshal_BOOLEAN__VOID); else g_closure_set_marshal (closure, g_cclosure_marshal_generic); } }
static JSBool gjs_timeout_add_seconds(JSContext *context, JSObject *obj, uintN argc, jsval *argv, jsval *retval) { GClosure *closure; JSObject *callback; guint32 interval; guint id; /* See comment for timeout_add above */ if (!gjs_parse_args(context, "timeout_add_seconds", "uo", argc, argv, "interval", &interval, "callback", &callback)) return JS_FALSE; closure = gjs_closure_new(context, callback, "timeout_seconds"); if (closure == NULL) return JS_FALSE; g_closure_ref(closure); g_closure_sink(closure); id = g_timeout_add_seconds_full(G_PRIORITY_DEFAULT, interval, closure_source_func, closure, closure_destroy_notify); /* this is needed to remove the timeout if the JSContext is * destroyed. */ g_closure_add_invalidate_notifier(closure, GUINT_TO_POINTER(id), closure_invalidated); if (!JS_NewNumberValue(context, id, retval)) return JS_FALSE; return JS_TRUE; }
GClosure* g_rclosure_new(VALUE callback_proc, VALUE extra_args, GValToRValSignalFunc g2r_func) { GRClosure* closure; closure = (GRClosure*)g_closure_new_simple(sizeof(GRClosure), NULL); closure->count = 1; closure->g2r_func = g2r_func; closure->objects = NULL; closure->callback = callback_proc; closure->extra_args = extra_args; closure->rb_holder = Data_Wrap_Struct(rb_cData, gr_closure_holder_mark, gr_closure_holder_free, closure); closure->tag[0] = '\0'; g_closure_set_marshal((GClosure*)closure, &rclosure_marshal); g_closure_add_invalidate_notifier((GClosure*)closure, NULL, &rclosure_invalidate); return (GClosure*)closure; }