Skip to content

Commit 326f9b4

Browse files
[jnigen] [jni] 0.9.0 (#1110)
* Refactor JArray<jbool> * Merge internal.c to dartjni.c
1 parent 3519c6f commit 326f9b4

File tree

11 files changed

+280
-301
lines changed

11 files changed

+280
-301
lines changed

pkgs/jni/CHANGELOG.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
## 0.9.0-wip
1+
## 0.9.0
22

33
- **Breaking Change**
44
([#1004](https://github.com/dart-lang/native/issues/1004)): Changed the return

pkgs/jni/ffigen.yaml

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,12 +12,10 @@ output: 'lib/src/third_party/jni_bindings_generated.dart'
1212
headers:
1313
entry-points:
1414
- 'src/dartjni.h' # Exports majority of JNI functions
15-
- 'src/internal.h'
1615
- 'src/third_party/global_jni_env.h' # Exports GlobalJniEnv type
1716
- 'src/jni_constants.h'
1817
include-directives:
1918
- 'src/dartjni.h'
20-
- 'src/internal.h'
2119
- 'src/third_party/global_jni_env.h'
2220
- 'third_party/jni.h' # jni.h from Android NDK
2321
- 'src/jni_constants.h'

pkgs/jni/lib/src/jarray.dart

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -166,8 +166,7 @@ extension BoolArray on JArray<jboolean> {
166166
Uint8List getRange(int start, int end, {Allocator allocator = malloc}) {
167167
RangeError.checkValidRange(start, end, length);
168168
final rangeLength = end - start;
169-
final buffer = allocator
170-
.allocate<JBooleanMarker>(sizeOf<JBooleanMarker>() * rangeLength);
169+
final buffer = allocator<JBooleanMarker>(rangeLength);
171170
Jni.env
172171
.GetBooleanArrayRegion(reference.pointer, start, rangeLength, buffer);
173172
return buffer.asTypedList(rangeLength, finalizer: allocator._nativeFree);
@@ -177,11 +176,10 @@ extension BoolArray on JArray<jboolean> {
177176
[int skipCount = 0]) {
178177
RangeError.checkValidRange(start, end, length);
179178
final rangeLength = end - start;
180-
final it = iterable.skip(skipCount).take(rangeLength);
181179
_allocate<JBooleanMarker>(sizeOf<JBooleanMarker>() * rangeLength, (ptr) {
182-
it.forEachIndexed((index, element) {
183-
ptr[index] = element ? 1 : 0;
184-
});
180+
ptr
181+
.asTypedList(rangeLength)
182+
.setRange(0, rangeLength, iterable.map((e) => e ? 1 : 0), skipCount);
185183
Jni.env.SetBooleanArrayRegion(reference.pointer, start, rangeLength, ptr);
186184
});
187185
}

pkgs/jni/pubspec.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44

55
name: jni
66
description: A library to access JNI from Dart and Flutter that acts as a support library for package:jnigen.
7-
version: 0.9.0-wip
7+
version: 0.9.0
88
repository: https://github.com/dart-lang/native/tree/main/pkgs/jni
99

1010
topics:

pkgs/jni/src/CMakeLists.txt

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@ project(jni_library VERSION 0.0.1 LANGUAGES C)
99

1010
add_library(jni SHARED
1111
"dartjni.c"
12-
"internal.c"
1312
"third_party/global_jni_env.c"
1413
"include/dart_api_dl.c"
1514
)

pkgs/jni/src/dartjni.c

Lines changed: 242 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -639,3 +639,245 @@ FFI_PLUGIN_EXPORT JNIEnv* GetJniEnv() {
639639
attach_thread();
640640
return jniEnv;
641641
}
642+
643+
FFI_PLUGIN_EXPORT intptr_t InitDartApiDL(void* data) {
644+
return Dart_InitializeApiDL(data);
645+
}
646+
647+
// com.github.dart_lang.jni.DartException
648+
jclass _c_DartException = NULL;
649+
650+
jmethodID _m_DartException__ctor = NULL;
651+
FFI_PLUGIN_EXPORT JniResult DartException__ctor(jstring message) {
652+
attach_thread();
653+
load_class_global_ref(&_c_DartException,
654+
"com/github/dart_lang/jni/PortProxy$DartException");
655+
if (_c_DartException == NULL)
656+
return (JniResult){.value = {.j = 0}, .exception = check_exception()};
657+
load_method(_c_DartException, &_m_DartException__ctor, "<init>",
658+
"(Ljava/lang/String;)V");
659+
if (_m_DartException__ctor == NULL)
660+
return (JniResult){.value = {.j = 0}, .exception = check_exception()};
661+
jobject _result = (*jniEnv)->NewObject(jniEnv, _c_DartException,
662+
_m_DartException__ctor, message);
663+
jthrowable exception = check_exception();
664+
if (exception == NULL) {
665+
_result = to_global_ref(_result);
666+
}
667+
return (JniResult){.value = {.l = _result}, .exception = check_exception()};
668+
}
669+
670+
JNIEXPORT void JNICALL
671+
Java_com_github_dart_1lang_jni_PortContinuation__1resumeWith(JNIEnv* env,
672+
jclass clazz,
673+
jlong port,
674+
jobject result) {
675+
attach_thread();
676+
Dart_CObject c_post;
677+
c_post.type = Dart_CObject_kInt64;
678+
c_post.value.as_int64 = (jlong)((*env)->NewGlobalRef(env, result));
679+
Dart_PostCObject_DL(port, &c_post);
680+
}
681+
682+
// com.github.dart_lang.jni.PortContinuation
683+
jclass _c_PortContinuation = NULL;
684+
685+
jmethodID _m_PortContinuation__ctor = NULL;
686+
FFI_PLUGIN_EXPORT
687+
JniResult PortContinuation__ctor(int64_t j) {
688+
attach_thread();
689+
load_class_global_ref(&_c_PortContinuation,
690+
"com/github/dart_lang/jni/PortContinuation");
691+
if (_c_PortContinuation == NULL)
692+
return (JniResult){.value = {.j = 0}, .exception = check_exception()};
693+
load_method(_c_PortContinuation, &_m_PortContinuation__ctor, "<init>",
694+
"(J)V");
695+
if (_m_PortContinuation__ctor == NULL)
696+
return (JniResult){.value = {.j = 0}, .exception = check_exception()};
697+
jobject _result = (*jniEnv)->NewObject(jniEnv, _c_PortContinuation,
698+
_m_PortContinuation__ctor, j);
699+
jthrowable exception = check_exception();
700+
if (exception == NULL) {
701+
_result = to_global_ref(_result);
702+
}
703+
return (JniResult){.value = {.l = _result}, .exception = check_exception()};
704+
}
705+
706+
// com.github.dart_lang.jni.PortProxy
707+
jclass _c_PortProxy = NULL;
708+
709+
jmethodID _m_PortProxy__newInstance = NULL;
710+
FFI_PLUGIN_EXPORT
711+
JniResult PortProxy__newInstance(jobject binaryName,
712+
int64_t port,
713+
int64_t functionPtr) {
714+
attach_thread();
715+
load_class_global_ref(&_c_PortProxy, "com/github/dart_lang/jni/PortProxy");
716+
if (_c_PortProxy == NULL)
717+
return (JniResult){.value = {.j = 0}, .exception = check_exception()};
718+
load_static_method(_c_PortProxy, &_m_PortProxy__newInstance, "newInstance",
719+
"(Ljava/lang/String;JJJ)Ljava/lang/Object;");
720+
if (_m_PortProxy__newInstance == NULL)
721+
return (JniResult){.value = {.j = 0}, .exception = check_exception()};
722+
jobject _result = (*jniEnv)->CallStaticObjectMethod(
723+
jniEnv, _c_PortProxy, _m_PortProxy__newInstance, binaryName, port,
724+
(jlong)Dart_CurrentIsolate_DL(), functionPtr);
725+
return to_global_ref_result(_result);
726+
}
727+
728+
FFI_PLUGIN_EXPORT
729+
void resultFor(CallbackResult* result, jobject object) {
730+
acquire_lock(&result->lock);
731+
result->ready = 1;
732+
result->object = object;
733+
signal_cond(&result->cond);
734+
release_lock(&result->lock);
735+
}
736+
737+
void doNotFinalize(void* isolate_callback_data, void* peer) {}
738+
739+
void finalizeLocal(void* isolate_callback_data, void* peer) {
740+
attach_thread();
741+
(*jniEnv)->DeleteLocalRef(jniEnv, peer);
742+
}
743+
744+
void finalizeGlobal(void* isolate_callback_data, void* peer) {
745+
attach_thread();
746+
(*jniEnv)->DeleteGlobalRef(jniEnv, peer);
747+
}
748+
749+
void finalizeWeakGlobal(void* isolate_callback_data, void* peer) {
750+
attach_thread();
751+
(*jniEnv)->DeleteWeakGlobalRef(jniEnv, peer);
752+
}
753+
754+
void freeBoolean(void* isolate_callback_data, void* peer) {
755+
// To match the platform implementation of Dart's calloc.
756+
free_mem(peer);
757+
}
758+
759+
FFI_PLUGIN_EXPORT
760+
Dart_FinalizableHandle newJObjectFinalizableHandle(Dart_Handle object,
761+
jobject reference,
762+
jobjectRefType refType) {
763+
switch (refType) {
764+
case JNIInvalidRefType:
765+
return Dart_NewFinalizableHandle_DL(object, reference, 0, doNotFinalize);
766+
case JNILocalRefType:
767+
return Dart_NewFinalizableHandle_DL(object, reference, 0, finalizeLocal);
768+
case JNIGlobalRefType:
769+
return Dart_NewFinalizableHandle_DL(object, reference, 0, finalizeGlobal);
770+
case JNIWeakGlobalRefType:
771+
return Dart_NewFinalizableHandle_DL(object, reference, 0,
772+
finalizeWeakGlobal);
773+
}
774+
}
775+
776+
FFI_PLUGIN_EXPORT
777+
Dart_FinalizableHandle newBooleanFinalizableHandle(Dart_Handle object,
778+
bool* reference) {
779+
return Dart_NewFinalizableHandle_DL(object, reference, 1, freeBoolean);
780+
}
781+
782+
FFI_PLUGIN_EXPORT
783+
void deleteFinalizableHandle(Dart_FinalizableHandle finalizableHandle,
784+
Dart_Handle object) {
785+
return Dart_DeleteFinalizableHandle_DL(finalizableHandle, object);
786+
}
787+
788+
jclass _c_Object = NULL;
789+
jclass _c_Long = NULL;
790+
791+
jmethodID _m_Long_init = NULL;
792+
793+
JNIEXPORT jobjectArray JNICALL
794+
Java_com_github_dart_1lang_jni_PortProxy__1invoke(JNIEnv* env,
795+
jclass clazz,
796+
jlong port,
797+
jlong isolateId,
798+
jlong functionPtr,
799+
jobject proxy,
800+
jstring methodDescriptor,
801+
jobjectArray args) {
802+
CallbackResult* result = (CallbackResult*)malloc(sizeof(CallbackResult));
803+
if (isolateId != (jlong)Dart_CurrentIsolate_DL()) {
804+
init_lock(&result->lock);
805+
init_cond(&result->cond);
806+
acquire_lock(&result->lock);
807+
result->ready = 0;
808+
result->object = NULL;
809+
810+
Dart_CObject c_result;
811+
c_result.type = Dart_CObject_kInt64;
812+
c_result.value.as_int64 = (jlong)result;
813+
814+
Dart_CObject c_method;
815+
c_method.type = Dart_CObject_kInt64;
816+
c_method.value.as_int64 =
817+
(jlong)((*env)->NewGlobalRef(env, methodDescriptor));
818+
819+
Dart_CObject c_args;
820+
c_args.type = Dart_CObject_kInt64;
821+
c_args.value.as_int64 = (jlong)((*env)->NewGlobalRef(env, args));
822+
823+
Dart_CObject* c_post_arr[] = {&c_result, &c_method, &c_args};
824+
Dart_CObject c_post;
825+
c_post.type = Dart_CObject_kArray;
826+
c_post.value.as_array.values = c_post_arr;
827+
c_post.value.as_array.length = sizeof(c_post_arr) / sizeof(c_post_arr[0]);
828+
829+
Dart_PostCObject_DL(port, &c_post);
830+
831+
while (!result->ready) {
832+
wait_for(&result->cond, &result->lock);
833+
}
834+
835+
release_lock(&result->lock);
836+
destroy_lock(&result->lock);
837+
destroy_cond(&result->cond);
838+
} else {
839+
result->object = ((jobject(*)(uint64_t, jobject, jobject))functionPtr)(
840+
port, (*env)->NewGlobalRef(env, methodDescriptor),
841+
(*env)->NewGlobalRef(env, args));
842+
}
843+
// Returning an array of length 2.
844+
// [0]: The result pointer, used for cleaning up the global reference, and
845+
// freeing the memory since we passed the ownership to Java.
846+
// [1]: The returned object.
847+
attach_thread();
848+
load_class_global_ref(&_c_Object, "java/lang/Object");
849+
load_class_global_ref(&_c_Long, "java/lang/Long");
850+
load_method(_c_Long, &_m_Long_init, "<init>", "(J)V");
851+
jobject first = (*env)->NewObject(env, _c_Long, _m_Long_init, (jlong)result);
852+
jobject second = result->object;
853+
jobjectArray arr = (*env)->NewObjectArray(env, 2, _c_Object, NULL);
854+
(*env)->SetObjectArrayElement(env, arr, 0, first);
855+
(*env)->SetObjectArrayElement(env, arr, 1, second);
856+
return arr;
857+
}
858+
859+
JNIEXPORT void JNICALL
860+
Java_com_github_dart_1lang_jni_PortProxy__1cleanUp(JNIEnv* env,
861+
jclass clazz,
862+
jlong resultPtr) {
863+
CallbackResult* result = (CallbackResult*)resultPtr;
864+
(*env)->DeleteGlobalRef(env, result->object);
865+
free(result);
866+
}
867+
868+
JNIEXPORT void JNICALL
869+
Java_com_github_dart_1lang_jni_PortCleaner_clean(JNIEnv* env,
870+
jclass clazz,
871+
jlong port) {
872+
Dart_CObject close_signal;
873+
close_signal.type = Dart_CObject_kNull;
874+
Dart_PostCObject_DL(port, &close_signal);
875+
}
876+
877+
JNIEXPORT jobject JNICALL
878+
Java_com_github_dart_1lang_jni_JniUtils_fromReferenceAddress(JNIEnv* env,
879+
jclass clazz,
880+
jlong id) {
881+
attach_thread();
882+
return (jobject)(id);
883+
}

pkgs/jni/src/dartjni.h

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44

55
#pragma once
66

7+
#include "include/dart_api_dl.h"
8+
79
// Note: include appropriate system jni.h as found by CMake, not third_party/jni.h.
810
#include <jni.h>
911
#include <stdint.h>
@@ -366,3 +368,31 @@ static inline JniResult to_global_ref_result(jobject ref) {
366368
}
367369
return result;
368370
}
371+
372+
FFI_PLUGIN_EXPORT intptr_t InitDartApiDL(void* data);
373+
374+
FFI_PLUGIN_EXPORT
375+
JniResult DartException__ctor(jstring message);
376+
377+
FFI_PLUGIN_EXPORT
378+
JniResult PortContinuation__ctor(int64_t j);
379+
380+
FFI_PLUGIN_EXPORT
381+
JniResult PortProxy__newInstance(jobject binaryName,
382+
int64_t port,
383+
int64_t functionPtr);
384+
385+
FFI_PLUGIN_EXPORT void resultFor(CallbackResult* result, jobject object);
386+
387+
FFI_PLUGIN_EXPORT
388+
Dart_FinalizableHandle newJObjectFinalizableHandle(Dart_Handle object,
389+
jobject reference,
390+
jobjectRefType refType);
391+
392+
FFI_PLUGIN_EXPORT
393+
Dart_FinalizableHandle newBooleanFinalizableHandle(Dart_Handle object,
394+
bool* reference);
395+
396+
FFI_PLUGIN_EXPORT
397+
void deleteFinalizableHandle(Dart_FinalizableHandle finalizableHandle,
398+
Dart_Handle object);

0 commit comments

Comments
 (0)