Add a call method to Blocks (#407)

* Add a call method to Blocks, so that ObjC blocks can be called from Dart

* fmt
diff --git a/lib/src/code_generator/objc_block.dart b/lib/src/code_generator/objc_block.dart
index 7ae7486..711e469 100644
--- a/lib/src/code_generator/objc_block.dart
+++ b/lib/src/code_generator/objc_block.dart
@@ -52,6 +52,7 @@
     final trampFuncType = FunctionType(
         returnType: returnType,
         parameters: [Parameter(type: blockPtr, name: 'block'), ...params]);
+    final natTrampFnType = NativeFunc(trampFuncType);
 
     // Write the function pointer based trampoline function.
     s.write(returnType.getDartType(w));
@@ -117,6 +118,22 @@
                   $exceptionalReturn).cast(), $registerClosure(fn));
 ''');
 
+    // Call method.
+    s.write('  ${returnType.getDartType(w)} call(');
+    for (int i = 0; i < params.length; ++i) {
+      s.write('${i == 0 ? '' : ', '}${params[i].type.getDartType(w)}');
+      s.write(' ${params[i].name}');
+    }
+    s.write(''') {
+    ${isVoid ? '' : 'return '}_impl.ref.invoke.cast<
+        ${natTrampFnType.getCType(w)}>().asFunction<
+            ${trampFuncType.getDartType(w)}>()(_impl''');
+    for (int i = 0; i < params.length; ++i) {
+      s.write(', ${params[i].name}');
+    }
+    s.write(''');
+  }''');
+
     // Get the pointer to the underlying block.
     s.write('  ${blockPtr.getCType(w)} get pointer => _impl;\n');
 
diff --git a/test/native_objc_test/block_test.dart b/test/native_objc_test/block_test.dart
index 4586cd8..87f882d 100644
--- a/test/native_objc_test/block_test.dart
+++ b/test/native_objc_test/block_test.dart
@@ -42,6 +42,7 @@
       final blockTester = BlockTester.makeFromBlock_(lib, block.pointer);
       blockTester.pokeBlock();
       expect(blockTester.call_(123), 223);
+      expect(block(123), 223);
     });
 
     int Function(int) makeAdder(int addTo) {
@@ -53,6 +54,7 @@
       final blockTester = BlockTester.makeFromBlock_(lib, block.pointer);
       blockTester.pokeBlock();
       expect(blockTester.call_(123), 4123);
+      expect(block(123), 4123);
     });
   });
 }