[gnode] function: Add more support for out pointers
- From: Jasper St. Pierre <jstpierre src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnode] function: Add more support for out pointers
- Date: Sat, 28 Nov 2015 05:52:53 +0000 (UTC)
commit c70e90c47b4ae344544737f76d95c8f6d0a49004
Author: Jasper St. Pierre <jstpierre mecheye net>
Date: Fri Nov 27 13:06:10 2015 -0800
function: Add more support for out pointers
Allow calling gtk_init, even if we throw the result away.
src/function.cc | 89 +++++++++++++++++++++++++++++++++++++------------------
1 files changed, 60 insertions(+), 29 deletions(-)
---
diff --git a/src/function.cc b/src/function.cc
index b2d58d8..09d588c 100644
--- a/src/function.cc
+++ b/src/function.cc
@@ -24,12 +24,15 @@
#include "value.h"
#include "gobject.h"
+#include <girffi.h>
+
using namespace v8;
namespace GNodeJS {
struct FunctionInfo {
GIFunctionInfo *info;
+ GIFunctionInvoker invoker;
};
static Handle<Value> FunctionInvoker(const Arguments &args) {
@@ -37,13 +40,21 @@ static Handle<Value> FunctionInvoker(const Arguments &args) {
FunctionInfo *func = (FunctionInfo *) External::Unwrap (args.Data ());
GIBaseInfo *info = func->info;
- GIFunctionInfo *function_info = (GIFunctionInfo *) info;
GError *error = NULL;
- /* XXX: For now, only work on functions without any OUT args at all.
- * Just assume everything is an in arg. */
- int n_in_args = g_callable_info_get_n_args ((GICallableInfo *) info);
- int n_total_args = n_in_args;
+ int n_callable_args = g_callable_info_get_n_args ((GICallableInfo *) info);
+ int n_total_args = n_callable_args;
+ int n_in_args = 0;
+
+ for (int i = 0; i < n_callable_args; i++) {
+ GIArgInfo arg_info;
+
+ g_callable_info_load_arg ((GICallableInfo *) info, i, &arg_info);
+
+ if (g_arg_info_get_direction (&arg_info) == GI_DIRECTION_IN ||
+ g_arg_info_get_direction (&arg_info) == GI_DIRECTION_INOUT)
+ n_in_args++;
+ }
if (args.Length() < n_in_args) {
ThrowException (Exception::TypeError (String::New ("Not enough arguments.")));
@@ -55,38 +66,54 @@ static Handle<Value> FunctionInvoker(const Arguments &args) {
if (is_method)
n_total_args++;
- GIArgument total_args[n_total_args];
- GIArgument *in_args;
+ GIArgument total_arg_values[n_total_args];
+ GIArgument *callable_arg_values;
if (is_method) {
- total_args[0].v_pointer = GObjectFromWrapper (args.This ());
- in_args = &total_args[1];
+ total_arg_values[0].v_pointer = GObjectFromWrapper (args.This ());
+ callable_arg_values = &total_arg_values[1];
} else {
- in_args = &total_args[0];
+ callable_arg_values = &total_arg_values[0];
}
- for (int i = 0; i < n_in_args; i++) {
- GIArgInfo *arg_info = g_callable_info_get_arg ((GICallableInfo *) info, i);
- GITypeInfo type_info;
- bool may_be_null = g_arg_info_may_be_null (arg_info);
- g_arg_info_load_type (arg_info, &type_info);
- V8ToGIArgument (&type_info, &in_args[i], args[i], may_be_null);
- g_base_info_unref ((GIBaseInfo *) arg_info);
+ for (int i = 0; i < n_callable_args; i++) {
+ GIArgInfo arg_info = {};
+ g_callable_info_load_arg ((GICallableInfo *) info, i, &arg_info);
+ GIDirection direction = g_arg_info_get_direction (&arg_info);
+
+ if (direction == GI_DIRECTION_OUT) {
+ if (g_arg_info_is_caller_allocates (&arg_info)) {
+ assert (0);
+ } else {
+ callable_arg_values[i].v_pointer = NULL;
+ }
+ } else {
+ bool may_be_null = g_arg_info_may_be_null (&arg_info);
+ GITypeInfo type_info;
+ g_arg_info_load_type (&arg_info, &type_info);
+ V8ToGIArgument (&type_info, &callable_arg_values[i], args[i], may_be_null);
+ }
}
+ void *ffi_arg_pointers[n_total_args];
+ for (int i = 0; i < n_total_args; i++)
+ ffi_arg_pointers[i] = &total_arg_values[i];
+
GIArgument return_value;
- g_function_info_invoke (function_info,
- total_args, n_total_args,
- NULL, 0,
- &return_value,
- &error);
-
- for (int i = 0; i < n_in_args; i++) {
- GIArgInfo *arg_info = g_callable_info_get_arg ((GICallableInfo *) info, i);
- GITypeInfo type_info;
- g_arg_info_load_type (arg_info, &type_info);
- FreeGIArgument (&type_info, &in_args[i]);
- g_base_info_unref ((GIBaseInfo *) arg_info);
+ ffi_call (&func->invoker.cif, FFI_FN (func->invoker.native_address),
+ &return_value, ffi_arg_pointers);
+
+ for (int i = 0; i < n_callable_args; i++) {
+ GIArgInfo arg_info;
+ g_callable_info_load_arg ((GICallableInfo *) info, i, &arg_info);
+ GIDirection direction = g_arg_info_get_direction (&arg_info);
+ if (direction == GI_DIRECTION_OUT) {
+ /* XXX: Process out value. */
+ } else {
+ GITypeInfo type_info;
+ g_arg_info_load_type (&arg_info, &type_info);
+ FreeGIArgument (&type_info, &callable_arg_values[i]);
+ }
}
if (error) {
@@ -102,12 +129,16 @@ static Handle<Value> FunctionInvoker(const Arguments &args) {
static void FunctionDestroyed(Persistent<Value> object, void *data) {
FunctionInfo *func = (FunctionInfo *) data;
g_base_info_unref (func->info);
+ g_function_invoker_destroy(&func->invoker);
g_free (func);
}
Handle<Function> MakeFunction(GIBaseInfo *info) {
FunctionInfo *func = g_new0 (FunctionInfo, 1);
func->info = g_base_info_ref (info);
+
+ g_function_info_prep_invoker (func->info, &func->invoker, NULL);
+
Persistent<FunctionTemplate> tpl = Persistent<FunctionTemplate>::New (FunctionTemplate::New
(FunctionInvoker, External::Wrap (func)));
tpl.MakeWeak (func, FunctionDestroyed);
Local<Function> fn = tpl->GetFunction ();
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]