Skip to content

Commit cedb995

Browse files
committed
refactor: call back refactor
1 parent 5479d22 commit cedb995

File tree

9 files changed

+274
-301
lines changed

9 files changed

+274
-301
lines changed

dart_native/android/src/main/java/com/dartnative/dart_native/CallbackInvocationHandler.java

Lines changed: 20 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -12,27 +12,33 @@
1212
public class CallbackInvocationHandler implements InvocationHandler {
1313
private static final String TAG = "CallbackHandler";
1414

15-
private static HashMap<Class<?>, String> sTypeConvert = new HashMap<Class<?>, String>() {{
16-
put(int.class, "I");
17-
put(float.class, "F");
18-
put(double.class, "D");
19-
put(boolean.class, "Z");
20-
put(String.class, "Ljava/lang/String;");
15+
private static final HashMap<String, String> sBasicTypeConvert = new HashMap<String, String>() {{
16+
put("int", "java.lang.Integer");
17+
put("float", "java.lang.Float");
18+
put("double", "java.lang.Double");
19+
put("boolean", "java.lang.Boolean");
20+
put("byte", "java.lang.Byte");
21+
put("short", "java.lang.Short");
22+
put("long", "java.lang.Long");
23+
put("char", "java.lang.Character");
2124
}};
2225

2326
@Override
2427
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
2528
Log.d(TAG, "invoke method: " + method.getName());
26-
Class<?>[] paramTypes = method.getParameterTypes();
27-
String[] params = new String[paramTypes.length];
28-
for (int i = 0; i < paramTypes.length; i++) {
29-
params[i] = sTypeConvert.get(paramTypes[i]);
29+
int argumentLength = args == null ? 0 : args.length;
30+
String[] paramsType = new String[argumentLength];
31+
for (int i = 0; i < argumentLength; i++) {
32+
paramsType[i] = args[i] != null ? args[i].getClass().getName() : null;
3033
}
34+
3135
String funName = method.getName();
32-
String returnType = sTypeConvert.get(method.getReturnType());
33-
long dartObjectAddr = CallbackManager.getInstance().getRegisterDartAddr(proxy);
34-
return hookCallback(dartObjectAddr, funName, paramTypes.length, params, args, returnType);
36+
String returnType = method.getReturnType().getName();
37+
returnType = sBasicTypeConvert.get(returnType) == null ? returnType : sBasicTypeConvert.get(returnType);
38+
long dartObjectAddress = CallbackManager.getInstance().getRegisterDartAddr(proxy);
39+
40+
return hookCallback(dartObjectAddress, funName, argumentLength, paramsType, args, returnType);
3541
}
3642

37-
static native Object hookCallback(long dartObjectAddr, String funName, int argCount, String[] argTypes, Object[] args, String returnType);
43+
static native Object hookCallback(long dartObjectAddress, String funName, int argCount, String[] argTypes, Object[] args, String returnType);
3844
}

dart_native/android/src/main/jni/dart_native.cpp

Lines changed: 117 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
#include <string>
44
#include <regex>
55
#include <dart_api_dl.h>
6+
#include <semaphore.h>
67
#include "dn_type_convert.h"
78
#include "dn_log.h"
89
#include "dn_method_call.h"
@@ -13,10 +14,10 @@ extern "C"
1314
{
1415

1516
static JavaVM *gJvm = nullptr;
16-
/// todo release
1717
static jobject gClassLoader;
1818
static jmethodID gFindClassMethod;
1919
static pthread_key_t detachKey = 0;
20+
2021
/// for invoke result compare
2122
static jclass gStrCls;
2223

@@ -88,11 +89,6 @@ extern "C"
8889
return JNI_VERSION_1_6;
8990
}
9091

91-
JNIEXPORT void JNI_OnUnload(JavaVM* vm, void* reserved)
92-
{
93-
DNDebug("JNI_OnUnload");
94-
}
95-
9692
jclass _findClass(JNIEnv *env, const char *name)
9793
{
9894
jclass nativeClass = nullptr;
@@ -207,7 +203,7 @@ extern "C"
207203
{
208204
/// mark the last pointer as string
209205
/// dart will check this pointer
210-
dataTypes[argumentCount] = (char *) "java/lang/String";
206+
dataTypes[argumentCount] = (char *) "java.lang.String";
211207
nativeInvokeResult = convertToDartUtf16(env, (jstring)obj);
212208
}
213209
else
@@ -327,4 +323,118 @@ extern "C"
327323
work();
328324
delete work_ptr;
329325
}
326+
327+
/// notify dart run callback function
328+
bool NotifyDart(Dart_Port send_port, const Work *work)
329+
{
330+
const auto work_addr = reinterpret_cast<intptr_t>(work);
331+
332+
Dart_CObject dart_object;
333+
dart_object.type = Dart_CObject_kInt64;
334+
dart_object.value.as_int64 = work_addr;
335+
336+
const bool result = Dart_PostCObject_DL(send_port, &dart_object);
337+
if (!result)
338+
{
339+
DNDebug("Native callback to Dart failed! Invalid port or isolate died");
340+
}
341+
return result;
342+
}
343+
344+
JNIEXPORT jobject JNICALL Java_com_dartnative_dart_1native_CallbackInvocationHandler_hookCallback(JNIEnv *env,
345+
jclass clazz,
346+
jlong dartObjectAddress,
347+
jstring functionName,
348+
jint argumentCount,
349+
jobjectArray argumentTypes,
350+
jobjectArray argumentsArray,
351+
jstring returnTypeStr)
352+
{
353+
Dart_Port port = getCallbackDartPort(dartObjectAddress);
354+
if (port == 0)
355+
{
356+
DNError("not register this dart port!");
357+
return nullptr;
358+
}
359+
360+
char *funName = (char *)env->GetStringUTFChars(functionName, 0);
361+
char **dataTypes = new char *[argumentCount + 1];
362+
void **arguments = new void *[argumentCount + 1];
363+
364+
/// store argument to pointer
365+
for (int i = 0; i < argumentCount; ++i)
366+
{
367+
auto argTypeString = (jstring)env->GetObjectArrayElement(argumentTypes, i);
368+
auto argument = env->GetObjectArrayElement(argumentsArray, i);
369+
dataTypes[i] = (char *)env->GetStringUTFChars(argTypeString, 0);
370+
371+
if (strcmp(dataTypes[i], "java.lang.String") == 0)
372+
{
373+
arguments[i] = (jstring) argument == nullptr ? reinterpret_cast<uint16_t *>((char *)"")
374+
: convertToDartUtf16(env, (jstring)argument);
375+
}
376+
else
377+
{
378+
jclass objCls = env->GetObjectClass(argument);
379+
jobject gObj = env->NewGlobalRef(argument);
380+
objectGlobalCache[gObj] = static_cast<jclass>(env->NewGlobalRef(objCls));
381+
arguments[i] = gObj;
382+
383+
env->DeleteLocalRef(objCls);
384+
}
385+
386+
env->DeleteLocalRef(argTypeString);
387+
env->DeleteLocalRef(argument);
388+
}
389+
390+
/// when return void, jstring which from native is null.
391+
char *returnType = returnTypeStr == nullptr ? nullptr
392+
: (char *)env->GetStringUTFChars(returnTypeStr, 0);
393+
/// the last pointer is return type
394+
dataTypes[argumentCount] = returnType;
395+
396+
sem_t sem;
397+
bool isSemInitSuccess = sem_init(&sem, 0, 0) == 0;
398+
399+
const Work work = [dartObjectAddress, dataTypes, arguments, argumentCount, funName, &sem, isSemInitSuccess]() {
400+
NativeMethodCallback methodCallback = getCallbackMethod(dartObjectAddress, funName);
401+
void *target = getDartObject(dartObjectAddress);
402+
if (methodCallback != nullptr && target != nullptr)
403+
{
404+
methodCallback(target, funName, arguments, dataTypes, argumentCount);
405+
}
406+
if (isSemInitSuccess)
407+
{
408+
sem_post(&sem);
409+
}
410+
};
411+
412+
const Work *work_ptr = new Work(work);
413+
/// check run result
414+
bool notifyResult = NotifyDart(port, work_ptr);
415+
jobject callbackResult = nullptr;
416+
if (isSemInitSuccess)
417+
{
418+
if (notifyResult)
419+
{
420+
sem_wait(&sem);
421+
if (strcmp(returnType, "Ljava/lang/String;") == 0)
422+
{
423+
callbackResult = convertToJavaUtf16(env, (char *)arguments[argumentCount], nullptr, 0);
424+
}
425+
else
426+
{
427+
callbackResult = (jobject) arguments[argumentCount];
428+
}
429+
}
430+
sem_destroy(&sem);
431+
}
432+
433+
env->ReleaseStringUTFChars(returnTypeStr, returnType);
434+
env->ReleaseStringUTFChars(functionName, funName);
435+
delete[] arguments;
436+
delete[] dataTypes;
437+
438+
return callbackResult;
439+
}
330440
}

dart_native/android/src/main/jni/dn_callback.cpp

Lines changed: 1 addition & 151 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,9 @@
22
// Created by Hui on 6/1/21.
33
//
44
#include <string>
5-
#include <semaphore.h>
6-
#include <dart_native_api.h>
7-
#include <dart_api_dl.h>
85
#include "dn_callback.h"
96
#include "dn_log.h"
7+
#include "dn_type_convert.h"
108

119
static std::map<jlong, void *> targetCache;
1210
static std::map<jlong, int64_t> dartPortCache;
@@ -84,151 +82,3 @@ NativeMethodCallback getCallbackMethod(jlong dartObjectAddress, char *functionNa
8482
return methodsMap[functionName];
8583
}
8684

87-
bool NotifyDart(Dart_Port send_port, const Work *work)
88-
{
89-
const auto work_addr = reinterpret_cast<intptr_t>(work);
90-
91-
Dart_CObject dart_object;
92-
dart_object.type = Dart_CObject_kInt64;
93-
dart_object.value.as_int64 = work_addr;
94-
95-
const bool result = Dart_PostCObject_DL(send_port, &dart_object);
96-
if (!result)
97-
{
98-
DNDebug("Native callback to Dart failed! Invalid port or isolate died");
99-
}
100-
return result;
101-
}
102-
103-
extern "C" JNIEXPORT jobject JNICALL Java_com_dartnative_dart_1native_CallbackInvocationHandler_hookCallback(JNIEnv *env,
104-
jclass clazz,
105-
jlong dartObjectAddress,
106-
jstring functionName,
107-
jint argumentCount,
108-
jobjectArray argumentTypes,
109-
jobjectArray argumentsArray,
110-
jstring returnTypeStr)
111-
{
112-
Dart_Port port = getCallbackDartPort(dartObjectAddress);
113-
if (port == 0)
114-
{
115-
DNDebug("not register dart port!");
116-
return nullptr;
117-
}
118-
119-
char *funName = (char *)env->GetStringUTFChars(functionName, 0);
120-
char **argTypes = new char *[argumentCount + 1];
121-
void **arguments = new void *[argumentCount];
122-
for (int i = 0; i < argumentCount; ++i)
123-
{
124-
jstring argTypeString = (jstring)env->GetObjectArrayElement(argumentTypes, i);
125-
jobject argument = env->GetObjectArrayElement(argumentsArray, i);
126-
127-
argTypes[i] = (char *)env->GetStringUTFChars(argTypeString, 0);
128-
env->DeleteLocalRef(argTypeString);
129-
//todo optimization
130-
if (strcmp(argTypes[i], "I") == 0)
131-
{
132-
jclass cls = env->FindClass("java/lang/Integer");
133-
if (env->IsInstanceOf(argument, cls) == JNI_TRUE)
134-
{
135-
jmethodID integerToInt = env->GetMethodID(cls, "intValue", "()I");
136-
jint result = env->CallIntMethod(argument, integerToInt);
137-
arguments[i] = (void *)result;
138-
}
139-
env->DeleteLocalRef(cls);
140-
}
141-
else if (strcmp(argTypes[i], "F") == 0)
142-
{
143-
jclass cls = env->FindClass("java/lang/Float");
144-
if (env->IsInstanceOf(argument, cls) == JNI_TRUE)
145-
{
146-
jmethodID toJfloat = env->GetMethodID(cls, "floatValue", "()F");
147-
jfloat result = env->CallFloatMethod(argument, toJfloat);
148-
float templeFloat = (float)result;
149-
memcpy(&arguments[i], &templeFloat, sizeof(float));
150-
}
151-
env->DeleteLocalRef(cls);
152-
}
153-
else if (strcmp(argTypes[i], "D") == 0)
154-
{
155-
jclass cls = env->FindClass("java/lang/Double");
156-
if (env->IsInstanceOf(argument, cls) == JNI_TRUE)
157-
{
158-
jmethodID toJfloat = env->GetMethodID(cls, "doubleValue", "()D");
159-
jdouble result = env->CallDoubleMethod(argument, toJfloat);
160-
double templeDouble = (double)result;
161-
memcpy(&arguments[i], &templeDouble, sizeof(double));
162-
}
163-
env->DeleteLocalRef(cls);
164-
}
165-
else if (strcmp(argTypes[i], "Ljava/lang/String;") == 0)
166-
{
167-
jstring argString = (jstring)argument;
168-
arguments[i] = argString == nullptr ? (char *)""
169-
: (char *)env->GetStringUTFChars(argString, 0);
170-
env->DeleteLocalRef(argString);
171-
}
172-
}
173-
174-
/// when return void, jstring which from native is null.
175-
char *returnType = returnTypeStr == nullptr ? nullptr
176-
: (char *)env->GetStringUTFChars(returnTypeStr, 0);
177-
178-
argTypes[argumentCount] = returnType;
179-
180-
sem_t sem;
181-
bool isSemInitSuccess = sem_init(&sem, 0, 0) == 0;
182-
183-
const Work work = [dartObjectAddress, argTypes, arguments, argumentCount, funName, &sem, isSemInitSuccess]() {
184-
NativeMethodCallback methodCallback = getCallbackMethod(dartObjectAddress, funName);
185-
void *target = getDartObject(dartObjectAddress);
186-
if (methodCallback != nullptr && target != nullptr)
187-
{
188-
methodCallback(target, funName, arguments, argTypes, argumentCount);
189-
}
190-
if (isSemInitSuccess)
191-
{
192-
sem_post(&sem);
193-
}
194-
};
195-
196-
const Work *work_ptr = new Work(work);
197-
/// error
198-
bool notifyResult = NotifyDart(port, work_ptr);
199-
200-
jobject callbackResult = nullptr;
201-
if (isSemInitSuccess)
202-
{
203-
DNDebug("wait work execute");
204-
sem_wait(&sem);
205-
//todo optimization
206-
if (returnType == nullptr)
207-
{
208-
DNDebug("void");
209-
}
210-
else if (strcmp(returnType, "Ljava/lang/String;") == 0)
211-
{
212-
callbackResult = env->NewStringUTF(arguments[0] == nullptr ? (char *)""
213-
: (char *)arguments[0]);
214-
}
215-
else if (strcmp(returnType, "Z") == 0)
216-
{
217-
jclass booleanClass = env->FindClass("java/lang/Boolean");
218-
jmethodID methodID = env->GetMethodID(booleanClass, "<init>", "(Z)V");
219-
callbackResult = env->NewObject(booleanClass,
220-
methodID,
221-
notifyResult ? static_cast<jboolean>(*((int *)arguments))
222-
: JNI_FALSE);
223-
env->DeleteLocalRef(booleanClass);
224-
}
225-
sem_destroy(&sem);
226-
}
227-
228-
free(returnType);
229-
free(funName);
230-
free(arguments);
231-
free(argTypes);
232-
233-
return callbackResult;
234-
}

dart_native/example/lib/android/delegate_stub.dart

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,8 @@ class DelegateStub extends JObject with SampleDelegate {
3030
}
3131

3232
@override
33-
callbackComplex(int i, double d, String s) {
33+
bool callbackComplex(int i, double d, String s) {
3434
print("callbackComplex from native $i $d $s");
35+
return true;
3536
}
3637
}

0 commit comments

Comments
 (0)