51ea42537a
Also add a sample for calling Dart functions which return/accept futures. Change-Id: I932d0577709f4e068ccd3212797751ecb347c4f9 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/408281 Commit-Queue: Ivan Inozemtsev <iinozemtsev@google.com> Reviewed-by: Martin Kustermann <kustermann@google.com>
189 lines
5.9 KiB
C++
189 lines
5.9 KiB
C++
// Copyright (c) 2025, the Dart project authors. Please see the AUTHORS file
|
|
// for details. All rights reserved. Use of this source code is governed by a
|
|
// BSD-style license that can be found in the LICENSE file.
|
|
|
|
#include <chrono>
|
|
#include <future>
|
|
#include <iostream>
|
|
#include <thread>
|
|
#include "helpers.h"
|
|
#include "include/dart_api.h"
|
|
#include "include/dart_engine.h"
|
|
|
|
void ScheduleDartMessage(Dart_Isolate isolate, void* context) {
|
|
std::ignore = std::async(DartEngine_HandleMessage, isolate);
|
|
}
|
|
|
|
void FulfillIntPromise(void* context, int64_t value) {
|
|
auto promise = reinterpret_cast<std::promise<int64_t>*>(context);
|
|
promise->set_value(value);
|
|
delete promise;
|
|
}
|
|
|
|
// Helper to call Dart function `returnRegularFutureC`.
|
|
std::future<int64_t> ReturnRegularFuture(Dart_Isolate isolate,
|
|
int64_t delay_ms,
|
|
bool use_microtask) {
|
|
auto promise = new std::promise<int64_t>();
|
|
auto result = promise->get_future();
|
|
|
|
IsolateScope isolate_scope(isolate);
|
|
DartScope dart_scope;
|
|
|
|
// args
|
|
Dart_Handle args[] = {
|
|
Dart_NewInteger(delay_ms), Dart_NewBoolean(use_microtask),
|
|
Dart_NewInteger(
|
|
reinterpret_cast<intptr_t>(&FulfillIntPromise)), // callback
|
|
Dart_NewInteger(reinterpret_cast<intptr_t>(promise)) // context
|
|
};
|
|
|
|
// call
|
|
CheckError(Dart_Invoke(Dart_RootLibrary(),
|
|
Dart_NewStringFromCString("returnRegularFutureC"), 4,
|
|
args));
|
|
CheckError(DartEngine_DrainMicrotasksQueue(), "draining microtasks queue");
|
|
|
|
return result;
|
|
}
|
|
|
|
// Helper to call Dart function `sumIntStreamC`.
|
|
std::future<int64_t> SumIntStream(Dart_Isolate isolate,
|
|
int count,
|
|
int64_t delay_ms,
|
|
bool use_async_star) {
|
|
auto promise = new std::promise<int64_t>();
|
|
auto result = promise->get_future();
|
|
|
|
IsolateScope isolate_scope(isolate);
|
|
DartScope dart_scope;
|
|
|
|
// args
|
|
Dart_Handle args[] = {
|
|
Dart_NewInteger(count), Dart_NewInteger(delay_ms),
|
|
Dart_NewBoolean(use_async_star),
|
|
Dart_NewInteger(
|
|
reinterpret_cast<intptr_t>(&FulfillIntPromise)), // callback
|
|
Dart_NewInteger(reinterpret_cast<intptr_t>(promise)) // context
|
|
};
|
|
|
|
// call
|
|
CheckError(Dart_Invoke(Dart_RootLibrary(),
|
|
Dart_NewStringFromCString("sumIntStreamC"), 5, args));
|
|
CheckError(DartEngine_DrainMicrotasksQueue(), "draining microtasks queue");
|
|
|
|
return result;
|
|
}
|
|
|
|
class AwaitAndMultiplyCall {
|
|
public:
|
|
AwaitAndMultiplyCall(Dart_Isolate isolate,
|
|
Dart_PersistentHandle handle,
|
|
std::future<int64_t>&& result)
|
|
: result(std::move(result)), isolate_(isolate), handle_(handle) {}
|
|
|
|
void CompleteA(int64_t value) {
|
|
IsolateScope isolate_scope(isolate_);
|
|
DartScope dart_scope;
|
|
|
|
Dart_Handle args[] = {Dart_NewInteger(value)};
|
|
CheckError(
|
|
Dart_Invoke(handle_, Dart_NewStringFromCString("setA"), 1, args));
|
|
CheckError(DartEngine_DrainMicrotasksQueue(), "draining microtasks queue");
|
|
}
|
|
|
|
void CompleteB(int64_t value) {
|
|
IsolateScope isolate_scope(isolate_);
|
|
DartScope dart_scope;
|
|
|
|
Dart_Handle args[] = {Dart_NewInteger(value)};
|
|
CheckError(
|
|
Dart_Invoke(handle_, Dart_NewStringFromCString("setB"), 1, args));
|
|
CheckError(DartEngine_DrainMicrotasksQueue(), "draining microtasks queue");
|
|
}
|
|
|
|
std::future<int64_t> result;
|
|
|
|
void Release() {
|
|
IsolateScope isolate_scope(isolate_);
|
|
DartScope dart_scope;
|
|
|
|
Dart_DeletePersistentHandle(handle_);
|
|
}
|
|
|
|
private:
|
|
Dart_Isolate isolate_;
|
|
Dart_PersistentHandle handle_;
|
|
};
|
|
|
|
AwaitAndMultiplyCall AwaitAndMultiply(Dart_Isolate isolate) {
|
|
auto promise = new std::promise<int64_t>();
|
|
auto future = promise->get_future();
|
|
|
|
IsolateScope isolate_scope(isolate);
|
|
DartScope dart_scope;
|
|
|
|
Dart_Handle args[] = {
|
|
Dart_NewInteger(reinterpret_cast<intptr_t>(&FulfillIntPromise)),
|
|
Dart_NewInteger(reinterpret_cast<intptr_t>(promise)),
|
|
};
|
|
Dart_PersistentHandle call_handle = Dart_NewPersistentHandle(CheckError(
|
|
Dart_Invoke(Dart_RootLibrary(),
|
|
Dart_NewStringFromCString("awaitAndMultiplyC"), 2, args)));
|
|
CheckError(DartEngine_DrainMicrotasksQueue(), "draining microtasks queue");
|
|
|
|
return AwaitAndMultiplyCall(isolate, call_handle, std::move(future));
|
|
}
|
|
|
|
int main(int argc, char** argv) {
|
|
if (argc == 1) {
|
|
std::cerr << "Must specify snapshot path" << std::endl;
|
|
std::exit(1);
|
|
}
|
|
char* error = nullptr;
|
|
|
|
//
|
|
// Set up message handling and start isolate.
|
|
//
|
|
DartEngine_MessageScheduler scheduler{ScheduleDartMessage, nullptr};
|
|
DartEngine_SetDefaultMessageScheduler(scheduler);
|
|
|
|
DartEngine_SnapshotData snapshot_data = AutoSnapshotFromFile(argv[1], &error);
|
|
CheckError(error, "reading snapshot");
|
|
Dart_Isolate isolate = DartEngine_CreateIsolate(snapshot_data, &error);
|
|
CheckError(error, "creating isolate");
|
|
|
|
//
|
|
// Call Dart functions.
|
|
//
|
|
|
|
auto result1 = ReturnRegularFuture(isolate, 5, false).get();
|
|
std::cout << "returnRegularFutureC(useMicrotask = false) returns: " << result1
|
|
<< std::endl;
|
|
|
|
auto result2 = ReturnRegularFuture(isolate, 5, true).get();
|
|
std::cout << "returnRegularFutureC(useMicrotask = true) returns: " << result2
|
|
<< std::endl;
|
|
|
|
auto result3 = SumIntStream(isolate, 5, 5, false).get();
|
|
std::cout << "sumIntStream(useAsyncStar = false) returns: " << result3
|
|
<< std::endl;
|
|
|
|
auto result4 = SumIntStream(isolate, 5, 5, true).get();
|
|
std::cout << "sumIntStream(useAsyncStar = true) returns: " << result4
|
|
<< std::endl;
|
|
|
|
auto call = AwaitAndMultiply(isolate);
|
|
std::this_thread::sleep_for(std::chrono::milliseconds(1));
|
|
call.CompleteB(5);
|
|
std::this_thread::sleep_for(std::chrono::milliseconds(1));
|
|
call.CompleteA(20);
|
|
auto result5 = call.result.get();
|
|
std::cout << "awaitAndMultiply(5, 20) = " << result5 << std::endl;
|
|
call.Release();
|
|
//
|
|
// Shutdown
|
|
//
|
|
DartEngine_Shutdown();
|
|
}
|