seed r117 - trunk/libseed



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]