Writing a minimal native extension

We'll start by writing a very simple extension with just one function that takes Dart's String object as an argument and returns another String object with characters in a reverse order. Let's start by defining the two mandatory C functions, as we mentioned earlier.

The implementation here is based on the official example from https://github.com/dart-lang/bleeding_edge/blob/master/dart/samples/sample_extension/sample_extension.cc:

// Header files are part of Dart SDK.
#include "include/dart_native_api.h"
#include "include/dart_api.h"

Dart_NativeFunction ResolveName(Dart_Handle name,
                                int argc,
                                bool* auto_setup_scope) {

DART_EXPORT Dart_Handle fuzzy_search_Init(
        Dart_Handle parent_library) {
    if (Dart_IsError(parent_library)) {
        return parent_library;
    }
    // Register handler that is called every
    // time Dart's "native" keyword is used.
    Dart_Handle result_code = Dart_SetNativeResolver(
        parent_library, ResolveName, NULL);
    if (Dart_IsError(result_code)) {
        return result_code;
    }
    return Dart_Null();
}
// Raise a Dart exception if Dart_Handle contains an error value.
Dart_Handle HandleError(Dart_Handle handle) {
    if (Dart_IsError(handle)) {
        Dart_PropagateError(handle);
    }
    return handle;
}

void Hello(Dart_NativeArguments arguments) { /* ... */ }

Dart_NativeFunction ResolveName(Dart_Handle name,
                                int argc,
                                bool* auto_setup_scope) {
    if (!Dart_IsString(name)) return NULL;

    Dart_NativeFunction result = NULL;
    if (auto_setup_scope == NULL) return NULL;
    
    Dart_EnterScope();
    // Convert Dart's String object to C char array.
    const char* cname;
    HandleError(Dart_StringToCString(name, &cname));
    // Return reference to Hello() function from this extension.
    if (strcmp("Hello", cname) == 0) {
        result = Hello;
    }
    Dart_ExitScope();
    return result;
}

We also defined a HandleError() helper function that checks Dart's internal Dart_Handle structure for an error and lets us throw a Dart exception that can be properly handled with a try-catch in Dart. The Dart_Handle structure represents all values in Dart. Every time we pass values from Dart or return values to Dart, we need to wrap them as Dart_Handle structures (for example, we had to unwrap Dart's String to char* with Dart_StringToCString()).

The Dart code loads the extension and maps the _hello() function to Hello() in the extension:

// Use dart-ext to load the native extension.
// Native extension must be libfuzzy_search.[dll, so, dylib].
import 'dart-ext:fuzzy_search';
String _hello(String str) native "Hello";

main() {
  print(_hello());
}

The native keyword makes the Dart VM call ResolveName(), which returns a reference to the Hello() function. The last thing is to implement Hello():

char* reverse(const char* s) {
    int length = strlen(s);
    char* reverse = (char*)malloc(sizeof(char) * (length + 1));
    for (int i = 0; i < length; i++) {
        reverse[i] = s[length - 1 - i];
    }
    reverse[length] = '';
    return reverse;
}

void Hello(Dart_NativeArguments arguments) {
    Dart_EnterScope();
    const char* inputStr;
    char* reverseStr;
    Dart_StringToCString(
        Dart_GetNativeArgument(arguments, 0), &inputStr);
    reverseStr = reverse(inputStr);
    
    Dart_Handle result = Dart_NewStringFromCString(reverseStr);
    free(reverseStr);
    Dart_SetReturnValue(arguments, result);
    Dart_ExitScope();
}

We used the Dart_StringToCString()function to convert Dart's representation of String into an array of chars, which is stored in the inputStr variable. Then, we create a new array and copy all chars to it in reverse order. To return the value to Dart, we need to convert it into Dart_Handle with Dart_NewStringFromCString() and then call Dart_SetReturnValue(), which sets the returned value. Note that even if we didn't want to return any value, we would still have to set the return value as null with Dart_SetReturnValue(Dart_Null()).

At the beginning of the Hello() function, we create a new Dart scope with Dart_EnterScope(), which we close at the end with Dart_ExitScope(). This automatically deallocates all created Dart_Handles and we don't need to do it by ourselves as with reverseStr, where we have to release the allocated memory with free(reverseStr).

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.12.166.255