// Copyright (c) 2024, 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. // Executes `main` function from given Dart kernel binary (by default uses // compiled ./hello.dart). #include #include #include #include #include #include #include "bin/dartutils.h" #include "bin/dfe.h" #include "bin/platform.h" #include "include/dart_api.h" #include "include/dart_embedder_api.h" #include "platform/assert.h" Dart_Handle CheckHandle(Dart_Handle handle, const char* context = "unknown context") { if (Dart_IsError(handle)) { FATAL("Dart error (%s): %s", context, Dart_GetError(handle)); } return handle; } void CheckError(bool condition, const char* error, const char* context) { if (!condition) { FATAL("Dart error (%s): %s", context, error); } } void CheckError(const char* error, const char* context) { if (error != nullptr) { FATAL("Dart error (%s): %s", context, error); } } Dart_InitializeParams CreateInitializeParams() { Dart_InitializeParams params; memset(¶ms, 0, sizeof(params)); params.version = DART_INITIALIZE_PARAMS_CURRENT_VERSION; return params; } std::string GetExecutablePath() { const size_t kPathBufSize = PATH_MAX + 1; char executable_path[kPathBufSize] = {}; intptr_t path_length = dart::bin::Platform::ResolveExecutablePathInto( executable_path, kPathBufSize); CheckError(path_length > 0, "empty executable path", "ResolveExecutablePathInfo"); return std::string(executable_path, path_length); } std::string GetDefaultSnapshotPath() { std::string executable_path = GetExecutablePath(); std::string directory = executable_path.substr(0, executable_path.find_last_of("/\\")); return directory + "/gen/hello_kernel.dart.snapshot"; } std::string ReadSnapshot(std::string_view path) { std::string path_string{path}; std::ifstream source_file{path_string, std::ios::binary}; ASSERT(source_file.good()); source_file.seekg(0, source_file.end); uint64_t length = source_file.tellg(); source_file.seekg(0, source_file.beg); char* bytes = static_cast(std::malloc(length)); source_file.read(bytes, length); return std::string(bytes, length); } Dart_Handle ToDartStringList(const std::vector& values) { Dart_Handle string_type = CheckHandle(dart::bin::DartUtils::GetDartType("dart:core", "String")); Dart_Handle filler = CheckHandle(Dart_NewStringFromCString("")); Dart_Handle result = CheckHandle(Dart_NewListOfTypeFilled(string_type, filler, values.size())); for (size_t i = 0; i < values.size(); i++) { Dart_Handle element = CheckHandle(Dart_NewStringFromCString(values[i].c_str())); CheckHandle(Dart_ListSetAt(result, i, element)); } return result; } int main(int argc, char** argv) { std::string snapshot_path = argc == 1 ? GetDefaultSnapshotPath() : std::string(argv[1]); std::string snapshot_name = snapshot_path.substr(snapshot_path.find_last_of("/\\") + 1); std::string snapshot_data = ReadSnapshot(snapshot_path); std::string snapshot_uri = "file://" + snapshot_path; std::cout << "Snapshot path: " << snapshot_path << std::endl; char* error; // Start Dart VM. CheckError(dart::embedder::InitOnce(&error), error, "dart::embedder::InitOnce"); std::vector flags{}; CheckError(Dart_SetVMFlags(flags.size(), flags.data()), "Dart_SetVMFlags"); Dart_InitializeParams initialize_params = CreateInitializeParams(); CheckError(Dart_Initialize(&initialize_params), "Dart_Initialize"); dart::bin::DFE dfe; dfe.Init(); const uint8_t* platform_buffer = nullptr; intptr_t platform_buffer_size = 0; dfe.LoadPlatform(&platform_buffer, &platform_buffer_size); // Start an isolate from a platform kernel. Dart_IsolateFlags isolate_flags; Dart_CreateIsolateGroupFromKernel( /*script_uri=*/snapshot_uri.c_str(), /*name=*/snapshot_name.c_str(), /*kernel_buffer=*/platform_buffer, /*kernel_buffer_size=*/platform_buffer_size, /*flags=*/&isolate_flags, /*isolate_group_data=*/nullptr, /*isolate_data=*/nullptr, &error); CheckError(error, "Dart_CreateIsolateGroupFromKernel"); Dart_EnterScope(); CheckHandle(dart::bin::DartUtils::PrepareForScriptLoading( /*is_service_isolate=*/false, /*trace_loading=*/false), "PrepareForScriptLoading"); // Load kernel snapshot to run `main` from. Dart_Handle library = CheckHandle(Dart_LoadLibraryFromKernel( reinterpret_cast(snapshot_data.c_str()), snapshot_data.size()), "Dart_LoadLibraryFromKernel"); // Call main function with args. std::initializer_list main_args{ToDartStringList({"universe"})}; CheckHandle(Dart_Invoke(library, Dart_NewStringFromCString("main"), 1, const_cast(main_args.begin())), "Dart_Invoke('main')"); Dart_ExitScope(); Dart_ShutdownIsolate(); }