gnome-perl-introspection r11 - in Glib-Object-Introspection/trunk: . xs
- From: tsch svn gnome org
- To: svn-commits-list gnome org
- Subject: gnome-perl-introspection r11 - in Glib-Object-Introspection/trunk: . xs
- Date: Sat, 15 Mar 2008 22:56:01 +0000 (GMT)
Author: tsch
Date: Sat Mar 15 22:56:01 2008
New Revision: 11
URL: http://svn.gnome.org/viewvc/gnome-perl-introspection?rev=11&view=rev
Log:
* IdlFunctionInfo.xs (XS_Glib__Idl__FunctionInfo_invoke): Use
libffi directly instead of g_function_info_invoke for function
invocation.
Added:
Glib-Object-Introspection/trunk/ChangeLog
Modified:
Glib-Object-Introspection/trunk/xs/IdlFunctionInfo.xs
Modified: Glib-Object-Introspection/trunk/xs/IdlFunctionInfo.xs
==============================================================================
--- Glib-Object-Introspection/trunk/xs/IdlFunctionInfo.xs (original)
+++ Glib-Object-Introspection/trunk/xs/IdlFunctionInfo.xs Sat Mar 15 22:56:01 2008
@@ -1095,6 +1095,15 @@
{
GIFunctionInfo * info = SvGIFunctionInfo (ST(0));
+
+ ffi_cif cif;
+ ffi_type **arg_types = NULL;
+ ffi_type *return_type_ffi = NULL;
+ gpointer *args = NULL;
+ gpointer func_pointer = NULL;
+ GModule *module = NULL;
+ const gchar *symbol = NULL;
+
int have_args;
int n_args;
int n_in_args;
@@ -1102,17 +1111,22 @@
int i, out_i;
GITypeInfo ** out_arg_type = NULL;
GITypeInfo * return_type_info = NULL;
- GITransfer return_type_transfer;
gboolean has_return_value;
GArgument return_value;
GArgument * in_args = NULL;
GArgument * out_args = NULL;
- GError * error = NULL;
+
+ symbol = g_function_info_get_symbol (info);
#ifdef NOISY
- warn ("invoke: %s\n", g_function_info_get_symbol (info));
+ warn ("invoke: %s\n", symbol);
#endif
+ module = g_module_open (NULL, 0);
+ if (!g_module_symbol (module, symbol, &func_pointer)) {
+ croak ("Could not locate symbol %s", symbol);
+ }
+
#define OFFSET 1
have_args = items - OFFSET;
n_args = g_callable_info_get_n_args ((GICallableInfo *) info);
@@ -1125,12 +1139,17 @@
in_args = gperl_alloc_temp (sizeof (GArgument) * n_args);
out_args = gperl_alloc_temp (sizeof (GArgument) * n_args);
out_arg_type = gperl_alloc_temp (sizeof (GITypeInfo*) * n_args);
+
+ arg_types = gperl_alloc_temp (sizeof (ffi_type *) * n_args);
+ args = gperl_alloc_temp (sizeof (gpointer) * n_args);
}
n_in_args = n_out_args = 0;
for (i = 0 ; i < n_args ; i++) {
GIArgInfo * arg_info =
g_callable_info_get_arg ((GICallableInfo *) info, i);
+ /* In case of out and in-out args, arg_type is unref'ed after
+ * the function has been invoked */
GITypeInfo * arg_type = g_arg_info_get_type (arg_info);
gboolean may_be_null = g_arg_info_may_be_null (arg_info);
@@ -1140,49 +1159,71 @@
switch (g_arg_info_get_direction (arg_info)) {
case GI_DIRECTION_IN:
- sv_to_arg (ST (i+OFFSET), in_args+n_in_args++, arg_type, may_be_null);
+ sv_to_arg (ST (i+OFFSET), &in_args[n_in_args], arg_type, may_be_null);
+ arg_types[i] = get_ffi_type (arg_type);
+ args[i] = &in_args[n_in_args];
g_base_info_unref ((GIBaseInfo *) arg_type);
+ n_in_args++;
break;
case GI_DIRECTION_OUT:
- out_args[n_out_args++].v_pointer =
+ out_args[n_out_args].v_pointer =
gperl_alloc_temp (sizeof (GArgument));
- out_arg_type[n_out_args-1] = arg_type;
+ out_arg_type[n_out_args] = arg_type;
+ arg_types[i] = &ffi_type_pointer;
+ args[i] = &out_args[n_out_args];
+ n_out_args++;
break;
case GI_DIRECTION_INOUT:
{
GArgument * temp =
gperl_alloc_temp (sizeof (GArgument));
sv_to_arg (ST (i+OFFSET), temp, arg_type, may_be_null);
- in_args[n_in_args++].v_pointer =
- out_args[n_out_args++].v_pointer =
+ in_args[n_in_args].v_pointer =
+ out_args[n_out_args].v_pointer =
temp;
- out_arg_type[n_out_args-1] = arg_type;
+ out_arg_type[n_out_args] = arg_type;
+ arg_types[i] = &ffi_type_pointer;
+ args[i] = &in_args[n_in_args];
+ n_in_args++;
+ n_out_args++;
}
break;
}
- g_base_info_unref ((GIBaseInfo*) arg_info);
+ g_base_info_unref ((GIBaseInfo *) arg_info);
}
#undef OFFSET
- /* if (n_in_args != have_args)
- croak ("%s needs %d args, got %d",
- g_function_info_get_symbol (info),
- n_in_args, have_args); */
-
- if (! g_function_info_invoke (info, in_args, n_in_args,
- out_args, n_out_args,
- &return_value, &error))
- gperl_croak_gerror (NULL, error);
+#if 0
+ /*
+ * This doesn't work for callback stuff, for example. The C function
+ * has (func, data, destroy_notify) whereas Perl only has (func, data).
+ */
+ if (n_in_args != have_args)
+ croak ("%s needs %d args, got %d", symbol, n_in_args, have_args);
+#endif
+
+ /* find the return value type */
+ return_type_info = g_callable_info_get_return_type ((GICallableInfo *) info);
+ return_type_ffi = get_ffi_type (return_type_info);
+
+ /* prepare and call the function */
+ if (FFI_OK != ffi_prep_cif (&cif, FFI_DEFAULT_ABI, n_args,
+ return_type_ffi, arg_types))
+ {
+ g_base_info_unref ((GIBaseInfo *) return_type_info);
+ croak ("Could not prepare a call interface for %s", symbol);
+ }
+
+ ffi_call (&cif, func_pointer, &return_value, args);
/*
* place return value and output args on the stack
*/
- return_type_info = g_callable_info_get_return_type ((GICallableInfo *) info);
- return_type_transfer = g_callable_info_get_caller_owns ((GICallableInfo *) info);
has_return_value = GI_TYPE_TAG_VOID != g_type_info_get_tag (return_type_info);
-
if (has_return_value) {
+ GITransfer return_type_transfer =
+ g_callable_info_get_caller_owns ((GICallableInfo *) info);
SV *value = arg_to_sv (&return_value,
return_type_info,
return_type_transfer);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]