invoke method

dynamic invoke([
  1. List? args
])

Invoke the Block synchronously.

Invoking a block created by Dart function is invalid, because it's used for callback from native to Dart.

Implementation

dynamic invoke([List? args]) {
  if (pointer == nullptr || function != null) {
    return null;
  }
  Pointer<Utf8> typesEncodingsPtr = _blockTypeEncodeString(pointer);
  Pointer<Int32> countPtr = calloc<Int32>();
  Pointer<Pointer<Utf8>> typesPtrPtr =
      nativeTypesEncoding(typesEncodingsPtr, countPtr, 0);
  int count = countPtr.value;
  calloc.free(countPtr);
  // typesPtrPtr contains return type and block itself.
  if (count != (args?.length ?? 0) + 2) {
    throw 'The number of arguments for methods dart and objc does not match';
  }
  int stringTypeBitmask = 0;
  Pointer<Pointer<Void>> argsPtrPtr = nullptr.cast();
  List<Pointer<Utf8>> structTypes = [];
  List<Pointer<Void>> blockPointers = [];
  if (args != null) {
    argsPtrPtr = calloc<Pointer<Void>>(args.length);
    for (var i = 0; i < args.length; i++) {
      var arg = args[i];
      arg ??= nil;
      if (arg is String) {
        stringTypeBitmask |= (0x1 << i);
      }
      var argTypePtr = typesPtrPtr.elementAt(i + 2).value;
      if (argTypePtr.isStruct) {
        structTypes.add(argTypePtr);
      }
      final argPtrPtr = argsPtrPtr.elementAt(i);
      storeValueToPointer(arg, argPtrPtr, argTypePtr);
      if (arg is Function && argTypePtr.maybeBlock) {
        blockPointers.add(argPtrPtr.value);
      }
    }
  }

  Pointer<Void> resultPtr = blockInvoke(
      pointer, argsPtrPtr, nativePort, stringTypeBitmask, typesPtrPtr);
  if (argsPtrPtr != nullptr.cast()) {
    calloc.free(argsPtrPtr);
  }

  var retTypePtr = typesPtrPtr.value;
  if (retTypePtr.isStruct) {
    structTypes.add(retTypePtr);
  }
  // return value is a String.
  dynamic result;
  if (retTypePtr.isString) {
    result = loadStringFromPointer(resultPtr);
  } else {
    result = loadValueFromPointer(resultPtr, retTypePtr);
  }
  // free struct type memory (malloc on native side)
  structTypes.forEach(calloc.free);
  // free typesPtrPtr (malloc on native side)
  calloc.free(typesPtrPtr);
  // release block after use (copy on native side).
  blockPointers.forEach(Block_release);
  return result;
}