├── .gitignore ├── CMakeLists.txt ├── README.md ├── helloworld.dart └── src ├── dart.cc ├── dart.h ├── isolate.cc ├── isolate.h ├── library.cc ├── library.h ├── main.cc └── scoped_ptr.h /.gitignore: -------------------------------------------------------------------------------- 1 | # Compiled Object files 2 | *.slo 3 | *.lo 4 | *.o 5 | 6 | # Compiled Dynamic libraries 7 | *.so 8 | 9 | # Compiled Static libraries 10 | *.lai 11 | *.la 12 | *.a 13 | 14 | # cmake 15 | CMakeCache.txt 16 | cmake_install.cmake 17 | Makefile 18 | CMakeFiles 19 | 20 | bin 21 | 22 | tags 23 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 2.8) 2 | project(embed-dart-vm) 3 | 4 | set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${PROJECT_SOURCE_DIR}/bin) 5 | set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${PROJECT_SOURCE_DIR}/lib) 6 | set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${PROJECT_SOURCE_DIR}/lib) 7 | 8 | set(CMAKE_CXX_FLAGS "-Wall -Werror") 9 | set(CMAKE_CXX_FLAGS_DEBUG "-DDEBUG -g") 10 | set(CMAKE_CXX_FLAGS_RELEASE "-DNDEBUG -Os") 11 | set(DART_SDK_ROOT ~/git/dart/dart) 12 | set(DART_SDK_GEN ${DART_SDK_ROOT}/xcodebuild/DerivedSources/${CMAKE_BUILD_TYPE}) 13 | 14 | # needed for dart_vm_gen 15 | include_directories(${DART_SDK_ROOT}/runtime) 16 | include_directories(${DART_SDK_ROOT}/runtime/include) 17 | link_directories(${DART_SDK_ROOT}/xcodebuild/${CMAKE_BUILD_TYPE}) 18 | 19 | add_library(dart_vm_gen 20 | ${DART_SDK_GEN}/builtin_gen.cc 21 | ${DART_SDK_GEN}/corelib_gen.cc 22 | ${DART_SDK_GEN}/corelib_impl_gen.cc 23 | ${DART_SDK_GEN}/crypto_gen.cc 24 | ${DART_SDK_GEN}/io_gen.cc 25 | ${DART_SDK_GEN}/json_gen.cc 26 | ${DART_SDK_GEN}/snapshot_gen.cc 27 | ${DART_SDK_GEN}/uri_gen.cc 28 | ${DART_SDK_GEN}/utf_gen.cc) 29 | 30 | add_library(embed_dart_vm 31 | src/dart.cc 32 | src/isolate.cc 33 | src/library.cc 34 | ${DART_SDK_ROOT}/runtime/bin/builtin.cc 35 | ${DART_SDK_ROOT}/runtime/bin/gen_snapshot.cc) 36 | 37 | add_executable(embed-dart-vm_a src/main.cc) 38 | target_link_libraries(embed-dart-vm_a 39 | embed_dart_vm 40 | dart_builtin 41 | dart_export 42 | dart_lib_withcore 43 | dart_vm 44 | dart_vm_gen 45 | double_conversion 46 | jscre) 47 | 48 | add_executable(embed-dart-vm_b src/main.cc) 49 | target_link_libraries(embed-dart-vm_b 50 | embed_dart_vm 51 | dart_builtin 52 | dart_export 53 | dart_lib 54 | dart_vm 55 | dart_vm_gen 56 | double_conversion 57 | jscre) 58 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # This repo has been discontinued 2 | 3 | For details about embedding the Dart VM as a library into another application, 4 | see the [Dart Embedding API][`include/dart_api.h`]. 5 | 6 | For examples of how to use the Dart Embedding API, see 7 | [these examples maintained by the community][examples]. 8 | 9 | [`include/dart_api.h`]: https://github.com/dart-lang/sdk/blob/main/runtime/include/dart_api.h 10 | [examples]: https://github.com/fuzzybinary/dart-embedding-example 11 | -------------------------------------------------------------------------------- /helloworld.dart: -------------------------------------------------------------------------------- 1 | #library('helloworld'); 2 | 3 | void main() { 4 | print("hello world"); 5 | } 6 | -------------------------------------------------------------------------------- /src/dart.cc: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | 5 | #include "isolate.h" 6 | #include "library.h" 7 | 8 | extern const uint8_t* snapshot_buffer; 9 | 10 | namespace dart { 11 | 12 | Dart_Handle LibraryTagHandler(Dart_LibraryTag tag, 13 | Dart_Handle library, 14 | Dart_Handle url) { 15 | const char* url_str = NULL; 16 | Dart_Handle result = Dart_StringToCString(url, &url_str); 17 | if (Dart_IsError(result)) 18 | return result; 19 | assert(false); // TODO: implement. 20 | } 21 | 22 | Dart_Handle ResolveScript(const char* script, Dart_Handle core_library) { 23 | char* cwd = getcwd(NULL, 0); 24 | Dart_Handle args[3] = { 25 | Dart_NewString(cwd), 26 | Dart_NewString(script), 27 | Dart_True() // TODO: should this be true or false? 28 | }; 29 | Dart_Handle ret = Dart_Invoke( 30 | core_library, Dart_NewString("_resolveScriptUri"), 3, args); 31 | free(cwd); 32 | return ret; 33 | } 34 | 35 | Dart_Handle FilePathFromUri(Dart_Handle script, Dart_Handle core_library) { 36 | Dart_Handle args[2] = { 37 | script, 38 | Dart_True() // TODO: should this be true or false? 39 | }; 40 | return Dart_Invoke(core_library, Dart_NewString("_filePathFromUri"), 2, args); 41 | } 42 | 43 | Dart_Handle ReadSource(Dart_Handle script, Dart_Handle core_library) { 44 | Dart_Handle script_path = FilePathFromUri(script, core_library); 45 | if (Dart_IsError(script_path)) 46 | return script_path; 47 | 48 | const char* script_path_str; 49 | Dart_StringToCString(script_path, &script_path_str); 50 | 51 | FILE* file = fopen(script_path_str, "r"); 52 | if (file == NULL) 53 | return Dart_Error("Unable to read file '%s'", script_path_str); 54 | 55 | fseek(file, 0, SEEK_END); 56 | long length = ftell(file); 57 | fseek(file, 0, SEEK_SET); 58 | 59 | char* buffer = new char[length + 1]; 60 | size_t read = fread(buffer, 1, length, file); 61 | fclose(file); 62 | buffer[read] = '\0'; 63 | 64 | Dart_Handle source = Dart_NewString(buffer); 65 | 66 | delete[] buffer; 67 | 68 | return source; 69 | } 70 | 71 | Dart_Handle LoadScript(const char* script, 72 | bool resolve, 73 | Dart_Handle core_library) { 74 | std::cout << __FUNCTION__ << ": " << script << ", " << resolve << std::endl; 75 | Dart_Handle resolved_script; 76 | 77 | if (resolve) { 78 | resolved_script = ResolveScript(script, core_library); 79 | if (Dart_IsError(resolved_script)) 80 | return resolved_script; 81 | } else { 82 | resolved_script = Dart_NewString(script); 83 | } 84 | 85 | Dart_Handle source = ReadSource(resolved_script, core_library); 86 | if (Dart_IsError(source)) 87 | return source; 88 | 89 | return Dart_LoadScript(resolved_script, source); 90 | } 91 | 92 | Isolate* CreateIsolate(const char* script, const char* main, bool resolve, 93 | void* data, char** error) { 94 | std::cout << __FUNCTION__ << ": " << script << ", " << main << ", " 95 | << resolve << std::endl; 96 | Dart_Isolate isolate = Dart_CreateIsolate(script, main, snapshot_buffer, 97 | NULL, error); 98 | assert(isolate); 99 | 100 | std::cout << "Created isolate" << std::endl; 101 | Dart_EnterScope(); 102 | 103 | Dart_Handle result = Dart_SetLibraryTagHandler(LibraryTagHandler); 104 | 105 | if (Dart_IsError(result)) { 106 | *error = strdup(Dart_GetError(result)); 107 | Dart_ExitScope(); 108 | Dart_ShutdownIsolate(); 109 | return NULL; 110 | } 111 | 112 | // Set up uri library. 113 | Dart_Handle uri_library = Isolate::uri_library->Load(); 114 | if (Dart_IsError(uri_library)) { 115 | *error = strdup(Dart_GetError(result)); 116 | Dart_ExitScope(); 117 | Dart_ShutdownIsolate(); 118 | return NULL; 119 | } 120 | 121 | // Set up core library. 122 | Dart_Handle core_library = Isolate::core_library->Load(); 123 | if (Dart_IsError(core_library)) { 124 | *error = strdup(Dart_GetError(result)); 125 | Dart_ExitScope(); 126 | Dart_ShutdownIsolate(); 127 | return NULL; 128 | } 129 | 130 | // Set up io library. 131 | Dart_Handle io_library = Isolate::io_library->Load(); 132 | if (Dart_IsError(io_library)) { 133 | *error = strdup(Dart_GetError(result)); 134 | Dart_ExitScope(); 135 | Dart_ShutdownIsolate(); 136 | return NULL; 137 | } 138 | std::cout << "Loaded builtin libraries" << std::endl; 139 | 140 | std::cout << "About to load " << script << std::endl; 141 | Dart_Handle library = LoadScript(script, true, core_library); 142 | 143 | if (Dart_IsError(library)) { 144 | *error = strdup(Dart_GetError(library)); 145 | Dart_ExitScope(); 146 | Dart_ShutdownIsolate(); 147 | return NULL; 148 | } 149 | 150 | result = Dart_LibraryImportLibrary(library, core_library, Dart_Null()); 151 | 152 | if (Dart_IsError(library)) { 153 | *error = strdup(Dart_GetError(library)); 154 | Dart_ExitScope(); 155 | Dart_ShutdownIsolate(); 156 | return NULL; 157 | } 158 | 159 | return new Isolate(isolate, library); 160 | } 161 | 162 | bool IsolateCreateCallback(const char* script_uri, 163 | const char* main, 164 | void* callback_data, 165 | char** error) { 166 | Isolate* isolate = CreateIsolate(script_uri, main, true, NULL, error); 167 | if (isolate == NULL) { 168 | std::cerr << "Failed to create Isolate: " << script_uri << "|" << main 169 | << ": " << error << std::endl; 170 | } 171 | return isolate != NULL; 172 | } 173 | 174 | bool IsolateInterruptCallback() { 175 | return true; 176 | } 177 | 178 | void IsolateShutdownCallback(void* callback_data) { 179 | } 180 | 181 | // public 182 | void Initialize(int argc, const char* argv[]) { 183 | Dart_SetVMFlags(argc, argv); 184 | assert(Dart_Initialize(IsolateCreateCallback, 185 | IsolateInterruptCallback, 186 | IsolateShutdownCallback)); 187 | 188 | Isolate::InitializeBuiltinLibraries(); 189 | } 190 | 191 | // public 192 | void Shutdown() { 193 | Isolate::ShutdownBuiltinLibraries(); 194 | } 195 | 196 | // public 197 | Isolate* LoadScript(const char* script) { 198 | std::cout << __FUNCTION__ << ": " << script << std::endl; 199 | char* error = NULL; 200 | Isolate* isolate = CreateIsolate(script, "main", true, NULL, &error); 201 | if (!isolate) 202 | std::cerr << "Failed to create Isolate: " << std::endl 203 | << " " << error << std::endl; 204 | return isolate; 205 | } 206 | 207 | } 208 | 209 | -------------------------------------------------------------------------------- /src/dart.h: -------------------------------------------------------------------------------- 1 | namespace dart { 2 | class Isolate; 3 | 4 | void Initialize(int argc, const char* argv[]); 5 | void Shutdown(); 6 | Isolate* LoadScript(const char* script); 7 | } 8 | -------------------------------------------------------------------------------- /src/isolate.cc: -------------------------------------------------------------------------------- 1 | #include "isolate.h" 2 | #include "library.h" 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | #define BUILTIN_FUNCTION_NAME(name) Builtin_##name 9 | #define DECLARE_BUILTIN_FUNCTION(name) \ 10 | extern void BUILTIN_FUNCTION_NAME(name)(Dart_NativeArguments args) 11 | 12 | DECLARE_BUILTIN_FUNCTION(Exit); 13 | DECLARE_BUILTIN_FUNCTION(Logger_PrintString); 14 | 15 | namespace dart { 16 | namespace { 17 | 18 | typedef std::map NativeFunctionMap; 19 | 20 | NativeFunctionMap core_native_function_map; 21 | NativeFunctionMap io_native_function_map; 22 | 23 | template 24 | Dart_NativeFunction LibraryResolver(Dart_Handle name, int arg_count) { 25 | const char* native_function_name = 0; 26 | Dart_StringToCString(name, &native_function_name); 27 | NativeFunctionMap::const_iterator func_it = 28 | function_map.find(native_function_name); 29 | if (func_it != function_map.end()) 30 | return func_it->second; 31 | std::cout << "WARNING: " << native_function_name << " is unresolved." 32 | << std::endl; 33 | return NULL; 34 | } 35 | 36 | Library* CreateCoreLibrary() { 37 | core_native_function_map.insert( 38 | std::make_pair("Exit", BUILTIN_FUNCTION_NAME(Exit))); 39 | core_native_function_map.insert( 40 | std::make_pair("Logger_PrintString", 41 | BUILTIN_FUNCTION_NAME(Logger_PrintString))); 42 | return new Library("dart:builtin", 43 | NULL, 44 | LibraryResolver, 45 | NULL); 46 | } 47 | 48 | void IOLibraryInitializer(Dart_Handle library) { 49 | Dart_Handle timer_closure = 50 | Dart_Invoke(library, Dart_NewString("_getTimerFactoryClosure"), 0, 0); 51 | Dart_Handle isolate_library = 52 | Dart_LookupLibrary(Dart_NewString("dart:isolate")); 53 | 54 | Dart_Handle args[1]; 55 | args[0] = timer_closure; 56 | Dart_Handle result = Dart_Invoke(isolate_library, 57 | Dart_NewString("_setTimerFactoryClosure"), 58 | 1, 59 | args); 60 | assert(!Dart_IsError(result)); 61 | } 62 | 63 | Library* CreateIOLibrary() { 64 | // TODO: register any native methods. 65 | return new Library("dart:io", 0, LibraryResolver, 66 | IOLibraryInitializer); 67 | } 68 | 69 | Library* CreateUriLibrary() { 70 | return new Library("dart:uri", NULL, NULL, NULL); 71 | } 72 | 73 | } 74 | 75 | // static 76 | Library* Isolate::core_library = NULL; 77 | 78 | // static 79 | Library* Isolate::io_library = NULL; 80 | 81 | // static 82 | Library* Isolate::uri_library = NULL; 83 | 84 | // static 85 | void Isolate::InitializeBuiltinLibraries() { 86 | assert(core_library == NULL); 87 | core_library = CreateCoreLibrary(); 88 | io_library = CreateIOLibrary(); 89 | uri_library = CreateUriLibrary(); 90 | } 91 | 92 | // static 93 | void Isolate::ShutdownBuiltinLibraries() { 94 | assert(core_library != NULL); 95 | delete uri_library; 96 | delete io_library; 97 | delete core_library; 98 | } 99 | 100 | void Isolate::Invoke(const char* function) { 101 | std::cout << __FUNCTION__ << ": " << function << std::endl; 102 | Dart_EnterScope(); 103 | Dart_Handle result = Dart_Invoke(library_, 104 | Dart_NewString(function), 105 | 0, 106 | NULL); 107 | if (Dart_IsError(result)) { 108 | std::cerr << "Failed to invoke " << function << ": " 109 | << Dart_GetError(result); 110 | } 111 | Dart_RunLoop(); 112 | Dart_ExitScope(); 113 | } 114 | 115 | } 116 | -------------------------------------------------------------------------------- /src/isolate.h: -------------------------------------------------------------------------------- 1 | #include "dart_api.h" 2 | 3 | namespace dart { 4 | 5 | class Library; 6 | 7 | class Isolate { 8 | public: 9 | Isolate(Dart_Isolate isolate, Dart_Handle library) 10 | : isolate_(isolate), 11 | library_(library) { 12 | } 13 | 14 | static void InitializeBuiltinLibraries(); 15 | static void ShutdownBuiltinLibraries(); 16 | 17 | static Library* core_library; 18 | static Library* uri_library; 19 | static Library* io_library; 20 | 21 | void Invoke(const char* function); 22 | private: 23 | Dart_Isolate isolate_; 24 | Dart_Handle library_; 25 | }; 26 | 27 | } 28 | -------------------------------------------------------------------------------- /src/library.cc: -------------------------------------------------------------------------------- 1 | #include "library.h" 2 | 3 | namespace dart { 4 | 5 | Library::Library(const char* name, const char* source, 6 | Dart_NativeEntryResolver native_resolver, 7 | Dart_LibraryInitializer initializer) 8 | : name_(name), 9 | source_(source), 10 | native_resolver_(native_resolver), 11 | initializer_(initializer) { 12 | } 13 | 14 | Dart_Handle Library::Load() { 15 | Dart_Handle url = Dart_NewString(name_); 16 | Dart_Handle library = Dart_LookupLibrary(url); 17 | 18 | if (Dart_IsError(library)) 19 | library = Dart_LoadLibrary(url, Dart_NewString(source_)); 20 | 21 | if (Dart_IsError(library)) { 22 | std::cerr << "Failed to load library: " << name_ << "|" << source_ 23 | << ": " << Dart_GetError(library) << std::endl; 24 | return library; 25 | } 26 | 27 | if (native_resolver_ != NULL) 28 | Dart_SetNativeResolver(library, native_resolver_); 29 | if (initializer_ != NULL) 30 | initializer_(library); 31 | 32 | return library; 33 | } 34 | 35 | } 36 | -------------------------------------------------------------------------------- /src/library.h: -------------------------------------------------------------------------------- 1 | #include "dart_api.h" 2 | #include 3 | 4 | typedef void (*Dart_LibraryInitializer)(Dart_Handle library); 5 | 6 | namespace dart { 7 | 8 | class Library { 9 | public: 10 | Library(const char* name, const char* source, 11 | Dart_NativeEntryResolver native_resolver, 12 | Dart_LibraryInitializer initializer); 13 | 14 | Dart_Handle Load(); 15 | 16 | private: 17 | const char* name_; 18 | const char* source_; 19 | Dart_NativeEntryResolver native_resolver_; 20 | Dart_LibraryInitializer initializer_; 21 | }; 22 | 23 | } 24 | -------------------------------------------------------------------------------- /src/main.cc: -------------------------------------------------------------------------------- 1 | #include "dart.h" 2 | #include "isolate.h" 3 | #include "scoped_ptr.h" 4 | 5 | #include 6 | 7 | int main(int argc, const char* argv[]) { 8 | dart::Initialize(argc, argv); 9 | std::cout << "Dart Initialized" << std::endl; 10 | 11 | scoped_ptr isolate(dart::LoadScript("helloworld.dart")); 12 | assert(!!isolate); 13 | std::cout << "Script loaded into " << isolate.get() << std::endl; 14 | 15 | std::cout << "Invoking 'main'" << std::endl; 16 | isolate->Invoke("main"); 17 | std::cout << "Done" << std::endl; 18 | 19 | return 0; 20 | } 21 | -------------------------------------------------------------------------------- /src/scoped_ptr.h: -------------------------------------------------------------------------------- 1 | template 2 | class scoped_ptr { 3 | public: 4 | explicit scoped_ptr(T* ptr) : ptr_(ptr) {} 5 | ~scoped_ptr() { delete ptr_; ptr_ = NULL; } 6 | 7 | T* get() const { return ptr_; } 8 | T* operator->() const { return get(); } 9 | bool operator!() const { return get() == NULL; } 10 | private: 11 | T* ptr_; 12 | }; 13 | 14 | 15 | --------------------------------------------------------------------------------