Flutter Engine
The Flutter Engine
dart_args.h
Go to the documentation of this file.
1// Copyright 2013 The Flutter Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#ifndef LIB_TONIC_DART_ARGS_H_
6#define LIB_TONIC_DART_ARGS_H_
7
8#include <iostream>
9#include <sstream>
10#include <type_traits>
11#include <utility>
12
13#include "third_party/dart/runtime/include/dart_api.h"
16
17namespace tonic {
18
20 public:
21 explicit DartArgIterator(Dart_NativeArguments args, int start_index = 1)
22 : args_(args), index_(start_index), had_exception_(false) {}
23
24 template <typename T>
26 if (had_exception_)
27 return T();
28 Dart_Handle exception = nullptr;
29 T arg = DartConverter<T>::FromArguments(args_, index_++, exception);
30 if (exception) {
31 had_exception_ = true;
32 Dart_ThrowException(exception);
33 }
34 return arg;
35 }
36
37 bool had_exception() const { return had_exception_; }
38
39 Dart_NativeArguments args() const { return args_; }
40
41 private:
43 int index_;
44 bool had_exception_;
45
46 TONIC_DISALLOW_COPY_AND_ASSIGN(DartArgIterator);
47};
48
49// Classes for generating and storing an argument pack of integer indices
50// (based on well-known "indices trick", see: http://goo.gl/bKKojn):
51template <size_t... indices>
52struct IndicesHolder {};
53
54template <size_t requested_index, size_t... indices>
56 using type = typename IndicesGenerator<requested_index - 1,
57 requested_index - 1,
58 indices...>::type;
59};
60
61template <size_t... indices>
62struct IndicesGenerator<0, indices...> {
63 using type = IndicesHolder<indices...>;
64};
65
66template <typename T>
68
69template <typename ResultType, typename... ArgTypes>
70struct IndicesForSignature<ResultType (*)(ArgTypes...)> {
71 static const size_t count = sizeof...(ArgTypes);
73};
74
75template <typename C, typename ResultType, typename... ArgTypes>
76struct IndicesForSignature<ResultType (C::*)(ArgTypes...)> {
77 static const size_t count = sizeof...(ArgTypes);
79};
80
81template <typename C, typename ResultType, typename... ArgTypes>
82struct IndicesForSignature<ResultType (C::*)(ArgTypes...) const> {
83 static const size_t count = sizeof...(ArgTypes);
85};
86
87template <size_t index, typename ArgType>
89 using ValueType = typename std::remove_const<
91
93
95 : value(it->GetNext<ValueType>()) {}
96};
97
98template <typename T>
101}
102
103template <typename IndicesType, typename T>
105
106// Match functions on the form:
107// `void f(ArgTypes...)`
108template <size_t... indices, typename... ArgTypes>
109struct DartDispatcher<IndicesHolder<indices...>, void (*)(ArgTypes...)>
111 using FunctionPtr = void (*)(ArgTypes...);
112
114
116 : DartArgHolder<indices, ArgTypes>(it)..., it_(it) {}
117
120 }
121};
122
123// Match functions on the form:
124// `ResultType f(ArgTypes...)`
125template <size_t... indices, typename ResultType, typename... ArgTypes>
126struct DartDispatcher<IndicesHolder<indices...>, ResultType (*)(ArgTypes...)>
128 using FunctionPtr = ResultType (*)(ArgTypes...);
130
132
134 : DartArgHolder<indices, ArgTypes>(it)..., it_(it) {}
135
138 it_->args());
139 }
140
143 }
144};
145
146// Match instance methods on the form:
147// `void C::m(ArgTypes...)`
148template <size_t... indices, typename C, typename... ArgTypes>
149struct DartDispatcher<IndicesHolder<indices...>, void (C::*)(ArgTypes...)>
150 : public DartArgHolder<indices, ArgTypes>... {
151 using FunctionPtr = void (C::*)(ArgTypes...);
152
154
156 : DartArgHolder<indices, ArgTypes>(it)..., it_(it) {}
157
159 (GetReceiver<C>(it_->args())->*func)(
161 }
162};
163
164// Match instance methods on the form:
165// `ReturnType (C::m)(ArgTypes...) const`
166template <size_t... indices,
167 typename C,
168 typename ReturnType,
169 typename... ArgTypes>
170struct DartDispatcher<IndicesHolder<indices...>,
171 ReturnType (C::*)(ArgTypes...) const>
172 : public DartArgHolder<indices, ArgTypes>... {
173 using FunctionPtr = ReturnType (C::*)(ArgTypes...) const;
174
176
178 : DartArgHolder<indices, ArgTypes>(it)..., it_(it) {}
179
181 DartReturn((GetReceiver<C>(it_->args())->*func)(
183 it_->args());
184 }
185};
186
187// Match instance methods on the form:
188// `ReturnType (C::m)(ArgTypes...)`
189template <size_t... indices,
190 typename C,
191 typename ResultType,
192 typename... ArgTypes>
193struct DartDispatcher<IndicesHolder<indices...>, ResultType (C::*)(ArgTypes...)>
194 : public DartArgHolder<indices, ArgTypes>... {
195 using FunctionPtr = ResultType (C::*)(ArgTypes...);
196
198
200 : DartArgHolder<indices, ArgTypes>(it)..., it_(it) {}
201
203 DartReturn((GetReceiver<C>(it_->args())->*func)(
205 it_->args());
206 }
207};
208
209template <typename Sig>
212 using Indices = typename IndicesForSignature<Sig>::type;
213 DartDispatcher<Indices, Sig> decoder(&it);
214 if (it.had_exception())
215 return;
216 decoder.Dispatch(func);
217}
218
219template <typename Sig>
221 DartArgIterator it(args, 0);
222 using Indices = typename IndicesForSignature<Sig>::type;
223 DartDispatcher<Indices, Sig> decoder(&it);
224 if (it.had_exception())
225 return;
226 decoder.Dispatch(func);
227}
228
229template <typename Sig>
232 using Indices = typename IndicesForSignature<Sig>::type;
233 using Wrappable = typename DartDispatcher<Indices, Sig>::CtorResultType;
234 Wrappable wrappable;
235 {
236 DartDispatcher<Indices, Sig> decoder(&it);
237 if (it.had_exception())
238 return;
239 wrappable = decoder.DispatchCtor(func);
240 }
241
244
245 intptr_t native_fields[DartWrappable::kNumberOfNativeFields];
247 args, 0, DartWrappable::kNumberOfNativeFields, native_fields)));
248 TONIC_CHECK(!native_fields[DartWrappable::kPeerIndex]);
249
250 wrappable->AssociateWithDartWrapper(wrapper);
251}
252
253// Templates to automatically setup static entry points for FFI Native
254// functions.
255// Entry points for instance methods take the instance as the first argument and
256// call the given method with the remaining arguments.
257// Arguments will automatically get converted to and from their FFI
258// representations with the DartConverter templates.
259//
260// @tparam C The type of the receiver. Or `void` if there is no receiver.
261// @tparam Signature The signature of the function being dispatched to.
262// @tparam function The function pointer being dispatched to.
263template <typename C, typename Signature, Signature function>
265
266// Concatenate the FFI representation of each argument to the stream,
267// serialising them into a comma separated list.
268// Example: "Handle, Bool, Uint64"
269template <typename Arg, typename... Args>
270void WriteFfiArguments(std::ostringstream* stream) {
271 *stream << tonic::DartConverter<typename std::remove_const<
272 typename std::remove_reference<Arg>::type>::type>::GetFfiRepresentation();
273 if constexpr (sizeof...(Args) > 0) {
274 *stream << ", ";
275 WriteFfiArguments<Args...>(stream);
276 }
277}
278
279// Concatenate the Dart representation of each argument to the stream,
280// serialising them into a comma separated list.
281// Example: "Object, bool, int"
282template <typename Arg, typename... Args>
283void WriteDartArguments(std::ostringstream* stream) {
286 type>::GetDartRepresentation();
287 if constexpr (sizeof...(Args) > 0) {
288 *stream << ", ";
289 WriteDartArguments<Args...>(stream);
290 }
291}
292
293// Logical 'and' together whether each argument is allowed in a leaf call.
294template <typename Arg, typename... Args>
296 bool result = tonic::DartConverter<typename std::remove_const<
298 if constexpr (sizeof...(Args) > 0) {
299 result &= AllowedInLeafCall<Args...>();
300 }
301 return result;
302}
303
304// Match `Return function(...)`.
305template <typename Return, typename... Args, Return (*function)(Args...)>
306struct FfiDispatcher<void, Return (*)(Args...), function> {
308 static const size_t n_args = sizeof...(Args);
309
310 // Static C entry-point with Dart FFI signature.
312 typename DartConverter<typename std::remove_const<
313 typename std::remove_reference<Args>::type>::type>::FfiType... args) {
314 // Call C++ function, forwarding converted native arguments.
316 DartConverter<typename std::remove_const<typename std::remove_reference<
317 Args>::type>::type>::FromFfi(args)...));
318 }
319
320 static bool AllowedAsLeafCall() {
321 if constexpr (sizeof...(Args) > 0) {
322 return AllowedInLeafCall<Return>() && AllowedInLeafCall<Args...>();
323 }
324 return AllowedInLeafCall<Return>();
325 }
326
327 static const char* GetReturnFfiRepresentation() {
329 }
330
331 static const char* GetReturnDartRepresentation() {
333 }
334
335 static void WriteFfiArguments(std::ostringstream* stream) {
336 if constexpr (sizeof...(Args) > 0) {
338 }
339 }
340
341 static void WriteDartArguments(std::ostringstream* stream) {
342 if constexpr (sizeof...(Args) > 0) {
344 }
345 }
346};
347
348// Match `Return C::method(...)`.
349template <typename C,
350 typename Return,
351 typename... Args,
352 Return (C::*method)(Args...)>
353struct FfiDispatcher<C, Return (C::*)(Args...), method> {
355 static const size_t n_args = sizeof...(Args);
356
357 // Static C entry-point with Dart FFI signature.
359 DartWrappable* receiver,
360 typename DartConverter<typename std::remove_const<
361 typename std::remove_reference<Args>::type>::type>::FfiType... args) {
362 // Call C++ method on receiver, forwarding converted native arguments.
363 return DartConverter<Return>::ToFfi((static_cast<C*>(receiver)->*method)(
364 DartConverter<typename std::remove_const<typename std::remove_reference<
365 Args>::type>::type>::FromFfi(args)...));
366 }
367
368 static bool AllowedAsLeafCall() {
369 if constexpr (sizeof...(Args) > 0) {
370 return AllowedInLeafCall<Return>() && AllowedInLeafCall<Args...>();
371 }
372 return AllowedInLeafCall<Return>();
373 }
374
375 static const char* GetReturnFfiRepresentation() {
377 }
378
379 static const char* GetReturnDartRepresentation() {
381 }
382
383 static void WriteFfiArguments(std::ostringstream* stream) {
384 *stream << tonic::DartConverter<C*>::GetFfiRepresentation();
385 if constexpr (sizeof...(Args) > 0) {
386 *stream << ", ";
388 }
389 }
390
391 static void WriteDartArguments(std::ostringstream* stream) {
392 *stream << tonic::DartConverter<C*>::GetDartRepresentation();
393 if constexpr (sizeof...(Args) > 0) {
394 *stream << ", ";
396 }
397 }
398};
399
400// Match `Return C::method(...) const`.
401template <typename C,
402 typename Return,
403 typename... Args,
404 Return (C::*method)(Args...) const>
405struct FfiDispatcher<C, Return (C::*)(Args...) const, method> {
407 static const size_t n_args = sizeof...(Args);
408
409 // Static C entry-point with Dart FFI signature.
411 DartWrappable* receiver,
412 typename DartConverter<typename std::remove_const<
413 typename std::remove_reference<Args>::type>::type>::FfiType... args) {
414 // Call C++ method on receiver, forwarding converted native arguments.
415 return DartConverter<Return>::ToFfi((static_cast<C*>(receiver)->*method)(
416 DartConverter<typename std::remove_const<typename std::remove_reference<
417 Args>::type>::type>::FromFfi(args)...));
418 }
419
420 static bool AllowedAsLeafCall() {
421 if constexpr (sizeof...(Args) > 0) {
422 return AllowedInLeafCall<Return>() && AllowedInLeafCall<Args...>();
423 }
424 return AllowedInLeafCall<Return>();
425 }
426
427 static const char* GetReturnFfiRepresentation() {
429 }
430
431 static const char* GetReturnDartRepresentation() {
433 }
434
435 static void WriteFfiArguments(std::ostringstream* stream) {
436 *stream << tonic::DartConverter<C*>::GetFfiRepresentation();
437 if constexpr (sizeof...(Args) > 0) {
438 *stream << ", ";
440 }
441 }
442
443 static void WriteDartArguments(std::ostringstream* stream) {
444 *stream << tonic::DartConverter<C*>::GetDartRepresentation();
445 if constexpr (sizeof...(Args) > 0) {
446 *stream << ", ";
448 }
449 }
450};
451
452// `void` specialisation since we can't declare `ToFfi` to take void rvalues.
453// Match `void function(...)`.
454template <typename... Args, void (*function)(Args...)>
455struct FfiDispatcher<void, void (*)(Args...), function> {
456 static const size_t n_args = sizeof...(Args);
457
458 // Static C entry-point with Dart FFI signature.
459 static void Call(
460 typename DartConverter<typename std::remove_const<
461 typename std::remove_reference<Args>::type>::type>::FfiType... args) {
462 // Call C++ function, forwarding converted native arguments.
463 function(
464 DartConverter<typename std::remove_const<typename std::remove_reference<
465 Args>::type>::type>::FromFfi(args)...);
466 }
467
468 static bool AllowedAsLeafCall() {
469 if constexpr (sizeof...(Args) > 0) {
470 return AllowedInLeafCall<Args...>();
471 }
472 return true;
473 }
474
475 static const char* GetReturnFfiRepresentation() {
477 }
478
479 static const char* GetReturnDartRepresentation() {
481 }
482
483 static void WriteFfiArguments(std::ostringstream* stream) {
484 if constexpr (sizeof...(Args) > 0) {
486 }
487 }
488
489 static void WriteDartArguments(std::ostringstream* stream) {
490 if constexpr (sizeof...(Args) > 0) {
492 }
493 }
494};
495
496// `void` specialisation since we can't declare `ToFfi` to take void rvalues.
497// Match `void C::method(...)`.
498template <typename C, typename... Args, void (C::*method)(Args...)>
499struct FfiDispatcher<C, void (C::*)(Args...), method> {
500 static const size_t n_args = sizeof...(Args);
501
502 // Static C entry-point with Dart FFI signature.
503 static void Call(
504 DartWrappable* receiver,
505 typename DartConverter<typename std::remove_const<
506 typename std::remove_reference<Args>::type>::type>::FfiType... args) {
507 // Call C++ method on receiver, forwarding converted native arguments.
508 (static_cast<C*>(receiver)->*method)(
509 DartConverter<typename std::remove_const<typename std::remove_reference<
510 Args>::type>::type>::FromFfi(args)...);
511 }
512
513 static bool AllowedAsLeafCall() {
514 if constexpr (sizeof...(Args) > 0) {
515 return AllowedInLeafCall<Args...>();
516 }
517 return true;
518 }
519
520 static const char* GetReturnFfiRepresentation() {
522 }
523
524 static const char* GetReturnDartRepresentation() {
526 }
527
528 static void WriteFfiArguments(std::ostringstream* stream) {
529 *stream << tonic::DartConverter<C*>::GetFfiRepresentation();
530 if constexpr (sizeof...(Args) > 0) {
531 *stream << ", ";
533 }
534 }
535
536 static void WriteDartArguments(std::ostringstream* stream) {
537 *stream << tonic::DartConverter<C*>::GetDartRepresentation();
538 if constexpr (sizeof...(Args) > 0) {
539 *stream << ", ";
541 }
542 }
543};
544
545} // namespace tonic
546
547#endif // LIB_TONIC_DART_ARGS_H_
int count
Definition: FontMgrTest.cpp:50
GLenum type
DartArgIterator(Dart_NativeArguments args, int start_index=1)
Definition: dart_args.h:21
Dart_NativeArguments args() const
Definition: dart_args.h:39
bool had_exception() const
Definition: dart_args.h:37
#define C(TEST_CATEGORY)
Definition: colrv1.cpp:248
struct _Dart_Handle * Dart_Handle
Definition: dart_api.h:258
DART_EXPORT Dart_Handle Dart_GetNativeArgument(Dart_NativeArguments args, int index)
DART_EXPORT Dart_Handle Dart_ThrowException(Dart_Handle exception)
struct _Dart_NativeArguments * Dart_NativeArguments
Definition: dart_api.h:3019
DART_EXPORT Dart_Handle Dart_GetNativeFieldsOfArgument(Dart_NativeArguments args, int arg_index, int num_fields, intptr_t *field_values)
G_BEGIN_DECLS G_MODULE_EXPORT FlValue * args
GAsyncResult * result
Dart_NativeFunction function
Definition: fuchsia.cc:51
static CompileType * ResultType(Definition *call)
void DartCallStatic(Sig func, Dart_NativeArguments args)
Definition: dart_args.h:220
void DartCallConstructor(Sig func, Dart_NativeArguments args)
Definition: dart_args.h:230
void WriteDartArguments(std::ostringstream *stream)
Definition: dart_args.h:283
bool CheckAndHandleError(Dart_Handle handle)
Definition: dart_error.cc:33
bool AllowedInLeafCall()
Definition: dart_args.h:295
void WriteFfiArguments(std::ostringstream *stream)
Definition: dart_args.h:270
void DartReturn(T result, Dart_NativeArguments args)
Definition: dart_args.h:99
void DartCall(Sig func, Dart_NativeArguments args)
Definition: dart_args.h:210
#define T
Definition: precompiler.cc:65
DartArgHolder(DartArgIterator *it)
Definition: dart_args.h:94
typename std::remove_const< typename std::remove_reference< ArgType >::type >::type ValueType
Definition: dart_args.h:90
static void WriteFfiArguments(std::ostringstream *stream)
Definition: dart_args.h:383
typename DartConverter< Return >::FfiType FfiReturn
Definition: dart_args.h:354
static FfiReturn Call(DartWrappable *receiver, typename DartConverter< typename std::remove_const< typename std::remove_reference< Args >::type >::type >::FfiType... args)
Definition: dart_args.h:358
static void WriteDartArguments(std::ostringstream *stream)
Definition: dart_args.h:391
static void WriteDartArguments(std::ostringstream *stream)
Definition: dart_args.h:443
typename DartConverter< Return >::FfiType FfiReturn
Definition: dart_args.h:406
static FfiReturn Call(DartWrappable *receiver, typename DartConverter< typename std::remove_const< typename std::remove_reference< Args >::type >::type >::FfiType... args)
Definition: dart_args.h:410
static void WriteFfiArguments(std::ostringstream *stream)
Definition: dart_args.h:435
static void WriteDartArguments(std::ostringstream *stream)
Definition: dart_args.h:536
static void WriteFfiArguments(std::ostringstream *stream)
Definition: dart_args.h:528
static void Call(DartWrappable *receiver, typename DartConverter< typename std::remove_const< typename std::remove_reference< Args >::type >::type >::FfiType... args)
Definition: dart_args.h:503
static void WriteDartArguments(std::ostringstream *stream)
Definition: dart_args.h:341
typename DartConverter< Return >::FfiType FfiReturn
Definition: dart_args.h:307
static void WriteFfiArguments(std::ostringstream *stream)
Definition: dart_args.h:335
static FfiReturn Call(typename DartConverter< typename std::remove_const< typename std::remove_reference< Args >::type >::type >::FfiType... args)
Definition: dart_args.h:311
static void WriteDartArguments(std::ostringstream *stream)
Definition: dart_args.h:489
static void Call(typename DartConverter< typename std::remove_const< typename std::remove_reference< Args >::type >::type >::FfiType... args)
Definition: dart_args.h:459
static void WriteFfiArguments(std::ostringstream *stream)
Definition: dart_args.h:483
typename IndicesGenerator< count >::type type
Definition: dart_args.h:84
typename IndicesGenerator< count >::type type
Definition: dart_args.h:78
typename IndicesGenerator< count >::type type
Definition: dart_args.h:72
typename IndicesGenerator< requested_index - 1, requested_index - 1, indices... >::type type
Definition: dart_args.h:58
#define TONIC_CHECK(condition)
Definition: macros.h:23