invoke method
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;
}