/** * _nm_dbus_signal_connect_data: * @proxy: a #GDBusProxy * @signal_name: the D-Bus signal to connect to * @signature: (allow-none): the signal's type signature (must be a tuple) * @c_handler: the signal handler function * @data: (allow-none): data to pass to @c_handler * @destroy_data: (allow-none): closure destroy notify for @data * @connect_flags: connection flags * * Connects to the D-Bus signal @signal_name on @proxy. @c_handler must be a * void function whose first argument is a #GDBusProxy, followed by arguments * for each element of @signature, ending with a #gpointer argument for @data. * * The argument types in @c_handler correspond to the types output by * g_dbus_gvariant_to_gvalue(), except for 'ay' and 'aay'. In particular: * - both 16-bit and 32-bit integers are passed as #gint/#guint * - 'as' values are passed as #GStrv (char **) * - all other array, tuple, and dict types are passed as #GVariant * * If @signature is %NULL, then the signal's parameters will be ignored, and * @c_handler should take only the #GDBusProxy and #gpointer arguments. * * Returns: the signal handler ID, which can be used with * g_signal_handler_remove(). Beware that because of the way the signal is * connected, you will not be able to remove it with * g_signal_handlers_disconnect_by_func(), although * g_signal_handlers_disconnect_by_data() will work correctly. */ gulong _nm_dbus_signal_connect_data (GDBusProxy *proxy, const char *signal_name, const GVariantType *signature, GCallback c_handler, gpointer data, GClosureNotify destroy_data, GConnectFlags connect_flags) { NMDBusSignalData *sd; GClosure *closure; gboolean swapped = !!(connect_flags & G_CONNECT_SWAPPED); gboolean after = !!(connect_flags & G_CONNECT_AFTER); g_return_val_if_fail (G_IS_DBUS_PROXY (proxy), 0); g_return_val_if_fail (signal_name != NULL, 0); g_return_val_if_fail (signature == NULL || g_variant_type_is_tuple (signature), 0); g_return_val_if_fail (c_handler != NULL, 0); sd = g_slice_new (NMDBusSignalData); sd->signal_name = g_strdup (signal_name); sd->signature = signature; closure = (swapped ? g_cclosure_new_swap : g_cclosure_new) (c_handler, data, destroy_data); g_closure_set_marshal (closure, g_cclosure_marshal_generic); g_closure_set_meta_marshal (closure, sd, dbus_signal_meta_marshal); g_closure_add_finalize_notifier (closure, sd, dbus_signal_data_free); return g_signal_connect_closure (proxy, "g-signal", closure, after); }
static inline GClosure *createCppClosure(ClosureDataBase *closureData) { GClosure *closure = g_closure_new_simple(sizeof(GClosure), closureData); g_closure_set_marshal(closure, &c_marshaller); g_closure_add_finalize_notifier(closure, NULL, &closureDestroyNotify); g_closure_ref(closure); g_closure_sink(closure); return closure; }
/* Creates a new closure which invokes callback_func with user_data as the last parameter. 创建GCClosure, 并初始化 但仍返回GClosure */ GClosure* g_cclosure_new (GCallback callback_func, gpointer user_data, GClosureNotify destroy_data) { closure = g_closure_new_simple (sizeof (GCClosure), user_data); g_closure_add_finalize_notifier (closure, user_data, destroy_data); ((GCClosure*) closure)->callback = (gpointer) callback_func; }
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; }
/** * g_cclosure_new: (skip) * @callback_func: the function to invoke * @user_data: user data to pass to @callback_func * @destroy_data: destroy notify to be called when @user_data is no longer used * * Creates a new closure which invokes @callback_func with @user_data as * the last parameter. * * Returns: a new #GCClosure */ GClosure* g_cclosure_new (GCallback callback_func, gpointer user_data, GClosureNotify destroy_data) { GClosure *closure; g_return_val_if_fail (callback_func != NULL, NULL); closure = g_closure_new_simple (sizeof (GCClosure), user_data); if (destroy_data) g_closure_add_finalize_notifier (closure, user_data, destroy_data); ((GCClosure*) closure)->callback = (gpointer) callback_func; return closure; }
static inline GClosure* mgtk_closure_new(gpointer callback_id) { GClosure *closure; /* printf("register id = %i\n",(int) callback_id); */ closure = g_closure_new_simple(sizeof(GClosure), callback_id); g_closure_set_marshal (closure, mgtk_callback_dispatch); g_closure_add_finalize_notifier (closure, callback_id, mgtk_callback_destroy); return closure; }
/** * Create one of our custom GClosure subclasses. To save us having to export * it, however, we just return the GClosure* that it extends. */ GClosure* bindings_java_closure_new ( JNIEnv* env, jobject handler, jclass receiver, const gchar* name, guint id ) { GClosure* closure; BindingsJavaClosure* bjc; GSignalQuery info; GString* buf; guint i; gchar* methodName; gchar* methodSignature; /* * First we allocate the closure and do the footwork to tell it what * its marshaller is */ closure = g_closure_new_simple(sizeof(BindingsJavaClosure), NULL); g_closure_add_finalize_notifier(closure, NULL, bindings_java_closure_destroy); g_closure_set_marshal(closure, bindings_java_marshaller); bjc = (BindingsJavaClosure*) closure; /* * And now we begin the legwork of figuring out what the methodID of * the callback to be invoked is and caching that in the closure. We * get the GSignalQuery data for the specified signal and then use that * to formulate a string that can be use to lookup the method. */ g_signal_query(id, &info); switch(G_TYPE_FUNDAMENTAL(info.return_type)) { case G_TYPE_BOOLEAN: bjc->returnType = 'Z'; break; case G_TYPE_INT: bjc->returnType = 'I'; break; case G_TYPE_ENUM: bjc->returnType = 'E'; break; case G_TYPE_STRING: /* * Strings are encoded as java.lang.String objects in signatures, * so we use the object type marker for gchar* (only). */ bjc->returnType = 'L'; break; case G_TYPE_NONE: bjc->returnType = 'V'; break; default: g_critical("Don't know what to do with signal return type %s", g_type_name(info.return_type)); return NULL; } /* * the name of the methods we invoke is algorithmic: "receiveName", * where Name is a PascalCase version of the signal name we were * passed in. */ buf = g_string_new("receive"); gchar** tokens = g_strsplit_set(name, "_-:", -1); for (i = 0; i < g_strv_length(tokens); i++) { gchar* token = tokens[i]; if (token[0] == '\0') { // skip past :: which splits signal name from "detail" continue; } gchar first = g_unichar_toupper(token[0]); g_string_append_c(buf, first); token++; g_string_append(buf, token); } methodName = buf->str; g_string_free(buf, FALSE); g_strfreev(tokens); /* * And here is the tricky bit: formulate the method signature that goes * along with this signal. A method of the signature * * boolean method(int, long, String) * * has a JNI encoding of * * (IJLjava/util/String;)Z */ buf = g_string_new("(Lorg/gnome/glib/Signal;J"); // add the signature for each parameter type for(i = 0; i < info.n_params; i++) { g_string_append(buf, bindings_java_typeToSignature(info.param_types[i])); } // and the return type g_string_append(buf, ")"); g_string_append(buf, bindings_java_typeToSignature(info.return_type)); methodSignature = buf->str; g_string_free(buf, FALSE); /* * Now at last we can lookup the method ID */ // jclass CANDIDATE = (*env)->FindClass(env, "org/gnome/gtk/GtkWidget"); // if ((*env)->IsSameObject(env, CANDIDATE, receiver)) { // g_debug("Received a GtkWidget"); // } bjc->receiver = receiver; bjc->method = (*env)->GetStaticMethodID(env, bjc->receiver, methodName, methodSignature); // g_debug("Looking for\nJava method %s\nwith signature %s\nin class %s\nto handle signal %s\n", // methodName, methodSignature, "FIXME", g_signal_name(id)); // clean up g_free(methodName); g_free(methodSignature); // and check for error if (bjc->method == NULL) { // Exception already thrown by GetMethodID return NULL; } /* * Set the reference so that the marshaller can find the Signal instance. */ bjc->handler = (*env)->NewWeakGlobalRef(env, handler); /* * And we're done! */ return closure; }
EditorClientFrameDestructionObserver(Frame* frame, GClosure* closure) : FrameDestructionObserver(frame) , m_closure(closure) { g_closure_add_finalize_notifier(m_closure, this, destroyOnClosureFinalization); }