Flutter Engine
dart_wrappable.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_WRAPPABLE_H_
6 #define LIB_TONIC_DART_WRAPPABLE_H_
7 
8 #include "third_party/dart/runtime/include/dart_api.h"
9 #include "tonic/common/macros.h"
11 #include "tonic/dart_state.h"
14 
15 #include <type_traits>
16 
17 namespace tonic {
18 
19 // DartWrappable is a base class that you can inherit from in order to be
20 // exposed to Dart code as an interface.
22  public:
24  kPeerIndex, // Must be first to work with Dart_GetNativeReceiver.
27  };
28 
29  DartWrappable() : dart_wrapper_(nullptr) {}
30 
31  // Subclasses that wish to expose a new interface must override this function
32  // and provide information about their wrapper. There is no need to call your
33  // base class's implementation of this function.
34  // Implement using IMPLEMENT_WRAPPERTYPEINFO macro
35  virtual const DartWrapperInfo& GetDartWrapperInfo() const = 0;
36 
37  // Override this to customize the object size reported to the Dart garbage
38  // collector.
39  // Implement using IMPLEMENT_WRAPPERTYPEINFO macro
40  virtual size_t GetAllocationSize() const;
41 
42  virtual void RetainDartWrappableReference() const = 0;
43 
44  virtual void ReleaseDartWrappableReference() const = 0;
45 
46  // Use this method sparingly. It follows a slower path using Dart_New.
47  // Prefer constructing the object in Dart code and using
48  // AssociateWithDartWrapper.
49  Dart_Handle CreateDartWrapper(DartState* dart_state);
50  void AssociateWithDartWrapper(Dart_Handle wrappable);
51  void ClearDartWrapper(); // Warning: Might delete this.
52  Dart_WeakPersistentHandle dart_wrapper() const { return dart_wrapper_; }
53 
54  protected:
55  virtual ~DartWrappable();
56 
57  static Dart_PersistentHandle GetTypeForWrapper(
58  tonic::DartState* dart_state,
59  const tonic::DartWrapperInfo& wrapper_info);
60 
61  private:
62  static void FinalizeDartWrapper(void* isolate_callback_data,
63  Dart_WeakPersistentHandle wrapper,
64  void* peer);
65 
66  Dart_WeakPersistentHandle dart_wrapper_;
67 
68  TONIC_DISALLOW_COPY_AND_ASSIGN(DartWrappable);
69 };
70 
71 #define DEFINE_WRAPPERTYPEINFO() \
72  public: \
73  const tonic::DartWrapperInfo& GetDartWrapperInfo() const override { \
74  return dart_wrapper_info_; \
75  } \
76  static Dart_PersistentHandle GetDartType(tonic::DartState* dart_state) { \
77  return GetTypeForWrapper(dart_state, dart_wrapper_info_); \
78  } \
79  \
80  private: \
81  static const tonic::DartWrapperInfo& dart_wrapper_info_
82 
83 #define IMPLEMENT_WRAPPERTYPEINFO(LibraryName, ClassName) \
84  static const tonic::DartWrapperInfo \
85  kDartWrapperInfo_##LibraryName_##ClassName = { \
86  #LibraryName, \
87  #ClassName, \
88  sizeof(ClassName), \
89  }; \
90  const tonic::DartWrapperInfo& ClassName::dart_wrapper_info_ = \
91  kDartWrapperInfo_##LibraryName_##ClassName;
92 
94  static DartWrappable* FromDart(Dart_Handle handle);
95  static DartWrappable* FromArguments(Dart_NativeArguments args,
96  int index,
97  Dart_Handle& exception);
98 };
99 
100 template <typename T>
102  T*,
103  typename std::enable_if<
105  static Dart_Handle ToDart(DartWrappable* val) {
106  if (!val)
107  return Dart_Null();
108  if (Dart_WeakPersistentHandle wrapper = val->dart_wrapper())
109  return Dart_HandleFromWeakPersistent(wrapper);
110  return val->CreateDartWrapper(DartState::Current());
111  }
112 
113  static void SetReturnValue(Dart_NativeArguments args,
114  DartWrappable* val,
115  bool auto_scope = true) {
116  if (!val)
117  Dart_SetReturnValue(args, Dart_Null());
118  else if (Dart_WeakPersistentHandle wrapper = val->dart_wrapper())
119  Dart_SetWeakHandleReturnValue(args, wrapper);
120  else
121  Dart_SetReturnValue(args, val->CreateDartWrapper(DartState::Current()));
122  }
123 
124  static T* FromDart(Dart_Handle handle) {
125  // TODO(abarth): We're missing a type check.
126  return static_cast<T*>(DartConverterWrappable::FromDart(handle));
127  }
128 
129  static T* FromArguments(Dart_NativeArguments args,
130  int index,
131  Dart_Handle& exception,
132  bool auto_scope = true) {
133  // TODO(abarth): We're missing a type check.
134  return static_cast<T*>(
135  DartConverterWrappable::FromArguments(args, index, exception));
136  }
137 };
138 
139 ////////////////////////////////////////////////////////////////////////////////
140 // Support for generic smart pointers that have a "get" method that returns a
141 // pointer to a type that is Dart convertible as well as a constructor that
142 // adopts a raw pointer to that type.
143 
144 template <template <typename T> class PTR, typename T>
145 struct DartConverter<PTR<T>> {
146  static Dart_Handle ToDart(const PTR<T>& val) {
147  return DartConverter<T*>::ToDart(val.get());
148  }
149 
150  static PTR<T> FromDart(Dart_Handle handle) {
151  return DartConverter<T*>::FromDart(handle);
152  }
153 
154  static PTR<T> FromArguments(Dart_NativeArguments args,
155  int index,
156  Dart_Handle& exception,
157  bool auto_scope = true) {
158  return PTR<T>(
159  DartConverter<T*>::FromArguments(args, index, exception, auto_scope));
160  }
161 
162  static void SetReturnValue(Dart_NativeArguments args,
163  const PTR<T>& val,
164  bool auto_scope = true) {
165  DartConverter<T*>::SetReturnValue(args, val.get());
166  }
167 };
168 
169 template <typename T>
170 inline T* GetReceiver(Dart_NativeArguments args) {
171  intptr_t receiver;
172  Dart_Handle result = Dart_GetNativeReceiver(args, &receiver);
173  TONIC_DCHECK(!Dart_IsError(result));
174  if (!receiver)
175  Dart_ThrowException(ToDart("Object has been disposed."));
176  return static_cast<T*>(reinterpret_cast<DartWrappable*>(receiver));
177 }
178 
179 } // namespace tonic
180 
181 #endif // LIB_TONIC_DART_WRAPPABLE_H_
G_BEGIN_DECLS FlValue * args
static PTR< T > FromDart(Dart_Handle handle)
static DartWrappable * FromArguments(Dart_NativeArguments args, int index, Dart_Handle &exception)
virtual const DartWrapperInfo & GetDartWrapperInfo() const =0
static Dart_Handle ToDart(const PTR< T > &val)
static void SetReturnValue(Dart_NativeArguments args, DartWrappable *val, bool auto_scope=true)
#define TONIC_DCHECK
Definition: macros.h:32
virtual void RetainDartWrappableReference() const =0
static DartState * Current()
Definition: dart_state.cc:55
uint8_t value
void AssociateWithDartWrapper(Dart_Handle wrappable)
virtual size_t GetAllocationSize() const
static Dart_PersistentHandle GetTypeForWrapper(tonic::DartState *dart_state, const tonic::DartWrapperInfo &wrapper_info)
static DartWrappable * FromDart(Dart_Handle handle)
Dart_Handle CreateDartWrapper(DartState *dart_state)
T * GetReceiver(Dart_NativeArguments args)
Dart_Handle ToDart(const T &object)
static T * FromArguments(Dart_NativeArguments args, int index, Dart_Handle &exception, bool auto_scope=true)
static PTR< T > FromArguments(Dart_NativeArguments args, int index, Dart_Handle &exception, bool auto_scope=true)
static void SetReturnValue(Dart_NativeArguments args, const PTR< T > &val, bool auto_scope=true)
Dart_WeakPersistentHandle dart_wrapper() const
virtual void ReleaseDartWrappableReference() const =0