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)
.
3.12.166.255