Skip to content

Commit

Permalink
Merge branch 'release/0.7.10'
Browse files Browse the repository at this point in the history
  • Loading branch information
yulingtianxia committed Dec 26, 2022
2 parents b87500b + 9b12932 commit 9baaf23
Show file tree
Hide file tree
Showing 19 changed files with 78 additions and 38 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/dart.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ jobs:
- uses: subosito/flutter-action@v2
with:
# same with pubspec.yaml
flutter-version: "2.2.0"
flutter-version: "3.3.8"
- run: flutter pub get
working-directory: dart_native/example
- run: flutter test --no-pub test/
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ jobs:
- uses: subosito/flutter-action@v2
with:
# same with pubspec.yaml
flutter-version: "2.2.0"
flutter-version: "3.3.8"
- run: flutter pub get
working-directory: dart_native/example
- run: flutter analyze --no-pub --no-current-package lib/ test/
Expand Down
6 changes: 6 additions & 0 deletions dart_native/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
## 0.7.10

* [Fix] A dangling pointer on Android.
* [Fix] DetachCurrentThread crash on Android.
* [Feature] Collections support automatic type conversions on Android.

## 0.7.9

* Bump to ffi >=1.1.2
Expand Down
Binary file not shown.
Binary file not shown.
Binary file removed dart_native/android/src/libs/x86/libdart_native.so
Binary file not shown.
Binary file not shown.
6 changes: 3 additions & 3 deletions dart_native/android/src/main/jni/include/dn_native_invoker.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,7 @@

namespace dartnative {

typedef void(*InvokeCallback)(void *result, char *method, char **typePointers, int argumentCount);

typedef void(*InvokeCallback)(void *result, char *method, char **typePointers, int argumentCount, int isInterface);

JavaLocalRef<jclass> FindClass(const char *name, JNIEnv *env = nullptr);

Expand All @@ -41,7 +40,8 @@ void *DoInvokeNativeMethod(jobject object,
uint32_t stringTypeBitmask,
void *callback,
Dart_Port dartPort,
TaskThread thread);
TaskThread thread,
bool isInterface);

jobject InvokeDartFunction(bool is_same_thread,
int return_async,
Expand Down
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 @@ -161,7 +161,7 @@ void *InvokeNativeMethod(void *objPtr,
auto type = TaskThread(thread);
auto invokeFunction = [=] {
return DoInvokeNativeMethod(object, methodName, arguments, dataTypes, argumentCount, returnType,
stringTypeBitmask, callback, dartPort, type);
stringTypeBitmask, callback, dartPort, type, isInterface);
};
if (type == TaskThread::kFlutterUI) {
return invokeFunction();
Expand Down
24 changes: 17 additions & 7 deletions dart_native/android/src/main/jni/src/dn_jni_env.cc
Original file line number Diff line number Diff line change
Expand Up @@ -8,31 +8,41 @@
namespace dartnative {

static JavaVM *g_vm = nullptr;
static pthread_key_t detach_key = 0;
static pthread_key_t t_key = 0;

void InitWithJavaVM(JavaVM *vm) { g_vm = vm; }

void DetachThreadDestructor(void *arg) {
DNDebug("detach from current thread");
g_vm->DetachCurrentThread();
detach_key = 0;
t_key = 0;
}

JNIEnv *AttachCurrentThread() {
JNIEnv *env;
env = (JNIEnv *)pthread_getspecific(t_key);
if (env != nullptr) {
return env;
}

if (g_vm == nullptr) {
return nullptr;
}

if (detach_key == 0) {
pthread_key_create(&detach_key, DetachThreadDestructor);
if (t_key == 0) {
pthread_key_create(&t_key, DetachThreadDestructor);
}
JNIEnv *env;

jint ret = g_vm->GetEnv((void **) &env, JNI_VERSION_1_6);

switch (ret) {
case JNI_OK:return env;
case JNI_EDETACHED:DNDebug("attach to current thread");
case JNI_OK:
pthread_setspecific(t_key, env);
return env;
case JNI_EDETACHED:
DNDebug("attach to current thread");
g_vm->AttachCurrentThread(&env, nullptr);
pthread_setspecific(t_key, env);
return env;
default:DNError("fail to get env");
return nullptr;
Expand Down
5 changes: 3 additions & 2 deletions dart_native/android/src/main/jni/src/dn_jni_utils.cc
Original file line number Diff line number Diff line change
Expand Up @@ -151,8 +151,8 @@ uint16_t *JavaStringToDartString(JNIEnv *env, jstring nativeString) {

/// Returns a malloc pointer to the result.
char *GenerateSignature(char **argumentTypes, int argumentCount, char *returnType) {
/// include "(" ")" length
size_t signatureLength = strlen(returnType) + 2;
/// include "(" ")" and blank length
size_t signatureLength = strlen(returnType) + 3;
/// all argument type length
for (int i = 0; i < argumentCount; i++) {
signatureLength += strlen(argumentTypes[i]);
Expand All @@ -166,6 +166,7 @@ char *GenerateSignature(char **argumentTypes, int argumentCount, char *returnTyp
}
strcpy(signature + offset, ")");
strcpy(signature + offset + 1, returnType);
signature[signatureLength - 1] = '\0';

return signature;
}
Expand Down
15 changes: 7 additions & 8 deletions dart_native/android/src/main/jni/src/dn_native_invoker.cc
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,8 @@ void *DoInvokeNativeMethod(jobject object,
uint32_t stringTypeBitmask,
void *callback,
Dart_Port dartPort,
TaskThread thread) {
TaskThread thread,
bool isInterface) {
void *nativeInvokeResult = nullptr;
JNIEnv *env = AttachCurrentThread();
if (env == nullptr) {
Expand Down Expand Up @@ -171,9 +172,6 @@ void *DoInvokeNativeMethod(jobject object,
stringTypeBitmask,
jObjBucket);

/// Save return type, dart will use this pointer.
typePointers[argumentCount] = returnType;

switch (*returnType) {
case 'C':nativeInvokeResult = (void *) env->CallCharMethodA(object, method, argValues);
break;
Expand Down Expand Up @@ -219,7 +217,6 @@ void *DoInvokeNativeMethod(jobject object,
typePointers[argumentCount] = (char *) "java.lang.String";
nativeInvokeResult = JavaStringToDartString(env, (jstring) ret.Object());
} else {
typePointers[argumentCount] = (char *) "java.lang.Object";
if (ret.IsNull()) {
nativeInvokeResult = nullptr;
break;
Expand All @@ -245,16 +242,18 @@ void *DoInvokeNativeMethod(jobject object,
((InvokeCallback) callback)(nativeInvokeResult,
methodName,
typePointers,
argumentCount);
argumentCount,
isInterface);
} else {
sem_t sem;
bool isSemInitSuccess = sem_init(&sem, 0, 0) == 0;
const WorkFunction work =
[callback, nativeInvokeResult, methodName, typePointers, argumentCount, isSemInitSuccess, &sem] {
[callback, nativeInvokeResult, methodName, typePointers, argumentCount, isSemInitSuccess, isInterface, &sem] {
((InvokeCallback) callback)(nativeInvokeResult,
methodName,
typePointers,
argumentCount);
argumentCount,
isInterface);
if (isSemInitSuccess) {
sem_post(&sem);
}
Expand Down
1 change: 0 additions & 1 deletion dart_native/example/lib/android/unit_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import 'package:dart_native_example/android/runtimestub.dart';
import 'package:dart_native_example/android/entity.dart';
import 'package:dart_native_example/android/runtimestub_async.dart';

import 'delegate_stub.dart';
import 'package:dart_native_example/dn_unit_test.dart';
import 'package:ffi/ffi.dart';

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.9"
version: "0.7.10"
dart_native_gen:
dependency: transitive
description:
Expand Down
20 changes: 19 additions & 1 deletion dart_native/lib/src/android/common/pointer_encoding.dart
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,10 @@ import 'package:dart_native/src/android/runtime/jobject.dart';
import 'package:dart_native/src/common/native_byte.dart';
import 'package:ffi/ffi.dart';

import 'package:dart_native/src/android/foundation/collection/jlist.dart';
import 'package:dart_native/src/android/foundation/collection/jmap.dart';
import 'package:dart_native/src/android/foundation/collection/jset.dart';

enum ValueType {
char,
int,
Expand Down Expand Up @@ -135,7 +139,8 @@ dynamic storeValueToPointer(dynamic object, Pointer<Pointer<Void>> ptr,
}
}

dynamic loadValueFromPointer(Pointer<Void> ptr, String returnType) {
dynamic loadValueFromPointer(Pointer<Void> ptr, String returnType,
{bool decodeRetVal = false}) {
if (returnType == 'V') {
return;
}
Expand All @@ -148,6 +153,19 @@ dynamic loadValueFromPointer(Pointer<Void> ptr, String returnType) {
return NativeByte.fromRaw(DirectByteBuffer.fromPointer(ptr));
}

// todo optimize
if (decodeRetVal && returnType == 'Ljava/util/Map;') {
return JHashMap.fromPointer(ptr).raw;
}

if (decodeRetVal && returnType == 'Ljava/util/List;') {
return JArrayList.fromPointer(ptr).raw;
}

if (decodeRetVal && returnType == 'Ljava/util/Set;') {
return JHashSet.fromPointer(ptr).raw;
}

dynamic result;
ByteBuffer buffer = Int64List.fromList([ptr.address]).buffer;
ByteData data = ByteData.view(buffer);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ ArrayType _getValueType(dynamic value) {
} else if (value is bool) {
return ArrayType('bool', '[Z');
} else if (value is JObject) {
return ArrayType('object', '[L' + value.className! + ';');
return ArrayType('object', '[L${value.className!};');
} else {
throw 'Invalid type in JArray.';
}
Expand Down
8 changes: 6 additions & 2 deletions dart_native/lib/src/android/runtime/functions.dart
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,12 @@ typedef MethodNativeCallback = Void Function(
Int64 responseId);

// use in dart async invoke native
typedef InvokeCallback = Void Function(Pointer<Void> result,
Pointer<Utf8> method, Pointer<Pointer<Utf8>> typePointers, Int32 argCount);
typedef InvokeCallback = Void Function(
Pointer<Void> result,
Pointer<Utf8> method,
Pointer<Pointer<Utf8>> typePointers,
Int32 argCount,
Int32 isInterface);

// notify c++ async invoke result
final void Function(
Expand Down
19 changes: 11 additions & 8 deletions dart_native/lib/src/android/runtime/messenger.dart
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,8 @@ Pointer<Void> _newNativeObject(String className, {List? args}) {
objectPtr =
nativeCreateObject(classNamePtr, nullptr.cast(), nullptr.cast(), 0, 0);
} else {
NativeArguments nativeArguments = _parseNativeArguments(args);
NativeArguments nativeArguments =
_parseNativeArguments(args, 'java.lang.Object');
objectPtr = nativeCreateObject(
classNamePtr,
nativeArguments.pointers,
Expand Down Expand Up @@ -58,11 +59,12 @@ Pointer<NativeFunction<InvokeCallback>> _invokeCallbackPtr =
Pointer.fromFunction(_invokeCallback);

void _invokeCallback(Pointer<Void> result, Pointer<Utf8> method,
Pointer<Pointer<Utf8>> typePtrs, int argCount) {
Pointer<Pointer<Utf8>> typePtrs, int argCount, int isInterface) {
final callback = _invokeCallbackMap[method];
if (callback != null) {
dynamic value = loadValueFromPointer(
result, typePtrs.elementAt(argCount).value.toDartString());
result, typePtrs.elementAt(argCount).value.toDartString(),
decodeRetVal: isInterface == 1);
callback(value);
_invokeCallbackMap.remove(method);
}
Expand Down Expand Up @@ -106,8 +108,8 @@ dynamic _doInvoke(
}
}

NativeArguments nativeArguments =
_parseNativeArguments(args, argsSignature: assignedSignaturePtr);
NativeArguments nativeArguments = _parseNativeArguments(args, returnType,
argsSignature: assignedSignaturePtr);

Pointer<Void> invokeMethodRet = nativeInvoke(
objPtr,
Expand All @@ -129,7 +131,8 @@ dynamic _doInvoke(
nativeArguments.typePointers
.elementAt(args?.length ?? 0)
.value
.toDartString());
.toDartString(),
decodeRetVal: isInterface);
assignedSignaturePtr?.forEach(calloc.free);
calloc.free(nativeArguments.typePointers);
}
Expand Down Expand Up @@ -157,7 +160,7 @@ Future<dynamic> invoke(
return completer.future;
}

NativeArguments _parseNativeArguments(List? args,
NativeArguments _parseNativeArguments(List? args, String returnType,
{List<Pointer<Utf8>>? argsSignature}) {
Pointer<Pointer<Void>> pointers = nullptr.cast();
Pointer<Pointer<Utf8>> typePointers =
Expand Down Expand Up @@ -205,7 +208,7 @@ NativeArguments _parseNativeArguments(List? args,
}
}
}
typePointers.elementAt(args?.length ?? 0).value = '0'.toNativeUtf8();
typePointers.elementAt(args?.length ?? 0).value = returnType.toNativeUtf8();
return NativeArguments(pointers, typePointers, stringTypeBitmask);
}

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.9
version: 0.7.10
homepage: https://github.com/dart-native/dart_native

environment:
Expand Down

0 comments on commit 9baaf23

Please sign in to comment.