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"
"reflect"
"runtime"
"sync"
"unicode/utf16"
"unsafe"
)
@ -113,10 +114,34 @@ static jbyteArray jni_NewByteArray(JNIEnv *env, jsize 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) {
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) {
(*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) {
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"
@ -132,15 +169,27 @@ type JVM C.JavaVM
type Env C.JNIEnv
type (
Class C.jclass
Object C.jobject
MethodID C.jmethodID
String C.jstring
ByteArray C.jbyteArray
Boolean C.jboolean
Value uint64 // All JNI types fit into 64-bits.
Class C.jclass
Object C.jobject
MethodID C.jmethodID
String C.jstring
ByteArray C.jbyteArray
ObjectArray C.jobjectArray
BooleanArray C.jbooleanArray
LongArray C.jlongArray
IntArray C.jintArray
Boolean C.jboolean
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 {
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)
}
// GetByteArrayElements returns the contents of the array.
// GetByteArrayElements returns the contents of the byte array.
func GetByteArrayElements(e *Env, jarr ByteArray) []byte {
if jarr == 0 {
return nil
@ -236,6 +285,76 @@ func GetByteArrayElements(e *Env, jarr ByteArray) []byte {
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
// panics if the allocation fails.
func NewByteArray(e *Env, content []byte) ByteArray {

Loading…
Cancel
Save