jni: introduce Get*ArrayElements

Signed-off-by: Elias Naur <mail@eliasnaur.com>
pull/14/head
Elias Naur 3 years ago
parent e007a9c153
commit 331bc1e30a

@ -11,6 +11,7 @@ import (
"fmt" "fmt"
"reflect" "reflect"
"runtime" "runtime"
"sync"
"unicode/utf16" "unicode/utf16"
"unsafe" "unsafe"
) )
@ -113,10 +114,34 @@ static jbyteArray jni_NewByteArray(JNIEnv *env, jsize length) {
return (*env)->NewByteArray(env, length); return (*env)->NewByteArray(env, length);
} }
static jboolean *jni_GetBooleanArrayElements(JNIEnv *env, jbooleanArray arr) {
return (*env)->GetBooleanArrayElements(env, arr, NULL);
}
static void jni_ReleaseBooleanArrayElements(JNIEnv *env, jbooleanArray arr, jboolean *elems, jint mode) {
(*env)->ReleaseBooleanArrayElements(env, arr, elems, mode);
}
static jbyte *jni_GetByteArrayElements(JNIEnv *env, jbyteArray arr) { static jbyte *jni_GetByteArrayElements(JNIEnv *env, jbyteArray arr) {
return (*env)->GetByteArrayElements(env, arr, NULL); return (*env)->GetByteArrayElements(env, arr, NULL);
} }
static jint *jni_GetIntArrayElements(JNIEnv *env, jintArray arr) {
return (*env)->GetIntArrayElements(env, arr, NULL);
}
static void jni_ReleaseIntArrayElements(JNIEnv *env, jintArray arr, jint *elems, jint mode) {
(*env)->ReleaseIntArrayElements(env, arr, elems, mode);
}
static jlong *jni_GetLongArrayElements(JNIEnv *env, jlongArray arr) {
return (*env)->GetLongArrayElements(env, arr, NULL);
}
static void jni_ReleaseLongArrayElements(JNIEnv *env, jlongArray arr, jlong *elems, jint mode) {
(*env)->ReleaseLongArrayElements(env, arr, elems, mode);
}
static void jni_ReleaseByteArrayElements(JNIEnv *env, jbyteArray arr, jbyte *elems, jint mode) { static void jni_ReleaseByteArrayElements(JNIEnv *env, jbyteArray arr, jbyte *elems, jint mode) {
(*env)->ReleaseByteArrayElements(env, arr, elems, mode); (*env)->ReleaseByteArrayElements(env, arr, elems, mode);
} }
@ -124,6 +149,18 @@ static void jni_ReleaseByteArrayElements(JNIEnv *env, jbyteArray arr, jbyte *ele
static jsize jni_GetArrayLength(JNIEnv *env, jarray arr) { static jsize jni_GetArrayLength(JNIEnv *env, jarray arr) {
return (*env)->GetArrayLength(env, arr); return (*env)->GetArrayLength(env, arr);
} }
static void jni_DeleteLocalRef(JNIEnv *env, jobject localRef) {
return (*env)->DeleteLocalRef(env, localRef);
}
static jobject jni_GetObjectArrayElement(JNIEnv *env, jobjectArray array, jsize index) {
return (*env)->GetObjectArrayElement(env, array, index);
}
static jboolean jni_IsInstanceOf(JNIEnv *env, jobject obj, jclass clazz) {
return (*env)->IsInstanceOf(env, obj, clazz);
}
*/ */
import "C" import "C"
@ -137,10 +174,22 @@ type (
MethodID C.jmethodID MethodID C.jmethodID
String C.jstring String C.jstring
ByteArray C.jbyteArray ByteArray C.jbyteArray
ObjectArray C.jobjectArray
BooleanArray C.jbooleanArray
LongArray C.jlongArray
IntArray C.jintArray
Boolean C.jboolean Boolean C.jboolean
Value uint64 // All JNI types fit into 64-bits. Value uint64 // All JNI types fit into 64-bits.
) )
// Cached class handles.
var classes struct {
once sync.Once
stringClass, integerClass Class
integerIntValue MethodID
}
func env(e *Env) *C.JNIEnv { func env(e *Env) *C.JNIEnv {
return (*C.JNIEnv)(unsafe.Pointer(e)) return (*C.JNIEnv)(unsafe.Pointer(e))
} }
@ -222,7 +271,7 @@ func CallIntMethod(e *Env, obj Object, method MethodID, args ...Value) (int32, e
return int32(res), exception(e) return int32(res), exception(e)
} }
// GetByteArrayElements returns the contents of the array. // GetByteArrayElements returns the contents of the byte array.
func GetByteArrayElements(e *Env, jarr ByteArray) []byte { func GetByteArrayElements(e *Env, jarr ByteArray) []byte {
if jarr == 0 { if jarr == 0 {
return nil return nil
@ -236,6 +285,76 @@ func GetByteArrayElements(e *Env, jarr ByteArray) []byte {
return s return s
} }
// GetBooleanArrayElements returns the contents of the boolean array.
func GetBooleanArrayElements(e *Env, jarr BooleanArray) []bool {
if jarr == 0 {
return nil
}
size := C.jni_GetArrayLength(env(e), C.jarray(jarr))
elems := C.jni_GetBooleanArrayElements(env(e), C.jbooleanArray(jarr))
defer C.jni_ReleaseBooleanArrayElements(env(e), C.jbooleanArray(jarr), elems, 0)
backing := (*(*[1 << 30]C.jboolean)(unsafe.Pointer(elems)))[:size:size]
r := make([]bool, len(backing))
for i, b := range backing {
r[i] = b == C.JNI_TRUE
}
return r
}
// GetStringArrayElements returns the contents of the String array.
func GetStringArrayElements(e *Env, jarr ObjectArray) []string {
var strings []string
iterateObjectArray(e, jarr, func(e *Env, idx int, item Object) {
s := GoString(e, String(item))
strings = append(strings, s)
})
return strings
}
// GetIntArrayElements returns the contents of the int array.
func GetIntArrayElements(e *Env, jarr IntArray) []int {
if jarr == 0 {
return nil
}
size := C.jni_GetArrayLength(env(e), C.jarray(jarr))
elems := C.jni_GetIntArrayElements(env(e), C.jintArray(jarr))
defer C.jni_ReleaseIntArrayElements(env(e), C.jintArray(jarr), elems, 0)
backing := (*(*[1 << 27]C.jint)(unsafe.Pointer(elems)))[:size:size]
r := make([]int, len(backing))
for i, l := range backing {
r[i] = int(l)
}
return r
}
// GetLongArrayElements returns the contents of the long array.
func GetLongArrayElements(e *Env, jarr LongArray) []int64 {
if jarr == 0 {
return nil
}
size := C.jni_GetArrayLength(env(e), C.jarray(jarr))
elems := C.jni_GetLongArrayElements(env(e), C.jlongArray(jarr))
defer C.jni_ReleaseLongArrayElements(env(e), C.jlongArray(jarr), elems, 0)
backing := (*(*[1 << 27]C.jlong)(unsafe.Pointer(elems)))[:size:size]
r := make([]int64, len(backing))
for i, l := range backing {
r[i] = int64(l)
}
return r
}
func iterateObjectArray(e *Env, jarr ObjectArray, f func(e *Env, idx int, item Object)) {
if jarr == 0 {
return
}
size := C.jni_GetArrayLength(env(e), C.jarray(jarr))
for i := 0; i < int(size); i++ {
item := C.jni_GetObjectArrayElement(env(e), C.jobjectArray(jarr), C.jint(i))
f(e, i, Object(item))
C.jni_DeleteLocalRef(env(e), item)
}
}
// NewByteArray allocates a Java byte array with the content. It // NewByteArray allocates a Java byte array with the content. It
// panics if the allocation fails. // panics if the allocation fails.
func NewByteArray(e *Env, content []byte) ByteArray { func NewByteArray(e *Env, content []byte) ByteArray {

Loading…
Cancel
Save