This is the fifth day of my participation in the November Gwen Challenge. Check out the details: The last Gwen Challenge 2021

Now that we’ve seen how Dart calls C functions, how can C functions call Dart? Let’s take a look at an example.

Dart function in C

A simple example

Principle: C itself does not provide a method to call the Dart function, but we can pass the Dart function as a parameter to C after the program starts, and C can cache the Dart function pointer, so that C can call the Dart function when needed.

First, let’s define a function on Dart. The Dart function must be a top-level or static function to be called, otherwise an error will be reported.

void dartFunction() {
  debugPrint("[Dart]: Dart function called");
}
Copy the code

We define a registration function sample.h in C

void callDart(void (*callback)());
Copy the code

sample.c

void callDart(void (*callback)()) {
    printf("[CPP]: Now call the Dart function");
    callback();
}
Copy the code

Callback is the received Dart function, which is called directly after registration.

We then convert the Dart function to Pointer and pass it into C by calling C’s callDart function.

late final _callDartPtr = _lookup<
          ffi.NativeFunction<
              ffi.Void Function(
                  ffi.Pointer<ffi.NativeFunction<ffi.Void Function(a) > >) > > ('callDart');
late final _callDart = _callDartPtr.asFunction<
    void Function(ffi.Pointer<ffi.NativeFunction<ffi.Void Function(a) > > > (); _callDart(ffi.Pointer.fromFunction(dartFunction));Copy the code

Here, we use the resulting ffi.Pointer.fromFunction method to convert the Dart function into a Dart map of C function Pointers, and then call C’s callDart function via _callDart.

Output after running:

[CPP]: Dart is now calledCopy the code

Success!

Dart function with parameters

How does C call the Dart function with parameters? Let’s define a Dart function

static void add(int num1,int num2) {
    print("[Dart]: num1: ${num1}, num2: ${num2}");
}
Copy the code

The above function is called to output the value of num1 and num2.

Then we modify the callDart function sample.h

void callDart(void (*callback)(), void (*add)(int.int));
Copy the code

sample.c

void callDart(void (*callback)(), void (*add)(int.int)) {
    printf("Now call the Dart function");
    callback();

    printf(Call the Dart Add function);
    add(1.2);
}
Copy the code

The dart end

late final _callDartPtr = _lookup<
      ffi.NativeFunction<
          ffi.Void Function(
              ffi.Pointer<ffi.NativeFunction<ffi.Void Function()>>,
              ffi.Pointer<
                  ffi.NativeFunction<
                      ffi.Void Function(ffi.Int32, ffi.Int32)>>)>>('callDart');
late final _callDart = _callDartPtr.asFunction<
    void Function(
        ffi.Pointer<ffi.NativeFunction<ffi.Void Function()>>,
        ffi.Pointer<
            ffi.NativeFunction<ffi.Void Function(ffi.Int32, ffi.Int32)>>)>();

_callDart(ffi.Pointer.fromFunction(DartFunctions.dartFunction),ffi.Pointer.fromFunction(DartFunctions.add));
Copy the code

Returns the output

Dart function [CPP]: Dart Add function [Dart]: num1:1, num2:2Copy the code

The parameter is then passed from C to the Dart side.

Get the return value

The above examples all call the Dart function and do not get the return value from the Dart side. Let’s modify the add method so that it returns the sum of num1 and num2.

static int add(int num1, int num2) {
    return num1 + num2;
}
Copy the code

sample.h

void callDart(void (*callback)(), int (*add)(int.int));
Copy the code

sample.c

void callDart(void (*callback)(), int (*add)(int.int)) {
    printf("Now call the Dart function");
    callback();

    printf(Call the Dart Add function);
    int result = add(1.2);
    printf("Add results % d", result);
}
Copy the code

main.dart

late final _callDartPtr = _lookup<
    ffi.NativeFunction<
        ffi.Void Function(
            ffi.Pointer<ffi.NativeFunction<ffi.Void Function()>>,
            ffi.Pointer<
                ffi.NativeFunction<
                    ffi.Int32 Function(ffi.Int32, ffi.Int32)>>)>>('callDart');
late final _callDart = _callDartPtr.asFunction<
    void Function(
        ffi.Pointer<ffi.NativeFunction<ffi.Void Function()>>,
        ffi.Pointer<
            ffi.NativeFunction<ffi.Int32 Function(ffi.Int32, ffi.Int32)>>)>();
_callDart(ffi.Pointer.fromFunction(DartFunctions.dartFunction),ffi.Pointer.fromFunction(DartFunctions.add, 0));
Copy the code

Note that if the Dart function has a return value, the second argument to the fromFunction needs to be passed in the value returned in case of an error.

The output

Dart function [CPP]: Dart Add function [Dart]: num1:1, num2:2 [CPP]: Add result 3Copy the code

Ok, now we have learned how to call the Dart function using C. Of course, in real projects, we usually define an initial function that passes the Dart function that WE want C to call into C’s memory and calls it when C needs it.

The above code I have submitted to my Github repository, there is a need to learn, portal