node-gtk 0.8.1 → 0.11.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/src/function.cc CHANGED
@@ -1,4 +1,3 @@
1
-
2
1
  #include <string.h>
3
2
  #include <girffi.h>
4
3
 
@@ -44,8 +43,8 @@ static int GetV8ArrayLength (Local<Value> value) {
44
43
  else if (value->IsNull() || value->IsUndefined())
45
44
  return 0;
46
45
 
47
- printf("%s\n", *Nan::Utf8String(TO_STRING (value)));
48
- g_assert_not_reached();
46
+ ERROR("Could not determine array length for value %s",
47
+ *Nan::Utf8String(TO_STRING (value)));
49
48
  }
50
49
 
51
50
  static void* AllocateArgument (GIBaseInfo *arg_info) {
@@ -56,7 +55,7 @@ static void* AllocateArgument (GIBaseInfo *arg_info) {
56
55
 
57
56
  GIBaseInfo* base_info = g_type_info_get_interface (&arg_type);
58
57
  size_t size = Boxed::GetSize (base_info);
59
- void* pointer = calloc(1, size);
58
+ void* pointer = g_malloc0(size);
60
59
 
61
60
  g_base_info_unref(base_info);
62
61
  return pointer;
@@ -106,7 +105,196 @@ bool IsDestroyNotify (GIBaseInfo *info) {
106
105
 
107
106
 
108
107
  /**
109
- * Calls a function
108
+ * The constructor just stores the GIBaseInfo ref. The rest of the
109
+ * initialization is done in FunctionInfo::Init, lazily.
110
+ */
111
+ FunctionInfo::FunctionInfo (GIBaseInfo* gi_info) {
112
+ info = g_base_info_ref (gi_info);
113
+ call_parameters = nullptr;
114
+ }
115
+
116
+ FunctionInfo::~FunctionInfo () {
117
+ g_base_info_unref (info);
118
+
119
+ if (call_parameters != nullptr) {
120
+ g_function_invoker_destroy (&invoker);
121
+ delete[] call_parameters;
122
+ }
123
+ }
124
+
125
+ /**
126
+ * Initializes the parameters metadata (number, directionality, type) and caches it
127
+ */
128
+ bool FunctionInfo::Init() {
129
+
130
+ if (call_parameters != nullptr)
131
+ return true;
132
+
133
+ g_function_info_prep_invoker (info, &invoker, NULL);
134
+
135
+ is_method = IsMethod(info);
136
+ can_throw = g_callable_info_can_throw_gerror (info);
137
+
138
+ n_callable_args = g_callable_info_get_n_args (info);
139
+ n_total_args = n_callable_args;
140
+ n_out_args = 0;
141
+ n_in_args = 0;
142
+
143
+ if (is_method)
144
+ n_total_args++;
145
+
146
+ if (can_throw)
147
+ n_total_args++;
148
+
149
+ call_parameters = new Parameter[n_callable_args]();
150
+
151
+ /*
152
+ * Examine load parameter types and count arguments
153
+ */
154
+
155
+ for (int i = 0; i < n_callable_args; i++) {
156
+ GIArgInfo arg_info;
157
+ GITypeInfo type_info;
158
+ g_callable_info_load_arg ((GICallableInfo *) info, i, &arg_info);
159
+ g_arg_info_load_type (&arg_info, &type_info);
160
+
161
+ bool may_be_null = g_arg_info_may_be_null (&arg_info);
162
+ GIDirection direction = g_arg_info_get_direction (&arg_info);
163
+ GITypeTag tag = g_type_info_get_tag(&type_info);
164
+
165
+ call_parameters[i].direction = direction;
166
+
167
+ if (call_parameters[i].type == ParameterType::kSKIP)
168
+ continue;
169
+
170
+ // If there is an array length, this is an array
171
+ int length_i = g_type_info_get_array_length (&type_info);
172
+ if (tag == GI_TYPE_TAG_ARRAY && length_i >= 0) {
173
+ call_parameters[i].type = ParameterType::kARRAY;
174
+ call_parameters[length_i].type = ParameterType::kSKIP;
175
+
176
+ // If array length came before, we need to remove it from args count
177
+
178
+ if (IsDirectionIn(call_parameters[length_i].direction) && length_i < i)
179
+ n_in_args--;
180
+
181
+ if (IsDirectionOut(call_parameters[length_i].direction) && length_i < i)
182
+ n_out_args--;
183
+
184
+ } else if (tag == GI_TYPE_TAG_INTERFACE) {
185
+
186
+ GIBaseInfo* interface_info = g_type_info_get_interface(&type_info);
187
+ GIInfoType interface_type = g_base_info_get_type(interface_info);
188
+
189
+ if (interface_type == GI_INFO_TYPE_CALLBACK) {
190
+ if (IsDestroyNotify(interface_info)) {
191
+ /* Skip GDestroyNotify if they appear before the respective callback */
192
+ call_parameters[i].type = ParameterType::kSKIP;
193
+ } else {
194
+ call_parameters[i].type = ParameterType::kCALLBACK;
195
+
196
+ int destroy_i = g_arg_info_get_destroy(&arg_info);
197
+ int closure_i = g_arg_info_get_closure(&arg_info);
198
+
199
+ if (destroy_i >= 0 && closure_i < 0) {
200
+ Throw::UnsupportedCallback (info);
201
+ g_base_info_unref(interface_info);
202
+ return false;
203
+ }
204
+
205
+ if (destroy_i >= 0 && destroy_i < n_callable_args)
206
+ call_parameters[destroy_i].type = ParameterType::kSKIP;
207
+
208
+ if (closure_i >= 0 && closure_i < n_callable_args)
209
+ call_parameters[closure_i].type = ParameterType::kSKIP;
210
+
211
+ if (destroy_i < i) {
212
+ if (IsDirectionIn(call_parameters[destroy_i].direction))
213
+ n_in_args--;
214
+ if (IsDirectionOut(call_parameters[destroy_i].direction))
215
+ n_out_args--;
216
+ }
217
+
218
+ if (closure_i < i) {
219
+ if (IsDirectionIn(call_parameters[closure_i].direction))
220
+ n_in_args--;
221
+ if (IsDirectionOut(call_parameters[closure_i].direction))
222
+ n_out_args--;
223
+ }
224
+ }
225
+ }
226
+
227
+ g_base_info_unref(interface_info);
228
+ }
229
+
230
+ if (IsDirectionIn(call_parameters[i].direction) && !may_be_null)
231
+ n_in_args++;
232
+
233
+ if (IsDirectionOut(call_parameters[i].direction))
234
+ n_out_args++;
235
+
236
+ }
237
+
238
+ /*
239
+ * Examine return type
240
+ */
241
+
242
+ GITypeInfo return_type;
243
+ g_callable_info_load_return_type(info, &return_type);
244
+ int return_length_i = g_type_info_get_array_length(&return_type);
245
+
246
+ if (return_length_i != -1)
247
+ n_out_args--;
248
+
249
+ if (!ShouldSkipReturn(info, &return_type))
250
+ n_out_args++;
251
+
252
+ return true;
253
+ }
254
+
255
+ /**
256
+ * Type checks the JS arguments, throwing an error.
257
+ * @returns true if types match
258
+ */
259
+ bool FunctionInfo::TypeCheck (const Nan::FunctionCallbackInfo<Value> &arguments) {
260
+
261
+ if (arguments.Length() < n_in_args) {
262
+ Throw::NotEnoughArguments(n_in_args, arguments.Length());
263
+ return false;
264
+ }
265
+
266
+ /*
267
+ * Type check every IN-argument that is not skipped
268
+ */
269
+
270
+ for (int in_arg = 0, i = 0; i < n_callable_args; i++) {
271
+ Parameter &param = call_parameters[i];
272
+
273
+ if (param.type == ParameterType::kSKIP)
274
+ continue;
275
+
276
+ GIArgInfo arg_info;
277
+ g_callable_info_load_arg (info, i, &arg_info);
278
+ GIDirection direction = g_arg_info_get_direction (&arg_info);
279
+
280
+ if (direction == GI_DIRECTION_IN || direction == GI_DIRECTION_INOUT) {
281
+ GITypeInfo type_info;
282
+ g_arg_info_load_type (&arg_info, &type_info);
283
+ bool may_be_null = g_arg_info_may_be_null (&arg_info);
284
+
285
+ if (!CanConvertV8ToGIArgument(&type_info, arguments[in_arg], may_be_null)) {
286
+ Throw::InvalidType(&arg_info, &type_info, arguments[in_arg]);
287
+ return false;
288
+ }
289
+ in_arg++;
290
+ }
291
+ }
292
+
293
+ return true;
294
+ }
295
+
296
+ /**
297
+ * Calls a C function from JS arguments
110
298
  * @param func the function info
111
299
  * @param info JS call informations
112
300
  * @param return_value (out, nullable) the C return value
@@ -119,19 +307,12 @@ Local<Value> FunctionCall (
119
307
  GIArgument *return_value,
120
308
  GError **error
121
309
  ) {
122
- /* FIXME(return_value is never use) */
123
310
 
124
311
  Local<Value> jsReturnValue;
125
312
  GIBaseInfo *gi_info = func->info; // do-not-free
126
313
  bool use_return_value = return_value != NULL;
127
314
  bool use_error = error != NULL;
128
315
 
129
- // bool debug_mode = strcmp(g_base_info_get_name(gi_info), "parse") == 0;
130
- bool debug_mode = false;
131
-
132
- if (debug_mode)
133
- print_callable_info(gi_info);
134
-
135
316
  if (!func->Init())
136
317
  return jsReturnValue;
137
318
 
@@ -143,7 +324,12 @@ Local<Value> FunctionCall (
143
324
  * and for error, if it can throw
144
325
  */
145
326
 
146
- GIArgument total_arg_values[func->n_total_args];
327
+ #ifndef __linux__
328
+ GIArgument *total_arg_values = new GIArgument[func->n_total_args]();
329
+ #else
330
+ GIArgument total_arg_values[func->n_total_args];
331
+ #endif
332
+
147
333
  GIArgument *callable_arg_values;
148
334
  GError *error_stack = nullptr;
149
335
 
@@ -158,7 +344,6 @@ Local<Value> FunctionCall (
158
344
  if (func->can_throw)
159
345
  callable_arg_values[func->n_callable_args].v_pointer = error != NULL ? error : &error_stack;
160
346
 
161
-
162
347
  /*
163
348
  * Second, allocate OUT-arguments and fill IN-arguments
164
349
  */
@@ -166,7 +351,7 @@ Local<Value> FunctionCall (
166
351
  for (int in_arg = 0, i = 0; i < func->n_callable_args; i++) {
167
352
  Parameter& param = func->call_parameters[i];
168
353
 
169
- if (param.type == ParameterType::SKIP)
354
+ if (param.type == ParameterType::kSKIP)
170
355
  continue;
171
356
 
172
357
  GIArgInfo arg_info;
@@ -175,7 +360,7 @@ Local<Value> FunctionCall (
175
360
  g_arg_info_load_type (&arg_info, &type_info);
176
361
  GIDirection direction = g_arg_info_get_direction (&arg_info);
177
362
 
178
- if (param.type == ParameterType::ARRAY) {
363
+ if (param.type == ParameterType::kARRAY) {
179
364
  GIArgInfo array_length_arg;
180
365
  GITypeInfo array_length_type;
181
366
 
@@ -201,8 +386,7 @@ Local<Value> FunctionCall (
201
386
  callable_arg_values[length_i].v_pointer = &len_param.data;
202
387
  }
203
388
  }
204
- else if (param.type == ParameterType::CALLBACK) {
205
- // GIScopeType scope = g_arg_info_get_scope(&arg_info);
389
+ else if (param.type == ParameterType::kCALLBACK) {
206
390
  Callback *callback;
207
391
  ffi_closure *closure;
208
392
 
@@ -221,12 +405,12 @@ Local<Value> FunctionCall (
221
405
  int closure_i = g_arg_info_get_closure(&arg_info);
222
406
 
223
407
  if (destroy_i >= 0) {
224
- g_assert (func->call_parameters[destroy_i].type == ParameterType::SKIP);
408
+ g_assert (func->call_parameters[destroy_i].type == ParameterType::kSKIP);
225
409
  callable_arg_values[destroy_i].v_pointer = callback ? (void*) Callback::DestroyNotify : NULL;
226
410
  }
227
411
 
228
412
  if (closure_i >= 0) {
229
- g_assert (func->call_parameters[closure_i].type == ParameterType::SKIP);
413
+ g_assert (func->call_parameters[closure_i].type == ParameterType::kSKIP);
230
414
  callable_arg_values[closure_i].v_pointer = callback;
231
415
  }
232
416
 
@@ -245,7 +429,7 @@ Local<Value> FunctionCall (
245
429
  else /* (direction == GI_DIRECTION_IN || direction == GI_DIRECTION_INOUT) */ {
246
430
 
247
431
  // Callback GIArgument is filled above, for the rest...
248
- if (param.type != ParameterType::CALLBACK) {
432
+ if (param.type != ParameterType::kCALLBACK) {
249
433
 
250
434
  // FIXME(handle failure here)
251
435
  FillArgument(&arg_info, &callable_arg_values[i], info[in_arg]);
@@ -267,16 +451,24 @@ Local<Value> FunctionCall (
267
451
  * Third, make the actual ffi_call
268
452
  */
269
453
 
270
- void *ffi_args[func->n_total_args];
271
- for (int i = 0; i < func->n_total_args; i++)
272
- ffi_args[i] = &total_arg_values[i];
454
+ #ifndef __linux__
455
+ void **ffi_args = new void*[func->n_total_args]();
456
+ #else
457
+ void *ffi_args[func->n_total_args];
458
+ #endif
273
459
 
460
+ for (int i = 0; i < func->n_total_args; i++)
461
+ ffi_args[i] = (void *)&total_arg_values[i];
274
462
 
275
- GIArgument return_value_stack;
463
+ GIArgument return_value_stack = {0};
276
464
 
277
465
  ffi_call (&func->invoker.cif, FFI_FN (func->invoker.native_address),
278
466
  use_return_value ? return_value : &return_value_stack, ffi_args);
279
467
 
468
+ #ifndef __linux__
469
+ delete[] ffi_args;
470
+ #endif
471
+
280
472
 
281
473
  /*
282
474
  * Fourth, convert the return value & OUT-arguments back to JS
@@ -326,13 +518,13 @@ Local<Value> FunctionCall (
326
518
  GIDirection direction = g_arg_info_get_direction (&arg_info);
327
519
  GITransfer transfer = g_arg_info_get_ownership_transfer (&arg_info);
328
520
 
329
- if (param.type == ParameterType::ARRAY) {
521
+ if (param.type == ParameterType::kARRAY) {
330
522
  if (direction == GI_DIRECTION_INOUT || direction == GI_DIRECTION_OUT)
331
523
  FreeGIArgumentArray (&arg_type, (GIArgument*)arg_value.v_pointer, transfer, direction, param.length);
332
524
  else
333
525
  FreeGIArgumentArray (&arg_type, &arg_value, transfer, direction, param.length);
334
526
  }
335
- else if (param.type == ParameterType::CALLBACK) {
527
+ else if (param.type == ParameterType::kCALLBACK) {
336
528
  Callback *callback = static_cast<Callback*>(func->call_parameters[i].data.v_pointer);
337
529
 
338
530
  g_assert(direction == GI_DIRECTION_IN);
@@ -349,198 +541,13 @@ Local<Value> FunctionCall (
349
541
  }
350
542
  }
351
543
 
352
- return jsReturnValue;
353
- }
354
-
355
-
356
- /**
357
- * The constructor just stores the GIBaseInfo ref. The rest of the
358
- * initialization is done in FunctionInfo::Init, lazily.
359
- */
360
- FunctionInfo::FunctionInfo (GIBaseInfo* gi_info) {
361
- info = g_base_info_ref (gi_info);
362
- call_parameters = nullptr;
363
- }
364
-
365
- FunctionInfo::~FunctionInfo () {
366
- g_base_info_unref (info);
367
-
368
- if (call_parameters != nullptr) {
369
- g_function_invoker_destroy (&invoker);
370
- delete[] call_parameters;
371
- }
372
- }
373
-
374
- /**
375
- * Initializes the function calling data.
376
- */
377
- bool FunctionInfo::Init() {
378
-
379
- if (call_parameters != nullptr)
380
- return true;
381
-
382
- g_function_info_prep_invoker (info, &invoker, NULL);
383
-
384
- is_method = IsMethod(info);
385
- can_throw = g_callable_info_can_throw_gerror (info);
386
-
387
- n_callable_args = g_callable_info_get_n_args (info);
388
- n_total_args = n_callable_args;
389
- n_out_args = 0;
390
- n_in_args = 0;
391
-
392
- if (is_method)
393
- n_total_args++;
394
-
395
- if (can_throw)
396
- n_total_args++;
397
-
398
- call_parameters = new Parameter[n_callable_args]();
399
-
400
- /*
401
- * Examine load parameter types and count arguments
402
- */
403
-
404
- for (int i = 0; i < n_callable_args; i++) {
405
- GIArgInfo arg_info;
406
- GITypeInfo type_info;
407
- g_callable_info_load_arg ((GICallableInfo *) info, i, &arg_info);
408
- g_arg_info_load_type (&arg_info, &type_info);
409
-
410
- bool may_be_null = g_arg_info_may_be_null (&arg_info);
411
- GIDirection direction = g_arg_info_get_direction (&arg_info);
412
- GITypeTag tag = g_type_info_get_tag(&type_info);
413
-
414
- call_parameters[i].direction = direction;
415
-
416
- if (call_parameters[i].type == ParameterType::SKIP)
417
- continue;
418
-
419
- // If there is an array length, this is an array
420
- int length_i = g_type_info_get_array_length (&type_info);
421
- if (tag == GI_TYPE_TAG_ARRAY && length_i >= 0) {
422
- call_parameters[i].type = ParameterType::ARRAY;
423
- call_parameters[length_i].type = ParameterType::SKIP;
424
-
425
- // If array length came before, we need to remove it from args count
426
-
427
- if (IsDirectionIn(call_parameters[length_i].direction) && length_i < i)
428
- n_in_args--;
429
-
430
- if (IsDirectionOut(call_parameters[length_i].direction) && length_i < i)
431
- n_out_args--;
432
-
433
- } else if (tag == GI_TYPE_TAG_INTERFACE) {
434
-
435
- GIBaseInfo* interface_info = g_type_info_get_interface(&type_info);
436
- GIInfoType interface_type = g_base_info_get_type(interface_info);
437
-
438
- if (interface_type == GI_INFO_TYPE_CALLBACK) {
439
- if (IsDestroyNotify(interface_info)) {
440
- /* Skip GDestroyNotify if they appear before the respective callback */
441
- call_parameters[i].type = ParameterType::SKIP;
442
- } else {
443
- call_parameters[i].type = ParameterType::CALLBACK;
444
-
445
- int destroy_i = g_arg_info_get_destroy(&arg_info);
446
- int closure_i = g_arg_info_get_closure(&arg_info);
447
-
448
- if (destroy_i >= 0 && closure_i < 0) {
449
- Throw::UnsupportedCallback (info);
450
- g_base_info_unref(interface_info);
451
- return false;
452
- }
453
-
454
- if (destroy_i >= 0 && destroy_i < n_callable_args)
455
- call_parameters[destroy_i].type = ParameterType::SKIP;
456
-
457
- if (closure_i >= 0 && closure_i < n_callable_args)
458
- call_parameters[closure_i].type = ParameterType::SKIP;
459
-
460
- if (destroy_i < i) {
461
- if (IsDirectionIn(call_parameters[destroy_i].direction))
462
- n_in_args--;
463
- if (IsDirectionOut(call_parameters[destroy_i].direction))
464
- n_out_args--;
465
- }
466
-
467
- if (closure_i < i) {
468
- if (IsDirectionIn(call_parameters[closure_i].direction))
469
- n_in_args--;
470
- if (IsDirectionOut(call_parameters[closure_i].direction))
471
- n_out_args--;
472
- }
473
- }
474
- }
475
-
476
- g_base_info_unref(interface_info);
477
- }
478
-
479
- if (IsDirectionIn(call_parameters[i].direction) && !may_be_null)
480
- n_in_args++;
481
-
482
- if (IsDirectionOut(call_parameters[i].direction))
483
- n_out_args++;
484
-
485
- }
486
-
487
- /*
488
- * Examine return type
489
- */
490
-
491
- GITypeInfo return_type;
492
- g_callable_info_load_return_type(info, &return_type);
493
- int return_length_i = g_type_info_get_array_length(&return_type);
494
-
495
- if (return_length_i != -1)
496
- n_out_args--;
544
+ #ifndef __linux__
545
+ delete[] total_arg_values;
546
+ #endif
497
547
 
498
- if (!ShouldSkipReturn(info, &return_type))
499
- n_out_args++;
500
-
501
- return true;
548
+ return jsReturnValue;
502
549
  }
503
550
 
504
- /**
505
- * Type checks the JS arguments, throwing an error.
506
- * @returns true if types match
507
- */
508
- bool FunctionInfo::TypeCheck (const Nan::FunctionCallbackInfo<Value> &arguments) {
509
-
510
- if (arguments.Length() < n_in_args) {
511
- Throw::NotEnoughArguments(n_in_args, arguments.Length());
512
- return false;
513
- }
514
-
515
- /*
516
- * Type check every IN-argument that is not skipped
517
- */
518
-
519
- for (int in_arg = 0, i = 0; i < n_callable_args; i++) {
520
- Parameter &param = call_parameters[i];
521
-
522
- if (param.type == ParameterType::SKIP)
523
- continue;
524
-
525
- GIArgInfo arg_info;
526
- g_callable_info_load_arg (info, i, &arg_info);
527
- GIDirection direction = g_arg_info_get_direction (&arg_info);
528
-
529
- if (direction == GI_DIRECTION_IN || direction == GI_DIRECTION_INOUT) {
530
- GITypeInfo type_info;
531
- g_arg_info_load_type (&arg_info, &type_info);
532
- bool may_be_null = g_arg_info_may_be_null (&arg_info);
533
-
534
- if (!CanConvertV8ToGIArgument(&type_info, arguments[in_arg], may_be_null)) {
535
- Throw::InvalidType(&arg_info, &type_info, arguments[in_arg]);
536
- return false;
537
- }
538
- in_arg++;
539
- }
540
- }
541
-
542
- return true;
543
- }
544
551
 
545
552
  /**
546
553
  * Creates the JS return value from the C arguments list
@@ -603,7 +610,7 @@ Local<Value> FunctionInfo::GetReturnValue (
603
610
 
604
611
  if (direction == GI_DIRECTION_OUT || direction == GI_DIRECTION_INOUT) {
605
612
 
606
- if (param.type == ParameterType::ARRAY) {
613
+ if (param.type == ParameterType::kARRAY) {
607
614
 
608
615
  int length_i = g_type_info_get_array_length(&arg_type);
609
616
  GIArgInfo length_arg;
@@ -622,7 +629,7 @@ Local<Value> FunctionInfo::GetReturnValue (
622
629
 
623
630
  ADD_RETURN (result)
624
631
 
625
- } else if (param.type == ParameterType::NORMAL) {
632
+ } else if (param.type == ParameterType::kNORMAL) {
626
633
 
627
634
  if (IsPointerType(&arg_type) && g_arg_info_is_caller_allocates(&arg_info)) {
628
635
  void *pointer = &arg_value.v_pointer;
@@ -681,7 +688,6 @@ void FunctionInvoker(const Nan::FunctionCallbackInfo<Value> &info) {
681
688
  RETURN (jsReturnValue);
682
689
  }
683
690
 
684
- // see src/callback.cc
685
691
  Callback::AsyncFree();
686
692
  }
687
693
 
@@ -690,118 +696,4 @@ void FunctionDestroyed(const v8::WeakCallbackInfo<FunctionInfo> &data) {
690
696
  delete func;
691
697
  }
692
698
 
693
-
694
- bool PrepareVFuncInvoker (GIFunctionInfo *info, GIFunctionInvoker *invoker, GType implementor, GError **error) {
695
- gpointer address;
696
- ffi_type **atypes;
697
- GITypeInfo *tinfo;
698
- gint n_args, n_invoke_args, in_pos, out_pos;
699
- bool success;
700
-
701
- GITypeInfo *rinfo = g_callable_info_get_return_type ((GICallableInfo *)info);
702
- ffi_type *rtype = g_type_info_get_ffi_type (rinfo);
703
-
704
- in_pos = 0;
705
- out_pos = 0;
706
-
707
- n_args = g_callable_info_get_n_args ((GICallableInfo *)info);
708
-
709
- n_invoke_args = n_args;
710
-
711
- /* is_method */
712
- n_invoke_args += 1;
713
- in_pos++;
714
-
715
- int n_in_args = 0;
716
- int n_out_args = 0;
717
-
718
- for (int i = 0; i < n_args; i++) {
719
- GIArgInfo arg_info;
720
- g_callable_info_load_arg(info, i, &arg_info);
721
- auto direction = g_arg_info_get_direction(&arg_info);
722
-
723
- if (IsDirectionIn(direction))
724
- n_in_args++;
725
- if (IsDirectionOut(direction))
726
- n_out_args++;
727
- }
728
-
729
- atypes = (ffi_type**)g_alloca (sizeof (ffi_type*) * n_invoke_args);
730
-
731
- /* is_method */
732
- atypes[0] = &ffi_type_pointer;
733
-
734
- for (int i = 0; i < n_args; i++) {
735
- int offset = 1;
736
- GIArgInfo *ainfo = g_callable_info_get_arg ((GICallableInfo *)info, i);
737
-
738
- switch (g_arg_info_get_direction (ainfo)) {
739
- case GI_DIRECTION_IN:
740
- tinfo = g_arg_info_get_type (ainfo);
741
- atypes[i+offset] = g_type_info_get_ffi_type (tinfo);
742
- g_base_info_unref ((GIBaseInfo *)tinfo);
743
-
744
- in_pos++;
745
-
746
- break;
747
- case GI_DIRECTION_OUT:
748
- atypes[i+offset] = &ffi_type_pointer;
749
-
750
- out_pos++;
751
- break;
752
- case GI_DIRECTION_INOUT:
753
- atypes[i+offset] = &ffi_type_pointer;
754
-
755
- in_pos++;
756
- out_pos++;
757
- break;
758
- default:
759
- g_assert_not_reached ();
760
- }
761
- g_base_info_unref ((GIBaseInfo *)ainfo);
762
- }
763
-
764
- success = ffi_prep_cif (&invoker->cif, FFI_DEFAULT_ABI, n_invoke_args, rtype, atypes) == FFI_OK;
765
-
766
- address = g_vfunc_info_get_address (info, implementor, error);
767
- invoker->native_address = address;
768
-
769
- g_base_info_unref ((GIBaseInfo *)rinfo);
770
- return success;
771
- }
772
-
773
- MaybeLocal<Function> MakeVirtualFunction(GIBaseInfo *info, GType implementor) {
774
- GError* error = NULL;
775
-
776
- FunctionInfo *func = g_new0 (FunctionInfo, 1);
777
- func->info = g_base_info_ref (info);
778
- PrepareVFuncInvoker(info, &func->invoker, implementor, &error);
779
-
780
- if (error != NULL) {
781
- char* message = g_strdup_printf("Couldn't create virtual function '%s': %s",
782
- g_base_info_get_name(info), error->message);
783
- Nan::ThrowError(message);
784
- g_free (message);
785
- g_base_info_unref (func->info);
786
- g_function_invoker_destroy (&func->invoker);
787
- g_free (func);
788
- g_error_free (error);
789
- return MaybeLocal<Function>();
790
- }
791
-
792
- auto external = New<External>(func);
793
- auto name = UTF8(g_base_info_get_name (info));
794
-
795
- auto tpl = New<FunctionTemplate>(FunctionInvoker, external);
796
- tpl->SetLength(g_callable_info_get_n_args (info));
797
-
798
- auto fn = Nan::GetFunction (tpl).ToLocalChecked();
799
- fn->SetName(name);
800
-
801
- Persistent<FunctionTemplate> persistent(Isolate::GetCurrent(), tpl);
802
- persistent.SetWeak(func, FunctionDestroyed, WeakCallbackType::kParameter);
803
-
804
- return MaybeLocal<Function>(fn);
805
- }
806
-
807
699
  };