Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Embedding Dart in Your Application

Sponsored · Your Podcast. Everywhere. Effortlessly. Share. Educate. Inspire. Entertain. You do you. We'll handle the rest.
Avatar for Don Olmstead Don Olmstead
May 10, 2016
180

Embedding Dart in Your Application

Avatar for Don Olmstead

Don Olmstead

May 10, 2016

Transcript

  1. The browser is the platform HTML5 + WebGL ◦ Can

    make robust 3D applications ◦ Cross-platform ◦ Continually evolving JavaScript
  2. Demo time • Goals ◦ Provide an example on how

    to embed Dart in a native application ◦ Server ▪ Communicate between Dart and C++ ▪ Expose Websockets server ◦ Client ▪ Show real-time updates of the controller's state ▪ Control information through Websockets ▪ UI using Canvas
  3. Embedding the VM • Create Isolates ◦ Dart_CreateIsolate • Handle

    loading of libraries ◦ Dart_SetLibraryTagHandler • Read source code ◦ Resolve uri ◦ Load file from location • Invoke main method ◦ Dart_Invoke
  4. Isolate creation Isolate* Isolate::createIsolate(const char* scriptUri, const char* main, bool

    resolveScript, void* data, char** error) { Dart_Isolate isolate = Dart_CreateIsolate(scriptUri, main, snapshot_buffer, data, error); if (isolate) { Dart_SetLibraryTagHandler(__libraryTagHandler); Dart_Handle uriLibrary = __uriLibrary->load(); // Setup URI library Dart_Handle coreLibrary = __coreLibrary->load(); // Setup core builtin library Dart_Handle ioLibrary = __ioLibrary->load(); // Setup IO library Dart_Handle library = __loadScript(scriptUri, resolveScript, coreLibrary); // Load the script into the isolate Dart_LibraryImportLibrary(library, coreLibrary); // Implicitly import the core library return new Isolate(isolate, library, static_cast<Isolate*>(data)); } return 0; }
  5. Complications with embedding • Built in library sources not easily

    accessible ◦ Have to modify code to access source ◦ Easier to just use a snapshot ▪ Also not intuitive to get at • Core library has to be imported into the isolate ◦ Dart_LibraryImportLibrary
  6. Extending the VM • Create a native resolver ◦ Dart_SetNativeResolver

    ◦ Links string names to native functions • Provide linkage between Dart object and C/C++ object ◦ Handle creation/destruction • Write Dart code that wraps the native code • Respond to calls from Dart
  7. A native resolver Dart_NativeFunction Builtin::NativeLookup(Dart_Handle name, int argument_count) { const

    char* function_name = NULL; Dart_Handle result = Dart_StringToCString(name, &function_name); int num_entries = sizeof(BuiltinEntries) / sizeof(struct NativeEntries); for (int i = 0; i < num_entries; i++) { struct NativeEntries* entry = &(BuiltinEntries[i]); if (!strcmp(function_name, entry->name_)) { return (entry->argument_count_ == argument_count) ? reinterpret_cast<Dart_NativeFunction>(entry->function_) : NULL; } } return NULL; }
  8. The Dart side #library('embed:input'); #import('dart:nativewrappers'); class GamePadState extends NativeFieldWrapperClass1 {

    GamePadState() { _initialize(); } void _initialize() native 'GamePadState_New'; bool get isConnected() native 'GamePadState_IsConnected'; double get leftThumbstickX() native 'GamePadState_GetLeftThumbstickX'; double get leftThumbstickY() native 'GamePadState_GetLeftThumbstickY'; double get rightThumbstickX() native 'GamePadState_GetRightThumbstickX'; double get rightThumbstickY() native 'GamePadState_GetRightThumbstickY'; double get leftTrigger() native 'GamePadState_GetLeftTrigger'; double get rightTrigger() native 'GamePadState_GetRightTrigger'; int get buttons() native 'GamePadState_GetButtons'; }
  9. The C++ side (instance lifetime) void GamePadState_New(Dart_NativeArguments args) { Dart_Handle

    instance = Dart_GetNativeArgument(args, 0); GamePadState* state = new GamePadState(); Dart_SetNativeInstanceField(instance, 0, reinterpret_cast<intptr_t>(state)); Dart_NewWeakPersistentHandle(instance, state, GamePadState_Delete); } void GamePadState_Delete(Dart_Handle handle, void* data) { GamePadState* state = static_cast<GamePadState*>(data); delete state; }
  10. The C++ side (using) template <typename T> void getNativeField(Dart_NativeArguments args,

    int index, T** value) { Dart_Handle handle = Dart_GetNativeArgument(args, index); std::intptr_t ptr; Dart_GetNativeInstanceField(handle, 0, &ptr); *value = reinterpret_cast<T*>(ptr); } void GamePadState_IsConnected(Dart_NativeArguments args) { GamePadState* state = 0; getNativeField(args, 0, &state); Dart_SetReturnValue(args, Dart_NewBoolean(state->isConnected())); }
  11. Improving the experience • Move functionality into an auxiliary library

    ◦ Simplify the embedding experience • Handle common cases ◦ Allow easy loading of built in libraries ◦ Provide a simple way to link in native functions • Create a binding library
  12. Thanks for listening! Don Olmstead @don_olmstead +Don Olmstead http://donolmstead.me Code

    available on Github https://github.com/donny-dont/DartEmbeddingDemo