acd16c6aa7
This is an initial cut of a tool for automatically creating shims for C/C++ programs using the entry point annotations in Dart code. The tool has two required arguments: * the .dill file containing the kernel representation of the Dart code * the base path of the header and implementation files to create With a base path of 'dir/name', the header file is created as 'dir/name.h' and the implementation file is created as 'dir/name.cc'. In addition, 'dir/name.h' is used as a basis for creating a #ifndef/#define/#endif header guard around the header contents. The created shims are specific to a single package, either * a user-specified package, provided via '-p'/'--package', or * the package of the main method If the user does not specify a package and there is no main method in the .dill file, the tool fails. Each shim takes the following arguments in order when applicable: * the isolate in which to perform the requested operation, * the instantiated type of the generic class (for invoking, setting, or getting constructors, static methods, and static fields) * the instance (for invoking, getting, or setting instance methods and fields) * the type arguments (for retrieving nullable or non-nullable instantiated types of a generic class) * the arguments (for invoking, setting, or getting constructors, methods, and fields) The generated shims: * cache the package library, types for non-generic classes, and types for generic classes instantiated with default type arguments. The cached persistent handles are cleared if any of the methods are called with a different isolate from the one used to populate the cache. * automatically handle conversions between C int64_t <=> Dart int and C double <=> Dart double. By default, shims are not created for allocation or initializing uninitialized instances. To create such shims, use the '-u' command line argument. Currently, shims are not created for methods that take optional or named arguments. To report an error if a shim cannot be created for any entry points, use the '-e' command line argument. TEST=tests/standalone/embedder_samples_test Change-Id: Ibdf3b52d900ba98038528178485f295c5868ac9d Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/410500 Reviewed-by: Ivan Inozemtsev <iinozemtsev@google.com> Commit-Queue: Tess Strickland <sstrickl@google.com>
96 lines
2.6 KiB
C++
96 lines
2.6 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 <condition_variable>
|
|
#include <iostream>
|
|
#include <mutex>
|
|
#include <queue>
|
|
#include <thread>
|
|
#include "helpers.h"
|
|
#include "include/dart_api.h"
|
|
#include "include/dart_engine.h"
|
|
#include "timer.h"
|
|
|
|
// Queue-based message handler, running on a separate thread.
|
|
class ThreadedMessageHandler {
|
|
public:
|
|
void Run() {
|
|
is_running = true;
|
|
while (is_running) {
|
|
Dart_Isolate isolate;
|
|
{
|
|
std::unique_lock notifications_lock(notifications_mutex_);
|
|
can_pop_.wait(notifications_lock);
|
|
if (notifications_.empty()) {
|
|
continue;
|
|
}
|
|
isolate = notifications_.front();
|
|
notifications_.pop();
|
|
}
|
|
DartEngine_HandleMessage(isolate);
|
|
}
|
|
}
|
|
|
|
void Notify(Dart_Isolate isolate) {
|
|
std::unique_lock notifications_lock(notifications_mutex_);
|
|
notifications_.push(isolate);
|
|
can_pop_.notify_one();
|
|
}
|
|
|
|
void Stop() {
|
|
is_running = false;
|
|
can_pop_.notify_one();
|
|
}
|
|
|
|
static void ScheduleDartMessage(Dart_Isolate isolate, void* context) {
|
|
reinterpret_cast<ThreadedMessageHandler*>(context)->Notify(isolate);
|
|
}
|
|
|
|
private:
|
|
std::queue<Dart_Isolate> notifications_;
|
|
std::condition_variable can_pop_;
|
|
std::atomic<bool> is_running;
|
|
std::mutex notifications_mutex_;
|
|
};
|
|
|
|
int main(int argc, char** argv) {
|
|
if (argc == 1) {
|
|
std::cerr << "Must specify snapshot path" << std::endl;
|
|
std::exit(1);
|
|
}
|
|
char* error = nullptr;
|
|
|
|
// Start an event loop on a separate thread and use it as a default
|
|
// scheduler.
|
|
ThreadedMessageHandler message_handler;
|
|
std::thread message_handler_thread(&ThreadedMessageHandler::Run,
|
|
&message_handler);
|
|
DartEngine_SetDefaultMessageScheduler(
|
|
{ThreadedMessageHandler::ScheduleDartMessage, &message_handler});
|
|
|
|
// Load snapshot and create an isolate
|
|
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 function to start a timer.
|
|
Call_startTimer(isolate, 1);
|
|
|
|
// Wait a bit.
|
|
std::this_thread::sleep_for(std::chrono::milliseconds(100));
|
|
|
|
// Stop the timer.
|
|
Call_stopTimer(isolate);
|
|
|
|
// Get timer value.
|
|
std::cout << "Ticks: " << Get_ticks(isolate) << std::endl;
|
|
|
|
// Stop event loop.
|
|
message_handler.Stop();
|
|
message_handler_thread.join();
|
|
|
|
DartEngine_Shutdown();
|
|
}
|