mirror of
https://github.com/netbirdio/gomobile-tvos-fork.git
synced 2026-05-22 18:43:29 -07:00
bind,cmd: accept Java API in bound packages
Accept Java API interface types as arguments and return values from bound Go package functions and methods. Also, allow Go structs to extend Java classes and implement Java interfaces as well as override and implement methods. This is the third and final part of the implementation of the golang/go#16876 proposal. Fixes golang/go#16876 Change-Id: I6951dd87235553ce09abe5117a39a503466163c0 Reviewed-on: https://go-review.googlesource.com/28597 Reviewed-by: David Crawshaw <crawshaw@golang.org>
This commit is contained in:
@@ -29,13 +29,14 @@ static jmethodID seq_throw_exc;
|
||||
static jmethodID seq_getRef;
|
||||
static jmethodID seq_decRef;
|
||||
static jmethodID seq_incRef;
|
||||
static jmethodID seq_incGoObjectRef;
|
||||
static jmethodID seq_incRefnum;
|
||||
static jmethodID seq_wrapThrowable;
|
||||
|
||||
static jmethodID throwable_getMessage;
|
||||
|
||||
static jfieldID ref_objField;
|
||||
|
||||
static jclass throwable_class;
|
||||
|
||||
// env_destructor is registered as a thread data key destructor to
|
||||
// clean up a Go thread that is attached to the JVM.
|
||||
static void env_destructor(void *env) {
|
||||
@@ -61,7 +62,11 @@ static JNIEnv *go_seq_get_thread_env(void) {
|
||||
|
||||
void go_seq_maybe_throw_exception(JNIEnv *env, jobject msg) {
|
||||
if (msg != NULL) {
|
||||
(*env)->CallStaticVoidMethod(env, seq_class, seq_throw_exc, msg);
|
||||
if ((*env)->IsInstanceOf(env, msg, throwable_class)) {
|
||||
(*env)->Throw(env, msg);
|
||||
} else {
|
||||
(*env)->CallStaticVoidMethod(env, seq_class, seq_throw_exc, msg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -220,6 +225,13 @@ nbyteslice go_seq_from_java_bytearray(JNIEnv *env, jbyteArray arr, int copy) {
|
||||
return res;
|
||||
}
|
||||
|
||||
int32_t go_seq_to_refnum_go(JNIEnv *env, jobject o) {
|
||||
if (o == NULL) {
|
||||
return NULL_REFNUM;
|
||||
}
|
||||
return (int32_t)(*env)->CallStaticIntMethod(env, seq_class, seq_incGoObjectRef, o);
|
||||
}
|
||||
|
||||
int32_t go_seq_to_refnum(JNIEnv *env, jobject o) {
|
||||
if (o == NULL) {
|
||||
return NULL_REFNUM;
|
||||
@@ -241,9 +253,12 @@ jobject go_seq_from_refnum(JNIEnv *env, int32_t refnum, jclass proxy_class, jmet
|
||||
(*env)->CallStaticVoidMethod(env, seq_class, seq_decRef, (jint)refnum);
|
||||
// return ref.obj
|
||||
return (*env)->GetObjectField(env, ref, ref_objField);
|
||||
} else {
|
||||
} else if (proxy_class != NULL) {
|
||||
// return new <Proxy>(ref)
|
||||
return (*env)->NewObject(env, proxy_class, proxy_cons, ref);
|
||||
} else {
|
||||
// We're inside a Java proxy constructor and only need the Seq.Ref
|
||||
return ref;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -258,9 +273,13 @@ jstring go_seq_to_java_string(JNIEnv *env, nstring str) {
|
||||
|
||||
// go_seq_push_local_frame retrieves or creates the JNIEnv* for the current thread
|
||||
// and pushes a JNI reference frame. Must be matched with call to go_seq_pop_local_frame.
|
||||
JNIEnv *go_seq_push_local_frame(jint cap) {
|
||||
JNIEnv *go_seq_push_local_frame(jint nargs) {
|
||||
JNIEnv *env = go_seq_get_thread_env();
|
||||
if ((*env)->PushLocalFrame(env, cap) < 0) {
|
||||
// Given the number of function arguments, compute a conservative bound for the minimal frame size.
|
||||
// Assume two slots for each per parameter (Seq.Ref and Seq.Object) and add extra
|
||||
// extra space for the receiver, the return value, and exception (if any).
|
||||
jint frameSize = 2*nargs + 10;
|
||||
if ((*env)->PushLocalFrame(env, frameSize) < 0) {
|
||||
LOG_FATAL("PushLocalFrame failed");
|
||||
}
|
||||
return env;
|
||||
@@ -312,18 +331,19 @@ Java_go_Seq_init(JNIEnv *env, jclass clazz) {
|
||||
if (seq_incRef == NULL) {
|
||||
LOG_FATAL("failed to find method Seq.incRef");
|
||||
}
|
||||
seq_incGoObjectRef = (*env)->GetStaticMethodID(env, seq_class, "incGoObjectRef", "(Lgo/Seq$GoObject;)I");
|
||||
if (seq_incGoObjectRef == NULL) {
|
||||
LOG_FATAL("failed to find method Seq.incGoObjectRef");
|
||||
}
|
||||
seq_wrapThrowable = (*env)->GetStaticMethodID(env, seq_class, "wrapThrowable", "(Ljava/lang/Throwable;)Lgo/error;");
|
||||
if (seq_wrapThrowable == NULL) {
|
||||
LOG_FATAL("failed to find method Seq.wrapThrowable");
|
||||
}
|
||||
jclass throwable_class = (*env)->FindClass(env, "java/lang/Throwable");
|
||||
throwable_class = (*env)->FindClass(env, "java/lang/Throwable");
|
||||
if (throwable_class == NULL) {
|
||||
LOG_FATAL("failed to find Throwable class");
|
||||
}
|
||||
throwable_getMessage = (*env)->GetMethodID(env, throwable_class, "getMessage", "()Ljava/lang/String;");
|
||||
if (throwable_getMessage == NULL) {
|
||||
LOG_FATAL("failed to find method Throwable.getMessage");
|
||||
}
|
||||
throwable_class = (*env)->NewGlobalRef(env, throwable_class);
|
||||
jclass ref_class = (*env)->FindClass(env, "go/Seq$Ref");
|
||||
if (ref_class == NULL) {
|
||||
LOG_FATAL("failed to find the Seq.Ref class");
|
||||
@@ -376,3 +396,9 @@ jmethodID go_seq_get_method_id(jclass clazz, const char *name, const char *sig)
|
||||
go_seq_pop_local_frame(env);
|
||||
return m;
|
||||
}
|
||||
|
||||
void go_seq_release_byte_array(JNIEnv *env, jbyteArray arr, jbyte* ptr) {
|
||||
if (ptr != NULL) {
|
||||
(*env)->ReleaseByteArrayElements(env, arr, ptr, 0);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user