[seed: 7/7] [ffi] Calling functions works now...



commit 04adfffbe102296024ff2d1d8f5fb6f16d38860a
Author: Robert Carr <racarr gnome org>
Date:   Sat Aug 1 21:28:14 2009 -0400

    [ffi] Calling functions works now...

 modules/ffi/Makefile.am |    2 +-
 modules/ffi/seed-ffi.c  |  220 +++++++++++++++++++++++++++++++++++++++++++++-
 2 files changed, 216 insertions(+), 6 deletions(-)
---
diff --git a/modules/ffi/Makefile.am b/modules/ffi/Makefile.am
index c13f2ea..965e8ad 100644
--- a/modules/ffi/Makefile.am
+++ b/modules/ffi/Makefile.am
@@ -8,7 +8,7 @@ seedlib_LTLIBRARIES = \
 libseed_ffi_la_SOURCES = \
 	seed-ffi.c
 
-AM_CPPFLAGS = \
+libseed_ffi_la_CFLAGS = \
 	-I top_srcdir@/libseed/ \
 	$(GOBJECT_INTROSPECTION_CFLAGS) \
 	$(SEED_DEBUG_CFLAGS) \
diff --git a/modules/ffi/seed-ffi.c b/modules/ffi/seed-ffi.c
index 28d86b0..b9744d7 100644
--- a/modules/ffi/seed-ffi.c
+++ b/modules/ffi/seed-ffi.c
@@ -41,6 +41,135 @@ typedef struct _seed_ffi_function_priv {
   SeedObject module_obj;
 } seed_ffi_function_priv;
 
+static ffi_type *
+gtype_to_ffi_type (SeedContext ctx, 
+		   SeedValue value,
+		   GType otype,
+		   GArgument *garg,
+		   gpointer *arg,
+		   SeedException *exception)
+{
+  ffi_type *return_type;
+  GType type = g_type_fundamental (otype);
+  g_assert (type != G_TYPE_INVALID);
+
+  switch (type)
+    {
+    case G_TYPE_BOOLEAN:
+    case G_TYPE_CHAR:
+    case G_TYPE_INT:
+      return_type = &ffi_type_sint;
+      garg->v_int = seed_value_to_int (ctx, value, exception);
+      *arg = &(garg->v_int);
+      break;
+    case G_TYPE_UCHAR:
+    case G_TYPE_UINT:
+      return_type = &ffi_type_uint;
+      garg->v_uint = seed_value_to_uint (ctx, value, exception);
+      *arg = &(garg->v_uint);
+      break;
+    case G_TYPE_STRING:
+      return_type = &ffi_type_pointer;
+      garg->v_pointer = seed_value_to_string (ctx, value, exception);
+      *arg = &(garg->v_pointer);
+      break;
+    case G_TYPE_OBJECT:
+      //    case G_TYPE_BOXED:
+      //    case G_TYPE_POINTER:
+      return_type = &ffi_type_pointer;
+      garg->v_pointer = seed_value_to_object (ctx, value, exception);
+      *arg = &(garg->v_pointer);
+      break;
+    case G_TYPE_FLOAT:
+      return_type = &ffi_type_float;
+      garg->v_float = seed_value_to_float (ctx, value, exception);
+      *arg = &(garg->v_float);
+      break;
+    case G_TYPE_DOUBLE:
+      return_type = &ffi_type_double;
+      garg->v_double = seed_value_to_double (ctx, value, exception);
+      *arg = &(garg->v_double);
+      break;
+    case G_TYPE_LONG:
+      return_type = &ffi_type_slong;
+      garg->v_uint = seed_value_to_uint (ctx, value, exception);
+      *arg = &(garg->v_uint);
+      break;
+    case G_TYPE_ULONG:
+      return_type = &ffi_type_ulong;
+      garg->v_ulong = seed_value_to_ulong (ctx, value, exception);
+      *arg = &(garg->v_ulong);
+      break;
+    case G_TYPE_INT64:
+      return_type = &ffi_type_sint64;
+      garg->v_int64 = seed_value_to_int64 (ctx, value, exception);
+      *arg = &(garg->v_int64);
+      break;
+    case G_TYPE_UINT64:
+      return_type = &ffi_type_uint64;
+      garg->v_uint64 = seed_value_to_uint64 (ctx, value, exception);
+      *arg = &(garg->v_uint64);
+      break;
+    default:
+      g_warning ("Unsupported fundamental type: %s", g_type_name (type));
+      return_type = &ffi_type_pointer;
+      garg->v_pointer = NULL;
+      *arg = &(garg->v_pointer);
+      break;
+    }
+  return return_type;
+}
+
+static ffi_type *
+return_type_to_ffi_type (GType otype)
+{
+  GType type = g_type_fundamental (otype);
+  g_assert (type != G_TYPE_INVALID);
+
+  switch (type)
+    {
+    case G_TYPE_BOOLEAN:
+    case G_TYPE_CHAR:
+    case G_TYPE_INT:
+      return &ffi_type_sint;
+      break;
+    case G_TYPE_UCHAR:
+    case G_TYPE_UINT:
+      return &ffi_type_uint;
+      break;
+    case G_TYPE_STRING:
+      return &ffi_type_pointer;
+      break;
+    case G_TYPE_OBJECT:
+      //    case G_TYPE_BOXED:
+      //    case G_TYPE_POINTER:
+      return &ffi_type_pointer;
+      break;
+    case G_TYPE_FLOAT:
+      return &ffi_type_float;
+      break;
+    case G_TYPE_DOUBLE:
+      return &ffi_type_double;
+      break;
+    case G_TYPE_LONG:
+      return &ffi_type_slong;
+      break;
+    case G_TYPE_ULONG:
+      return &ffi_type_ulong;
+      break;
+    case G_TYPE_INT64:
+      return &ffi_type_sint64;
+      break;
+    case G_TYPE_UINT64:
+      return &ffi_type_uint64;
+      break;
+    default:
+      g_warning ("Unsupported fundamental type: %s", g_type_name (type));
+      return &ffi_type_pointer;
+      break;
+    }
+}
+
 static SeedValue
 seed_ffi_get_signature (SeedContext ctx,
 			  SeedObject this_object,
@@ -136,6 +265,8 @@ seed_ffi_function_finalize (SeedObject obj)
     }
   
   g_free (priv->name);
+  g_free (priv);
+
   seed_value_unprotect (eng->context, priv->module_obj);
 }
 
@@ -153,6 +284,62 @@ seed_ffi_make_function (SeedContext ctx, SeedObject module_obj, gpointer symbol,
 }
 
 static SeedValue
+value_from_ffi_type (SeedContext ctx, 
+		     GType otype,
+		     gpointer *value, 
+		     SeedException *exception)
+{
+  switch (g_type_fundamental (otype))
+    {
+    case G_TYPE_INT:
+      return seed_value_from_int (ctx, *(gint*)value, exception);
+      break;
+    case G_TYPE_FLOAT:
+      return seed_value_from_float (ctx, *(gfloat*)value, exception);
+      break;
+    case G_TYPE_DOUBLE:
+      return seed_value_from_double (ctx, *(gdouble*)value, exception);
+      break;
+    case G_TYPE_BOOLEAN:
+      return seed_value_from_boolean (ctx, *(gboolean*)value, exception);
+      break;
+    case G_TYPE_STRING:
+      return seed_value_from_string (ctx, *(gchar**)value, exception);
+      break;
+    case G_TYPE_CHAR:
+      return seed_value_from_char (ctx, *(gchar*)value, exception);
+      break;
+    case G_TYPE_UCHAR:
+      return seed_value_from_uchar (ctx, *(guchar*)value, exception);
+      break;
+    case G_TYPE_UINT:
+      return seed_value_from_uint (ctx, *(guint*)value, exception);
+      break;
+      //    case G_TYPE_POINTER:
+      //      return seed_ (ctx, *(gpointer*)value, exception);
+      //      break;
+    case G_TYPE_LONG:
+      return seed_value_from_long (ctx, *(glong*)value, exception);
+      break;
+    case G_TYPE_ULONG:
+      return seed_value_from_ulong (ctx, *(gulong*)value, exception);
+      break;
+    case G_TYPE_INT64:
+      return seed_value_from_int64 (ctx, *(gint64*)value, exception);
+      break;
+    case G_TYPE_UINT64:
+      return seed_value_from_uint64 (ctx, *(guint64*)value, exception);
+      break;
+    case G_TYPE_NONE:
+      return seed_make_null (ctx);
+    default:
+      g_warning ("Unsupported fundamental type: %s",
+		 g_type_name(g_type_fundamental (otype)));
+      return seed_make_null (ctx);
+    }
+}
+
+static SeedValue
 seed_ffi_function_call (SeedContext ctx,
 			SeedObject function,
 			SeedObject this_object,
@@ -160,15 +347,15 @@ seed_ffi_function_call (SeedContext ctx,
 			const SeedValue arguments[],
 			SeedException *exception)
 {
+  GArgument *gargs;
   ffi_type *rtype;
   void *rvalue;
-  int n_args;
   ffi_type **atypes;
   void **args;
   int i;
   ffi_cif cif;
 
-  seed_ffi_function_priv *priv = seed_object_get_private (this_object);
+  seed_ffi_function_priv *priv = seed_object_get_private (function);
   
   if (argument_count != priv->n_args)
     {
@@ -176,6 +363,23 @@ seed_ffi_function_call (SeedContext ctx,
 			   priv->name, priv->n_args, argument_count);
       return seed_make_null (ctx);
     }
+  atypes = g_alloca (sizeof (ffi_type *) * (argument_count+1));
+  args = g_alloca (sizeof (gpointer) * (argument_count+1));
+  gargs = g_alloca (sizeof (GArgument) * (argument_count+1));
+
+  for (i = 0; i < argument_count; i++)
+    {
+      atypes[i] = gtype_to_ffi_type (ctx, arguments[i], priv->args[i], &gargs[i], args[i],exception);
+    }
+  rtype = return_type_to_ffi_type (priv->ret_val);
+		   
+  ffi_prep_cif (&cif, FFI_DEFAULT_ABI, argument_count, rtype, atypes);
+  
+  rvalue = g_alloca (MAX (rtype->size, sizeof (ffi_arg)));
+  
+  ffi_call (&cif, priv->symbol, rvalue, args);
+  
+  return value_from_ffi_type (ctx, priv->ret_val, rvalue, exception);
 }
 
 static SeedValue
@@ -213,15 +417,18 @@ seed_ffi_construct_library (SeedContext ctx,
   SeedObject ret;
   gchar *filename;
   
-  if (argument_count != 1)
+  if (argument_count != 1 && argument_count != 0)
     {
       seed_make_exception (ctx, exception, 
 			   "ArgumentError", 
-			   "ffi.Library constructor expects 1 argument (filename), got %d", 
+			   "ffi.Library constructor expects 1 argument (filename, or none to use NULL GModule), got %d", 
 			   argument_count);
       return seed_make_null (ctx);
     }
-  filename = seed_value_to_string (ctx, arguments[0], exception);
+  if (argument_count == 1)
+    filename = seed_value_to_string (ctx, arguments[0], exception);
+  else
+    filename = NULL;
   
   mod = g_module_open (filename, G_MODULE_BIND_LOCAL | G_MODULE_BIND_LAZY);
   if (!mod)
@@ -229,11 +436,14 @@ seed_ffi_construct_library (SeedContext ctx,
       seed_make_exception (ctx, exception, "GModuleError",
 			   "Opening module (%s) failed with: %s",
 			   filename, g_module_error ());
+      g_free (filename);
       return seed_make_null (ctx);
     }
   
   ret = seed_make_object (ctx, ffi_library_class, mod);
   
+  g_free (filename);
+  
   return ret;
 }
 



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]