Skip to content

Commit

Permalink
Merge branch 'release/0.7.2'
Browse files Browse the repository at this point in the history
  • Loading branch information
yulingtianxia committed Jun 29, 2022
2 parents 2fe1f4b + 857984d commit 40a7684
Show file tree
Hide file tree
Showing 17 changed files with 71 additions and 26 deletions.
15 changes: 1 addition & 14 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,14 +26,6 @@ Dart finalizer is only supported above Flutter 3(Dart 2.17), but with DartNative

DartNative supports automatic type conversion so its bridging code is shorter & simpler than the Flutter channel.

A comparison of the task of "checking if an app needs to be installed" is shown below:

| | # of lines of bridging code | Coding complexity |
| --- | --- | --- |
| DartNative | Dart 1 + Native 1 | Autogenerated code returns BOOL directly |
| Channel | Dart 15 + Native 30 | Needs to manually define return format, convert NSNumber to BOOL, determine channel & methodName |


The design and vision of this package:

![](images/dartnative.png)
Expand Down Expand Up @@ -183,7 +175,7 @@ unitTest.addFinalizer(() { // register a finalizer callback.
| List | NSArray | Array | List, ArrayList |
| Map | NSDictionary | Dictionary | Map, HashMap |
| Set | NSSet | Set | Set, HashSet |
| Function | Block | Closure | Promise(TODO) |
| Function | Block | Closure | Promise |
| Pointer | void * | UnsafeMutableRawPointer | - |
| NativeByte | NSData | Data | DirectByteBuffer |
| NativeObject | NSObject | NSObject | Object |
Expand Down Expand Up @@ -310,11 +302,6 @@ NOTE: *If you use dart_native on macOS, you must use `use_frameworks!` in your P

## Documentation

### Readme

1. [dart_native README.md](/dart_native/README.md)
2. [dart_native_gen README.md](/dart_native_gen/README.md)

### Further reading

- [告别 Flutter Channel,调用 Native API 仅需一行代码!](http://yulingtianxia.com/blog/2020/06/25/Codegen-for-DartNative/)
Expand Down
4 changes: 4 additions & 0 deletions dart_native/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
## 0.7.2

* [Fix] Support Promise on Android.

## 0.7.1

* [Fix] Leaks on iOS.
Expand Down
3 changes: 0 additions & 3 deletions dart_native/README.md

This file was deleted.

1 change: 1 addition & 0 deletions dart_native/README.md
Binary file modified dart_native/android/src/libs/arm64-v8a/libdart_native.so
Binary file not shown.
Binary file modified dart_native/android/src/libs/armeabi-v7a/libdart_native.so
Binary file not shown.
Binary file modified dart_native/android/src/libs/x86/libdart_native.so
Binary file not shown.
Binary file modified dart_native/android/src/libs/x86_64/libdart_native.so
Binary file not shown.
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.concurrent.atomic.AtomicBoolean;

/**
* Created by huizzzhou on 2020/11/11.
Expand All @@ -19,8 +20,16 @@ public class CallbackInvocationHandler implements InvocationHandler {
put("char", "java.lang.Character");
}};

AtomicBoolean done = new AtomicBoolean(false);

@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
boolean isDartFunctionHandler = proxy instanceof FunctionHandler;
// For auto release memory, invoke only once.
if (isDartFunctionHandler && done.getAndSet(true)) {
throw new IllegalStateException("Invoke already submitted.");
}
args = (isDartFunctionHandler && args != null) ? (Object[]) args[0] : args;
int argumentLength = args == null ? 0 : args.length;
String[] paramsType = new String[argumentLength];
for (int i = 0; i < argumentLength; i++) {
Expand All @@ -31,9 +40,12 @@ public Object invoke(Object proxy, Method method, Object[] args) throws Throwabl
String returnType = method.getReturnType().getName();
returnType = sBasicTypeConvert.get(returnType) == null ? returnType : sBasicTypeConvert.get(returnType);
long dartObjectAddress = CallbackManager.getInstance().getRegisterDartAddr(proxy);
if (isDartFunctionHandler) {
CallbackManager.unRegisterCallback(proxy);
}

return hookCallback(dartObjectAddress, funName, argumentLength, paramsType, args, returnType);
return hookCallback(dartObjectAddress, funName, argumentLength, paramsType, args, returnType, isDartFunctionHandler);
}

private native Object hookCallback(long dartObjectAddress, String funName, int argCount, String[] argTypes, Object[] args, String returnType);
private native Object hookCallback(long dartObjectAddress, String funName, int argCount, String[] argTypes, Object[] args, String returnType, boolean isDartFunctionHandler);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package com.dartnative.dart_native;

public interface FunctionHandler {
Object invoke(Object... arguments);
}
2 changes: 1 addition & 1 deletion dart_native/android/src/main/jni/src/dart_native.cc
Original file line number Diff line number Diff line change
Expand Up @@ -185,7 +185,7 @@ void RegisterNativeCallback(void *dartObject,
DoRegisterNativeCallback(dartObject, clsName, funName, callback, dartPort, env);
}

DN_EXTERN void UnregisterNativeCallback(void *dart_object) {
void UnregisterNativeCallback(void *dart_object) {
auto env = AttachCurrentThread();
if (env == nullptr) {
DNError("UnRegisterNativeCallback error, no JNIEnv provided!");
Expand Down
9 changes: 7 additions & 2 deletions dart_native/android/src/main/jni/src/dn_callback.cc
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,8 @@ static jobject HookNativeCallback(JNIEnv *env,
jint argument_count,
jobjectArray argument_types,
jobjectArray arguments_array,
jstring return_type_str) {
jstring return_type_str,
jboolean is_function_handler) {
auto callbacks = GetDartRegisterCallback(dart_object_address);
if (callbacks.empty()) {
DNError("Invoke dart function error, not register this dart object!");
Expand Down Expand Up @@ -102,6 +103,10 @@ static jobject HookNativeCallback(JNIEnv *env,
env,
async_callback);

if (is_function_handler) {
RemoveDartRegisterCallback(dart_object_address);
}

return callback_result;
}

Expand Down Expand Up @@ -142,7 +147,7 @@ void InitCallback(JNIEnv *env) {
static const JNINativeMethod interface_jni_methods[] = {
{
.name = "hookCallback",
.signature = "(JLjava/lang/String;I[Ljava/lang/String;[Ljava/lang/Object;Ljava/lang/String;)Ljava/lang/Object;",
.signature = "(JLjava/lang/String;I[Ljava/lang/String;[Ljava/lang/Object;Ljava/lang/String;Z)Ljava/lang/Object;",
.fnPtr = (void *) HookNativeCallback
}
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,11 @@
import androidx.annotation.Nullable;

import java.nio.ByteBuffer;
import java.nio.charset.StandardCharsets;
import java.util.Arrays;
import java.util.Map;

import com.dartnative.dart_native.DartNativeInterface;
import com.dartnative.dart_native.FunctionHandler;
import com.dartnative.dart_native.annotation.InterfaceEntry;
import com.dartnative.dart_native.annotation.InterfaceMethod;

Expand Down Expand Up @@ -51,4 +51,9 @@ public ByteBuffer getUTF8Data(String str) {
byteBuffer.rewind();
return byteBuffer;
}

@InterfaceMethod(name = "testCallback")
public void testCallback(FunctionHandler functionHandler) {
functionHandler.invoke(true, "callback from native");
}
}
13 changes: 13 additions & 0 deletions dart_native/example/lib/main.dart
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,9 @@ class _DartNativeAppState extends State<DartNativeApp> {
unitTest.addFinalizer(() {
print('The instance of \'unitTest\' has been destroyed!');
});

// example callback
testCallback();
}

String helloWorld() {
Expand All @@ -74,6 +77,16 @@ class _DartNativeAppState extends State<DartNativeApp> {
return interface.invokeMethodSync('getUTF8Data', args: [str]);
}

void testCallback() {
interface.invokeMethodSync('testCallback', args: [
(bool success, String result) {
if (success) {
print(result);
}
}
]);
}

Future<void> calculate() async {
final aStr = _controllerA.text;
final bStr = _controllerB.text;
Expand Down
2 changes: 1 addition & 1 deletion dart_native/example/pubspec.lock
Original file line number Diff line number Diff line change
Expand Up @@ -168,7 +168,7 @@ packages:
path: ".."
relative: true
source: path
version: "0.7.1"
version: "0.7.2"
dart_native_gen:
dependency: transitive
description:
Expand Down
14 changes: 14 additions & 0 deletions dart_native/lib/src/android/common/pointer_encoding.dart
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import 'dart:ffi';
import 'dart:typed_data';

import 'package:dart_native/src/android/common/callback_manager.dart';
import 'package:dart_native/src/android/foundation/collection/jarray.dart';
import 'package:dart_native/src/android/foundation/direct_byte_buffer.dart';
import 'package:dart_native/src/android/foundation/native_type.dart';
Expand All @@ -21,6 +22,7 @@ enum ValueType {
string,
byteBuffer,
cls,
function,
unknown
}

Expand All @@ -35,6 +37,8 @@ Map<ValueType, Pointer<Utf8>> _pointerForEncode = {
ValueType.bool: 'Z'.toNativeUtf8(),
ValueType.string: 'Ljava/lang/String;'.toNativeUtf8(),
ValueType.byteBuffer: 'Ljava/nio/ByteBuffer;'.toNativeUtf8(),
ValueType.function:
'Lcom/dartnative/dart_native/FunctionHandler;'.toNativeUtf8(),
ValueType.unknown: 'Lunknown;'.toNativeUtf8(),
};

Expand Down Expand Up @@ -119,6 +123,16 @@ dynamic storeValueToPointer(dynamic object, Pointer<Pointer<Void>> ptr,
typePtr.value = argSignature ?? _pointerForEncode[ValueType.unknown]!;
return;
}

if (object is Function) {
final functionHandler = JObject(
className: 'com/dartnative/dart_native/FunctionHandler',
isInterface: true);
registerCallback(functionHandler, object, 'invoke');
ptr.value = functionHandler.pointer;
typePtr.value = argSignature ?? _pointerForEncode[ValueType.function]!;
return;
}
}

dynamic loadValueFromPointer(Pointer<Void> ptr, String returnType) {
Expand Down
4 changes: 3 additions & 1 deletion dart_native/lib/src/android/runtime/jobject.dart
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,9 @@ class JObject extends NativeObject {
' or use @nativeJavaClass annotation to specify the java class';
}
_ptr = newObject(_cls!, this, args: args, isInterface: isInterface);
bindLifeCycleWithJava(_ptr);
if (!isInterface) {
bindLifeCycleWithJava(_ptr);
}
}

/// Wrapper java object pointer as dart object.
Expand Down
2 changes: 1 addition & 1 deletion dart_native/pubspec.yaml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
name: dart_native
description: Write native code using Dart. This package liberates you from native code and low performance channel.
version: 0.7.1
version: 0.7.2
homepage: https://github.com/dart-native/dart_native

environment:
Expand Down

0 comments on commit 40a7684

Please sign in to comment.