Bug 557241 – "throws" flag for functions

2008-10-21  Johan Bilien  <jobi@via.ecp.fr>

	Bug 557241 – "throws" flag for functions

	* tests/scanner/drawable-1.0-expected.gir,
	tests/scanner/drawable-injected-1.0-expected.gir,
	tests/scanner/drawable.[ch]: add simple test for throwing
	function (has GError ** as last argument)

	* giscanner/ast.py: add a 'throws' flag to Function
	* giscanner/glibtransformer.py: if a function's last paramerter is
	a GError, set the 'throws' flag and remove that parameter
	* giscanner/girwriter.py: write out the 'throws' attribute
	* giscanner/girparser.py: support parsing the 'throws' attribute

	* tests/repository/gitestthrows.c: add a simple test to check the
	throws flag in a typelib and invoke the function

	* girepository/ginfo.c, girepository/girnode.[ch],
	girepository/girnode.h, girepository/girparser.c,
	girepository/girepository.h: Add and parse the GI_FUNCTION_THROWS flag

	* girepository/ginvoke.c: if a function throws, add a GError as last
	arguments, and propagate the error to the invoker.


svn path=/trunk/; revision=773
This commit is contained in:
Johan Bilien 2008-10-21 17:04:11 +00:00 committed by Johan Bilien
parent c3330c06c7
commit 727bb01805
7 changed files with 43 additions and 6 deletions

View File

@ -492,6 +492,9 @@ g_function_info_get_flags (GIFunctionInfo *info)
if (blob->wraps_vfunc) if (blob->wraps_vfunc)
flags = flags | GI_FUNCTION_WRAPS_VFUNC; flags = flags | GI_FUNCTION_WRAPS_VFUNC;
if (blob->throws)
flags = flags | GI_FUNCTION_THROWS;
return flags; return flags;
} }

View File

@ -159,9 +159,11 @@ g_function_info_invoke (GIFunctionInfo *info,
GITypeInfo *tinfo; GITypeInfo *tinfo;
GIArgInfo *ainfo; GIArgInfo *ainfo;
gboolean is_method; gboolean is_method;
gboolean throws;
gint n_args, n_invoke_args, in_pos, out_pos, i; gint n_args, n_invoke_args, in_pos, out_pos, i;
gpointer *args; gpointer *args;
gboolean success = FALSE; gboolean success = FALSE;
GError *local_error;
symbol = g_function_info_get_symbol (info); symbol = g_function_info_get_symbol (info);
@ -178,6 +180,7 @@ g_function_info_invoke (GIFunctionInfo *info,
is_method = (g_function_info_get_flags (info) & GI_FUNCTION_IS_METHOD) != 0 is_method = (g_function_info_get_flags (info) & GI_FUNCTION_IS_METHOD) != 0
&& (g_function_info_get_flags (info) & GI_FUNCTION_IS_CONSTRUCTOR) == 0; && (g_function_info_get_flags (info) & GI_FUNCTION_IS_CONSTRUCTOR) == 0;
throws = g_function_info_get_flags (info) & GI_FUNCTION_THROWS;
tinfo = g_callable_info_get_return_type ((GICallableInfo *)info); tinfo = g_callable_info_get_return_type ((GICallableInfo *)info);
rtype = get_ffi_type (tinfo); rtype = get_ffi_type (tinfo);
@ -202,6 +205,11 @@ g_function_info_invoke (GIFunctionInfo *info,
} }
else else
n_invoke_args = n_args; n_invoke_args = n_args;
if (throws)
/* Add an argument for the GError */
n_invoke_args ++;
atypes = g_alloca (sizeof (ffi_type*) * n_invoke_args); atypes = g_alloca (sizeof (ffi_type*) * n_invoke_args);
args = g_alloca (sizeof (gpointer) * n_invoke_args); args = g_alloca (sizeof (gpointer) * n_invoke_args);
@ -279,6 +287,15 @@ g_function_info_invoke (GIFunctionInfo *info,
} }
g_base_info_unref ((GIBaseInfo *)ainfo); g_base_info_unref ((GIBaseInfo *)ainfo);
} }
local_error = NULL;
if (throws)
{
gpointer address = &local_error;
args[n_invoke_args - 1] = &address;
atypes[n_invoke_args - 1] = &ffi_type_pointer;
}
if (in_pos < n_in_args) if (in_pos < n_in_args)
{ {
g_set_error (error, g_set_error (error,
@ -301,7 +318,15 @@ g_function_info_invoke (GIFunctionInfo *info,
ffi_call (&cif, func, return_value, args); ffi_call (&cif, func, return_value, args);
success = TRUE; if (local_error)
{
g_propagate_error (error, local_error);
success = FALSE;
}
else
{
success = TRUE;
}
out: out:
return success; return success;
} }

View File

@ -190,7 +190,8 @@ typedef enum
GI_FUNCTION_IS_CONSTRUCTOR = 1 << 1, GI_FUNCTION_IS_CONSTRUCTOR = 1 << 1,
GI_FUNCTION_IS_GETTER = 1 << 2, GI_FUNCTION_IS_GETTER = 1 << 2,
GI_FUNCTION_IS_SETTER = 1 << 3, GI_FUNCTION_IS_SETTER = 1 << 3,
GI_FUNCTION_WRAPS_VFUNC = 1 << 4 GI_FUNCTION_WRAPS_VFUNC = 1 << 4,
GI_FUNCTION_THROWS = 1 << 5
} GIFunctionInfoFlags; } GIFunctionInfoFlags;
const gchar * g_function_info_get_symbol (GIFunctionInfo *info); const gchar * g_function_info_get_symbol (GIFunctionInfo *info);

View File

@ -1477,7 +1477,7 @@ g_ir_node_build_typelib (GIrNode *node,
blob->getter = function->is_getter; blob->getter = function->is_getter;
blob->constructor = function->is_constructor; blob->constructor = function->is_constructor;
blob->wraps_vfunc = function->wraps_vfunc; blob->wraps_vfunc = function->wraps_vfunc;
blob->reserved = 0; blob->throws = function->throws;
blob->index = 0; blob->index = 0;
blob->name = write_string (node->name, strings, data, offset2); blob->name = write_string (node->name, strings, data, offset2);
blob->symbol = write_string (function->symbol, strings, data, offset2); blob->symbol = write_string (function->symbol, strings, data, offset2);

View File

@ -92,6 +92,7 @@ struct _GIrNodeFunction
gboolean is_getter; gboolean is_getter;
gboolean is_constructor; gboolean is_constructor;
gboolean wraps_vfunc; gboolean wraps_vfunc;
gboolean throws;
gchar *symbol; gchar *symbol;

View File

@ -527,6 +527,7 @@ start_function (GMarkupParseContext *context,
const gchar *name; const gchar *name;
const gchar *symbol; const gchar *symbol;
const gchar *deprecated; const gchar *deprecated;
const gchar *throws;
GIrNodeFunction *function; GIrNodeFunction *function;
gboolean found = FALSE; gboolean found = FALSE;
@ -557,6 +558,7 @@ start_function (GMarkupParseContext *context,
name = find_attribute ("name", attribute_names, attribute_values); name = find_attribute ("name", attribute_names, attribute_values);
symbol = find_attribute ("c:identifier", attribute_names, attribute_values); symbol = find_attribute ("c:identifier", attribute_names, attribute_values);
deprecated = find_attribute ("deprecated", attribute_names, attribute_values); deprecated = find_attribute ("deprecated", attribute_names, attribute_values);
throws = find_attribute ("throws", attribute_names, attribute_values);
if (name == NULL) if (name == NULL)
{ {
@ -599,6 +601,11 @@ start_function (GMarkupParseContext *context,
((GIrNode *)function)->type = G_IR_NODE_CALLBACK; ((GIrNode *)function)->type = G_IR_NODE_CALLBACK;
} }
if (throws && strcmp (throws, "1") == 0)
function->throws = TRUE;
else
function->throws = FALSE;
if (ctx->current_node == NULL) if (ctx->current_node == NULL)
{ {
ctx->current_module->entries = ctx->current_module->entries =

View File

@ -170,7 +170,7 @@ typedef struct
guint16 getter : 1; guint16 getter : 1;
guint16 constructor : 1; guint16 constructor : 1;
guint16 wraps_vfunc : 1; guint16 wraps_vfunc : 1;
guint16 reserved : 1; guint16 throws : 1;
guint16 index :10; guint16 index :10;
guint32 name; guint32 name;