Allow specification of std::functions as native entrypoints from Dart code. (flutter/engine#8309)

This allows for the specification of std::functions (using EmbedderContext::NativeEntry) with their captures as native entrypoints. Earlier, only C functions we allowed which meant that there were no captures and assertions had to use globals which could introduce bugs when used with gtest_repeat.
This commit is contained in:
Chinmay Garde 2019-03-26 12:56:23 -07:00 committed by GitHub
parent 1ca8afa1bc
commit 07f506f752
3 changed files with 64 additions and 0 deletions

View File

@ -6,3 +6,15 @@ void customEntrypoint() {
}
void sayHiFromCustomEntrypoint() native "SayHiFromCustomEntrypoint";
@pragma('vm:entry-point')
void customEntrypoint1() {
sayHiFromCustomEntrypoint1();
sayHiFromCustomEntrypoint2();
sayHiFromCustomEntrypoint3();
}
void sayHiFromCustomEntrypoint1() native "SayHiFromCustomEntrypoint1";
void sayHiFromCustomEntrypoint2() native "SayHiFromCustomEntrypoint2";
void sayHiFromCustomEntrypoint3() native "SayHiFromCustomEntrypoint3";

View File

@ -16,11 +16,23 @@
#include "flutter/shell/platform/embedder/embedder.h"
#include "flutter/shell/platform/embedder/tests/embedder_test_resolver.h"
#define CREATE_NATIVE_ENTRY(native_entry) \
({ \
static ::shell::testing::EmbedderContext::NativeEntry closure; \
static Dart_NativeFunction entrypoint = [](Dart_NativeArguments args) { \
closure(args); \
}; \
closure = (native_entry); \
entrypoint; \
})
namespace shell {
namespace testing {
class EmbedderContext {
public:
using NativeEntry = std::function<void(Dart_NativeArguments)>;
EmbedderContext(std::string assets_path = "");
~EmbedderContext();

View File

@ -59,5 +59,45 @@ TEST_F(EmbedderTest, CanInvokeCustomEntrypoint) {
ASSERT_TRUE(engine.is_valid());
}
TEST_F(EmbedderTest, CanInvokeCustomEntrypointMacro) {
auto& context = GetEmbedderContext();
fml::AutoResetWaitableEvent latch1;
fml::AutoResetWaitableEvent latch2;
fml::AutoResetWaitableEvent latch3;
// Can be defined separately.
auto entry1 = [&latch1](Dart_NativeArguments args) {
FML_LOG(ERROR) << "In Callback 1";
latch1.Signal();
};
auto native_entry1 = CREATE_NATIVE_ENTRY(entry1);
context.AddNativeCallback("SayHiFromCustomEntrypoint1", native_entry1);
// Can be wrapped in in the args.
auto entry2 = [&latch2](Dart_NativeArguments args) {
FML_LOG(ERROR) << "In Callback 2";
latch2.Signal();
};
context.AddNativeCallback("SayHiFromCustomEntrypoint2",
CREATE_NATIVE_ENTRY(entry2));
// Everything can be inline.
context.AddNativeCallback(
"SayHiFromCustomEntrypoint3",
CREATE_NATIVE_ENTRY([&latch3](Dart_NativeArguments args) {
FML_LOG(ERROR) << "In Callback 3";
latch3.Signal();
}));
EmbedderConfigBuilder builder(context);
builder.SetDartEntrypoint("customEntrypoint1");
auto engine = builder.LaunchEngine();
latch1.Wait();
latch2.Wait();
latch3.Wait();
ASSERT_TRUE(engine.is_valid());
}
} // namespace testing
} // namespace shell