Skip to content

Commit c797abf

Browse files
author
Clement Skau
authored
Adds Tonic templates for Dart FFI bindings. (flutter#29405)
This change adds additional Tonic templates for automatically generating bindings for Dart FFI, as well as serialisation of the bindings. - Adds parallel FfiDispather templates to the existing DartDispatcher used for (old) native bindings. - Adds serialisation of the bindings to enable automatic conversion and verification. - Extends existing DartConverters with conversions to and from the FFI transport types. - Adds new test (ffi_native_unittest.cc) for the above. This will allow us to replace the existing native functions in e.g. dart:ui with new Dart FFI native functions.
1 parent 4a81fa3 commit c797abf

File tree

12 files changed

+1116
-44
lines changed

12 files changed

+1116
-44
lines changed

lib/ui/painting/rrect.h

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -23,10 +23,21 @@ namespace tonic {
2323

2424
template <>
2525
struct DartConverter<flutter::RRect> {
26-
static flutter::RRect FromDart(Dart_Handle handle);
27-
static flutter::RRect FromArguments(Dart_NativeArguments args,
28-
int index,
29-
Dart_Handle& exception);
26+
using NativeType = flutter::RRect;
27+
using FfiType = Dart_Handle;
28+
static constexpr const char* kFfiRepresentation = "Handle";
29+
static constexpr const char* kDartRepresentation = "Object";
30+
static constexpr bool kAllowedInLeafCall = false;
31+
32+
static NativeType FromDart(Dart_Handle handle);
33+
static NativeType FromArguments(Dart_NativeArguments args,
34+
int index,
35+
Dart_Handle& exception);
36+
37+
static NativeType FromFfi(FfiType val) { return FromDart(val); }
38+
static const char* GetFfiRepresentation() { return kFfiRepresentation; }
39+
static const char* GetDartRepresentation() { return kDartRepresentation; }
40+
static bool AllowedInLeafCall() { return kAllowedInLeafCall; }
3041
};
3142

3243
} // namespace tonic

testing/dart_fixture.cc

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,4 +74,8 @@ void DartFixture::AddNativeCallback(std::string name,
7474
native_resolver_->AddNativeCallback(std::move(name), callback);
7575
}
7676

77+
void DartFixture::AddFfiNativeCallback(std::string name, void* callback_ptr) {
78+
native_resolver_->AddFfiNativeCallback(std::move(name), callback_ptr);
79+
}
80+
7781
} // namespace flutter::testing

testing/dart_fixture.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ class DartFixture {
2929
virtual Settings CreateSettingsForFixture();
3030

3131
void AddNativeCallback(std::string name, Dart_NativeFunction callback);
32+
void AddFfiNativeCallback(std::string name, void* callback_ptr);
3233

3334
protected:
3435
void SetSnapshotsAndAssets(Settings& settings);

testing/test_dart_native_resolver.cc

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,10 @@ void TestDartNativeResolver::AddNativeCallback(std::string name,
2222
Dart_NativeFunction callback) {
2323
native_callbacks_[name] = callback;
2424
}
25+
void TestDartNativeResolver::AddFfiNativeCallback(std::string name,
26+
void* callback_ptr) {
27+
ffi_native_callbacks_[name] = callback_ptr;
28+
}
2529

2630
Dart_NativeFunction TestDartNativeResolver::ResolveCallback(
2731
std::string name) const {
@@ -33,6 +37,14 @@ Dart_NativeFunction TestDartNativeResolver::ResolveCallback(
3337
return found->second;
3438
}
3539

40+
void* TestDartNativeResolver::ResolveFfiCallback(std::string name) const {
41+
auto found = ffi_native_callbacks_.find(name);
42+
if (found == ffi_native_callbacks_.end()) {
43+
return nullptr;
44+
}
45+
return found->second;
46+
}
47+
3648
static std::mutex gIsolateResolversMutex;
3749
static std::map<Dart_Isolate, std::weak_ptr<TestDartNativeResolver>>
3850
gIsolateResolvers;
@@ -65,6 +77,25 @@ static const uint8_t* DartNativeEntrySymbolCallback(
6577
return reinterpret_cast<const uint8_t*>("¯\\_(ツ)_/¯");
6678
}
6779

80+
void* TestDartNativeResolver::FfiNativeResolver(const char* name,
81+
uintptr_t args_n) {
82+
std::scoped_lock lock(gIsolateResolversMutex);
83+
auto found = gIsolateResolvers.find(Dart_CurrentIsolate());
84+
if (found == gIsolateResolvers.end()) {
85+
FML_LOG(ERROR) << "Could not resolve native method for :" << name;
86+
return nullptr;
87+
}
88+
89+
if (auto resolver = found->second.lock()) {
90+
return resolver->ResolveFfiCallback(name);
91+
} else {
92+
gIsolateResolvers.erase(found);
93+
}
94+
95+
FML_LOG(ERROR) << "Could not resolve native method for :" << name;
96+
return nullptr;
97+
}
98+
6899
void TestDartNativeResolver::SetNativeResolverForIsolate() {
69100
FML_CHECK(!Dart_IsError(Dart_RootLibrary()));
70101
auto result = Dart_SetNativeResolver(Dart_RootLibrary(),
@@ -73,6 +104,10 @@ void TestDartNativeResolver::SetNativeResolverForIsolate() {
73104
FML_CHECK(!tonic::LogIfError(result))
74105
<< "Could not set native resolver in test.";
75106

107+
result = Dart_SetFfiNativeResolver(Dart_RootLibrary(), &FfiNativeResolver);
108+
FML_CHECK(!tonic::LogIfError(result))
109+
<< "Could not set FFI native resolver in test.";
110+
76111
std::scoped_lock lock(gIsolateResolversMutex);
77112
gIsolateResolvers[Dart_CurrentIsolate()] = shared_from_this();
78113

testing/test_dart_native_resolver.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,18 +35,22 @@ class TestDartNativeResolver
3535
~TestDartNativeResolver();
3636

3737
void AddNativeCallback(std::string name, Dart_NativeFunction callback);
38+
void AddFfiNativeCallback(std::string name, void* callback_ptr);
3839

3940
void SetNativeResolverForIsolate();
4041

4142
private:
4243
std::map<std::string, Dart_NativeFunction> native_callbacks_;
44+
std::map<std::string, void*> ffi_native_callbacks_;
4345

4446
Dart_NativeFunction ResolveCallback(std::string name) const;
47+
void* ResolveFfiCallback(std::string name) const;
4548

4649
static Dart_NativeFunction DartNativeEntryResolverCallback(
4750
Dart_Handle dart_name,
4851
int num_of_arguments,
4952
bool* auto_setup_scope);
53+
static void* FfiNativeResolver(const char* name, uintptr_t args_n);
5054

5155
FML_DISALLOW_COPY_AND_ASSIGN(TestDartNativeResolver);
5256
};

0 commit comments

Comments
 (0)