seed r117 - trunk/libseed
- From: racarr svn gnome org
- To: svn-commits-list gnome org
- Subject: seed r117 - trunk/libseed
- Date: Wed, 5 Nov 2008 10:02:24 +0000 (UTC)
Author: racarr
Date: Wed Nov 5 10:02:24 2008
New Revision: 117
URL: http://svn.gnome.org/viewvc/seed?rev=117&view=rev
Log:
Add Seed.closure_native. Takes as it's first argument a Javascript
function, and as it's second argument, a type signature (i.e.
Gtk.Callback), and constructs a boxed C function pointer that when
called invokes, a handler, which performs type conversion and invokes
the javascrpit function. Useful for things like pago_fontset_foreach,
etc...
Modified:
trunk/libseed/seed-builtins.c
trunk/libseed/seed-private.h
trunk/libseed/seed-types.c
Modified: trunk/libseed/seed-builtins.c
==============================================================================
--- trunk/libseed/seed-builtins.c (original)
+++ trunk/libseed/seed-builtins.c Wed Nov 5 10:02:24 2008
@@ -21,6 +21,7 @@
#include <readline/readline.h>
#include <readline/history.h>
#include <string.h>
+#include <sys/mman.h>
JSValueRef
seed_include(JSContextRef ctx,
@@ -336,6 +337,269 @@
return (JSValueRef)seed_make_struct(closure, 0);
}
+static ffi_type *
+get_ffi_type (GITypeInfo *info)
+{
+ ffi_type *rettype;
+
+ if (g_type_info_is_pointer (info))
+ rettype = &ffi_type_pointer;
+ else
+ switch (g_type_info_get_tag (info))
+ {
+ case GI_TYPE_TAG_VOID:
+ rettype = &ffi_type_void;
+ break;
+ case GI_TYPE_TAG_BOOLEAN:
+ rettype = &ffi_type_uint;
+ break;
+ case GI_TYPE_TAG_INT8:
+ rettype = &ffi_type_sint8;
+ break;
+ case GI_TYPE_TAG_UINT8:
+ rettype = &ffi_type_uint8;
+ break;
+ case GI_TYPE_TAG_INT16:
+ rettype = &ffi_type_sint16;
+ break;
+ case GI_TYPE_TAG_UINT16:
+ rettype = &ffi_type_uint16;
+ break;
+ case GI_TYPE_TAG_INT32:
+ rettype = &ffi_type_sint32;
+ break;
+ case GI_TYPE_TAG_UINT32:
+ rettype = &ffi_type_uint32;
+ break;
+ case GI_TYPE_TAG_INT64:
+ rettype = &ffi_type_sint64;
+ break;
+ case GI_TYPE_TAG_UINT64:
+ rettype = &ffi_type_uint64;
+ break;
+ case GI_TYPE_TAG_INT:
+ rettype = &ffi_type_sint;
+ break;
+ case GI_TYPE_TAG_UINT:
+ rettype = &ffi_type_uint;
+ break;
+ case GI_TYPE_TAG_SSIZE: /* FIXME */
+ case GI_TYPE_TAG_LONG:
+ rettype = &ffi_type_slong;
+ break;
+ case GI_TYPE_TAG_SIZE: /* FIXME */
+ case GI_TYPE_TAG_TIME_T: /* May not be portable */
+ case GI_TYPE_TAG_ULONG:
+ rettype = &ffi_type_ulong;
+ break;
+ case GI_TYPE_TAG_FLOAT:
+ rettype = &ffi_type_float;
+ break;
+ case GI_TYPE_TAG_DOUBLE:
+ rettype = &ffi_type_double;
+ break;
+ case GI_TYPE_TAG_UTF8:
+ case GI_TYPE_TAG_FILENAME:
+ case GI_TYPE_TAG_ARRAY:
+ case GI_TYPE_TAG_INTERFACE:
+ case GI_TYPE_TAG_GLIST:
+ case GI_TYPE_TAG_GSLIST:
+ case GI_TYPE_TAG_GHASH:
+ case GI_TYPE_TAG_ERROR:
+ rettype = &ffi_type_pointer;
+ break;
+ default:
+ g_assert_not_reached ();
+ }
+
+ return rettype;
+}
+
+typedef struct _SeedClosurePrivates
+{
+ GICallableInfo * info;
+ JSValueRef function;
+} SeedClosurePrivates;
+
+static void
+seed_handle_closure(ffi_cif *cif,
+ void * result,
+ void ** args,
+ void * userdata)
+{
+ SeedClosurePrivates * privates = userdata;
+ int num_args, i;
+ JSValueRef * jsargs;
+ JSValueRef * return_value;
+ GIArgInfo * arg_info;
+ GITypeInfo * return_type;
+ GArgument rarg;
+
+ num_args = g_callable_info_get_n_args(privates->info);
+ jsargs = (JSValueRef *)g_new0(JSValueRef, num_args);
+
+ for (i = 0; i < num_args; i++)
+ {
+ GITypeInfo * arg_type;
+ GITypeTag tag;
+ GType type;
+ GArgument * arg = &rarg;
+
+ arg_info = g_callable_info_get_arg(privates->info, i);
+ arg_type = g_arg_info_get_type(arg_info);
+ tag = g_type_info_get_tag(arg_type);
+
+ switch(tag)
+ {
+ case GI_TYPE_TAG_BOOLEAN:
+ arg->v_boolean = *(gboolean*)args[i];
+ break;
+ case GI_TYPE_TAG_INT8:
+ arg->v_int8 = *(gint8*)args[i];
+ break;
+ case GI_TYPE_TAG_UINT8:
+ arg->v_uint8 = *(guint8*)args[i];
+ break;
+ case GI_TYPE_TAG_INT16:
+ arg->v_int16 = *(gint16*)args[i];
+ break;
+ case GI_TYPE_TAG_UINT16:
+ arg->v_uint16 = *(guint16*)args[i];
+ break;
+ case GI_TYPE_TAG_INT32:
+ arg->v_int32 = *(gint32*)args[i];
+ break;
+ case GI_TYPE_TAG_UINT32:
+ arg->v_uint32 = *(guint32*)args[i];
+ break;
+ case GI_TYPE_TAG_LONG:
+ case GI_TYPE_TAG_INT64:
+ arg->v_int64 = *(glong*)args[i];
+ break;
+ case GI_TYPE_TAG_ULONG:
+ case GI_TYPE_TAG_UINT64:
+ arg->v_uint64 = *(glong*)args[i];
+ break;
+ case GI_TYPE_TAG_INT:
+ case GI_TYPE_TAG_SSIZE:
+ case GI_TYPE_TAG_SIZE:
+ arg->v_int32 = *(gint*)args[i];
+ break;
+ case GI_TYPE_TAG_UINT:
+ arg->v_uint32 = *(guint*)args[i];
+ break;
+ case GI_TYPE_TAG_FLOAT:
+ arg->v_float = *(gfloat*)args[i];
+ break;
+ case GI_TYPE_TAG_DOUBLE:
+ arg->v_double = *(gdouble*)args[i];
+ break;
+ case GI_TYPE_TAG_UTF8:
+ arg->v_string = (gchar *)args[i];
+ break;
+ case GI_TYPE_TAG_INTERFACE:
+ {
+ GIBaseInfo *interface;
+ GIInfoType interface_type;
+
+ interface = g_type_info_get_interface(arg_type);
+ interface_type = g_base_info_get_type(interface);
+
+ if (interface_type == GI_INFO_TYPE_OBJECT ||
+ interface_type == GI_INFO_TYPE_INTERFACE) {
+ arg->v_pointer = *(gpointer*)args[i];
+ break;
+ }
+
+ else if (interface_type == GI_INFO_TYPE_ENUM ||
+ interface_type == GI_INFO_TYPE_FLAGS) {
+ arg->v_double = *(double*)args[i];
+ break;
+ } else if (interface_type == GI_INFO_TYPE_STRUCT) {
+ arg->v_pointer = *(gpointer*)args[i];
+ break;
+ }
+ }
+ case GI_TYPE_TAG_GLIST:
+ case GI_TYPE_TAG_GSLIST:
+ arg->v_pointer = *(gpointer*)args[i];
+ break;
+ default:
+ arg->v_pointer = 0;
+ }
+ jsargs[i] = seed_gi_argument_make_js(arg, arg_type, 0);
+ }
+
+ JSObjectCallAsFunction(eng->context, (JSObjectRef)privates->function,
+ 0, num_args, jsargs, 0);
+}
+
+JSValueRef
+seed_closure_native(JSContextRef ctx,
+ JSObjectRef function,
+ JSObjectRef this_object,
+ size_t argumentCount,
+ const JSValueRef arguments[], JSValueRef * exception)
+{
+ ffi_cif * cif;
+ ffi_closure *closure;
+ ffi_type ** arg_types;
+ ffi_arg result;
+ ffi_status status;
+ GICallableInfo * info;
+ GITypeInfo * return_type;
+ GIArgInfo * arg_info;
+ gint num_args, i;
+ SeedClosurePrivates * privates;
+
+ if (argumentCount != 2)
+ {
+ gchar * mes = g_strdup_printf("Seed.closure_native expected"
+ " 2 arguments, got %d",
+ argumentCount);
+
+ seed_make_exception(exception, "ArgumentError", mes);
+ g_free(mes);
+
+ return JSValueMakeNull(eng->context);
+ }
+
+ info = (GICallableInfo *)
+ JSObjectGetPrivate((JSObjectRef)arguments[1]);
+
+ num_args = g_callable_info_get_n_args(info);
+ return_type = g_callable_info_get_return_type(info);
+ arg_types = (ffi_type **)g_new0(ffi_type, num_args+1);
+ cif = g_new0(ffi_cif, 1);
+
+ privates = g_new0(SeedClosurePrivates, 1);
+ privates->info = info;
+ privates->function = arguments[0];
+ //Leaks the function? Would need a new class for closures and finalize
+ //handler.
+ JSValueProtect(eng->context, privates->function);
+
+ for (i = 0; i < num_args; i++)
+ {
+ arg_info = g_callable_info_get_arg(info, i);
+ arg_types[i] = get_ffi_type(g_arg_info_get_type(arg_info));
+ }
+ arg_types[num_args] = 0;
+
+
+ closure = mmap(0, sizeof(ffi_closure), PROT_READ | PROT_WRITE |
+ PROT_EXEC,
+ MAP_ANON | MAP_PRIVATE, -1, 0);
+
+ ffi_prep_cif(cif, FFI_DEFAULT_ABI, 2,
+ &ffi_type_void, arg_types);
+ ffi_prep_closure(closure, cif, seed_handle_closure, privates);
+
+
+ return seed_make_struct(closure, 0);
+}
+
+
void seed_init_builtins(int *argc, char ***argv)
{
int i;
@@ -353,6 +617,9 @@
seed_create_function("fork", &seed_fork, obj);
seed_create_function("closure", &seed_closure, obj);
seed_create_function("setTimeout", &seed_set_timeout, obj);
+ seed_create_function("closure_native", &seed_closure_native, obj);
+
+
arrayObj = JSObjectMake(eng->context, NULL, NULL);
Modified: trunk/libseed/seed-private.h
==============================================================================
--- trunk/libseed/seed-private.h (original)
+++ trunk/libseed/seed-private.h Wed Nov 5 10:02:24 2008
@@ -26,6 +26,7 @@
#include <stdlib.h>
#include <stdio.h>
#include <girepository.h>
+#include <ffi.h>
typedef struct _SeedEngine SeedEngine;
typedef JSValueRef SeedValue;
@@ -41,4 +42,5 @@
#include "seed-builtins.h"
#include "seed-structs.h"
+
#endif
Modified: trunk/libseed/seed-types.c
==============================================================================
--- trunk/libseed/seed-types.c (original)
+++ trunk/libseed/seed-types.c Wed Nov 5 10:02:24 2008
@@ -261,20 +261,29 @@
arg->v_pointer = seed_struct_get_pointer(value);
break;
} else if (interface_type == GI_INFO_TYPE_CALLBACK) {
- GIFunctionInfo *info =
- JSObjectGetPrivate((JSObjectRef) value);
- const gchar *symbol =
- g_function_info_get_symbol(info);
- gchar *error;
- void *fp;
-
- dlerror();
- fp = (void *)dlsym(0, symbol);
- if ((error = dlerror()) != NULL) {
- g_critical("dlerror: %s \n", error);
- } else {
- arg->v_pointer = fp;
- break;
+ if (JSValueIsObjectOfClass(eng->context,
+ value, gobject_method_class))
+ {
+ GIFunctionInfo *info =
+ JSObjectGetPrivate((JSObjectRef) value);
+ const gchar *symbol =
+ g_function_info_get_symbol(info);
+ gchar *error;
+ void *fp;
+
+ dlerror();
+ fp = (void *)dlsym(0, symbol);
+ if ((error = dlerror()) != NULL) {
+ g_critical("dlerror: %s \n", error);
+ } else {
+ arg->v_pointer = fp;
+ break;
+ }
+ }
+ else
+ {
+ arg->v_pointer = seed_struct_get_pointer(value);
+ break;
}
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]