summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJari Vetoniemi <mailroxas@gmail.com>2018-05-16 15:28:21 +0300
committerJari Vetoniemi <mailroxas@gmail.com>2018-05-16 15:28:21 +0300
commitb79dd39e52415d8d91a7f24a2e44cd2ff9f7c91a (patch)
tree01bf9768e5a0d27607e592ffead0f9c4fd9bf038
parent8fb79727f8b7b9441606d8fde1d1310ff73ce505 (diff)
jvm: Return proxy objects for stubbed methods
This is better than returning NULL, as we can track better where things go wrong and what needs to be implemented.
-rw-r--r--src/jvm/jvm.c127
1 files changed, 71 insertions, 56 deletions
diff --git a/src/jvm/jvm.c b/src/jvm/jvm.c
index 213b549..0d99df9 100644
--- a/src/jvm/jvm.c
+++ b/src/jvm/jvm.c
@@ -481,6 +481,14 @@ jvm_form_symbol(struct jvm *jvm, jmethodID method_id, char *symbol, const size_t
cstr_replace(symbol, '$', '_');
}
+static jobject
+jvm_stub_class_from_method(struct jvm *jvm, jmethodID method_id)
+{
+ char symbol[255];
+ jvm_form_symbol(jvm, method_id, symbol, sizeof(symbol));
+ return jvm_make_class(jvm, symbol);
+}
+
static void*
jvm_wrap_method(struct jvm *jvm, jmethodID method_id)
{
@@ -567,103 +575,110 @@ JNIEnv_CallNonvirtualVoidMethodA(JNIEnv* p0, jobject p1, jclass p2, jmethodID p3
// N == Call method type convention (Long, Float, StaticLong, StaticFloat, etc...)
// T == C type of return value
// C == Type of second argument (jclass for static call, jobject for instance call)
-#define gen_jnienv_method_call(N, T, C) \
+// D == Default return value
+#define gen_jnienv_method_call(N, T, C, D) \
static T \
- JNIEnv_Call##N##MethodV(JNIEnv *p0, C p1, jmethodID p2, va_list p3) { \
- assert(p0 && p1 && p2); \
+ JNIEnv_Call##N##MethodV(JNIEnv *p0, C p1, jmethodID method, va_list p3) { \
+ assert(p0 && p1 && method); \
union { T (*fun)(JNIEnv*, C, va_list); void *ptr; } f; \
- f.ptr = jvm_wrap_method(jnienv_get_jvm(p0), p2); \
- return (f.ptr ? f.fun(p0, p1, p3) : 0); \
+ f.ptr = jvm_wrap_method(jnienv_get_jvm(p0), method); \
+ return (f.ptr ? f.fun(p0, p1, p3) : D); \
} \
static T \
- JNIEnv_Call##N##MethodA(JNIEnv* p0, C p1, jmethodID p2, jvalue* p3) { \
- assert(p0 && p1 && p2); \
+ JNIEnv_Call##N##MethodA(JNIEnv* p0, C p1, jmethodID method, jvalue* p3) { \
+ assert(p0 && p1 && method); \
union { T (*fun)(JNIEnv*, C, jvalue*); void *ptr; } f; \
- f.ptr = jvm_wrap_method(jnienv_get_jvm(p0), p2); \
- return (f.ptr ? f.fun(p0, p1, p3) : 0); \
+ f.ptr = jvm_wrap_method(jnienv_get_jvm(p0), method); \
+ return (f.ptr ? f.fun(p0, p1, p3) : D); \
} \
static T \
- JNIEnv_Call##N##Method(JNIEnv* p0, C p1, jmethodID p2, ...) { \
+ JNIEnv_Call##N##Method(JNIEnv* p0, C p1, jmethodID method, ...) { \
va_list ap; \
- va_start(ap, p2); \
- const T r = JNIEnv_Call##N##MethodV(p0, p1, p2, ap); \
+ va_start(ap, method); \
+ const T r = JNIEnv_Call##N##MethodV(p0, p1, method, ap); \
va_end(ap); \
return r; \
}
// N == Call method type name (Long, Float, etc...)
// T == C type of return value
-#define gen_jnienv_nonvirtual_method_call(N, T) \
+// D == Default return value
+#define gen_jnienv_nonvirtual_method_call(N, T, D) \
static T \
- JNIEnv_CallNonvirtual##N##MethodV(JNIEnv *p0, jobject p1, jclass p2, jmethodID p3, va_list p4) { \
- assert(p0 && p1 && p2 && p3); \
+ JNIEnv_CallNonvirtual##N##MethodV(JNIEnv *p0, jobject p1, jclass p2, jmethodID method, va_list p4) { \
+ assert(p0 && p1 && p2 && method); \
union { T (*fun)(JNIEnv*, jobject, jclass, va_list); void *ptr; } f; \
f.ptr = jvm_wrap_method(jnienv_get_jvm(p0), p2); \
- return (f.ptr ? f.fun(p0, p1, p2, p4) : 0); \
+ return (f.ptr ? f.fun(p0, p1, p2, p4) : D); \
} \
static T \
- JNIEnv_CallNonvirtual##N##MethodA(JNIEnv *p0, jobject p1, jclass p2, jmethodID p3, jvalue *p4) { \
- assert(p0 && p1 && p2 && p3); \
+ JNIEnv_CallNonvirtual##N##MethodA(JNIEnv *p0, jobject p1, jclass p2, jmethodID method, jvalue *p4) { \
+ assert(p0 && p1 && p2 && method); \
union { T (*fun)(JNIEnv*, jobject, jclass, jvalue*); void *ptr; } f; \
f.ptr = jvm_wrap_method(jnienv_get_jvm(p0), p2); \
- return (f.ptr ? f.fun(p0, p1, p2, p4) : 0); \
+ return (f.ptr ? f.fun(p0, p1, p2, p4) : D); \
} \
static T \
- JNIEnv_CallNonvirtual##N##Method(JNIEnv* p0, jobject p1, jclass p2, jmethodID p3, ...) { \
+ JNIEnv_CallNonvirtual##N##Method(JNIEnv* p0, jobject p1, jclass p2, jmethodID method, ...) { \
va_list ap; \
- va_start(ap, p3); \
- const T r = JNIEnv_CallNonvirtual##N##MethodV(p0, p1, p2, p3, ap); \
+ va_start(ap, method); \
+ const T r = JNIEnv_CallNonvirtual##N##MethodV(p0, p1, p2, method, ap); \
va_end(ap); \
return r; \
}
// N == Method type name
// T == C type of return value
-#define gen_jnienv_method(N, T) \
- gen_jnienv_method_call(N, T, jobject) \
- gen_jnienv_method_call(Static##N, T, jclass) \
- gen_jnienv_nonvirtual_method_call(N, T)
-
-gen_jnienv_method(Object, jobject)
-gen_jnienv_method(Boolean, jboolean)
-gen_jnienv_method(Byte, jbyte)
-gen_jnienv_method(Char, jchar)
-gen_jnienv_method(Short, jshort)
-gen_jnienv_method(Int, jint)
-gen_jnienv_method(Long, jlong)
-gen_jnienv_method(Float, jfloat)
-gen_jnienv_method(Double, jdouble)
+// D == Default return value
+#define gen_jnienv_method(N, T, D) \
+ gen_jnienv_method_call(N, T, jobject, D) \
+ gen_jnienv_method_call(Static##N, T, jclass, D) \
+ gen_jnienv_nonvirtual_method_call(N, T, D)
+
+gen_jnienv_method(Object, jobject, jvm_stub_class_from_method(jnienv_get_jvm(p0), method))
+gen_jnienv_method(Boolean, jboolean, false)
+gen_jnienv_method(Byte, jbyte, 0)
+gen_jnienv_method(Char, jchar, 0)
+gen_jnienv_method(Short, jshort, 0)
+gen_jnienv_method(Int, jint, 0)
+gen_jnienv_method(Long, jlong, 0)
+gen_jnienv_method(Float, jfloat, 0)
+gen_jnienv_method(Double, jdouble, 0)
// N == Property method type convention (Long, Float, StaticLong, StaticFloat, etc...)
// T == C type of return value
-#define gen_jnienv_property_call(N, T) \
+// D == Default return value
+#define gen_jnienv_property_call(N, T, D) \
static T \
- JNIEnv_Get##N##Field(JNIEnv *p0, jclass p1, jfieldID p2) { \
- assert(p0 && p1 && p2); \
+ JNIEnv_Get##N##Field(JNIEnv *p0, jclass p1, jfieldID method) { \
+ assert(p0 && p1 && method); \
union { T (*fun)(JNIEnv*, jobject); void *ptr; } f; \
- f.ptr = jvm_wrap_method(jnienv_get_jvm(p0), (jmethodID)p2); \
- return (f.ptr ? f.fun(p0, p1) : 0); \
+ f.ptr = jvm_wrap_method(jnienv_get_jvm(p0), (jmethodID)method); \
+ return (f.ptr ? f.fun(p0, p1) : D); \
} \
static void \
- JNIEnv_Set##N##Field(JNIEnv* p0, jclass p1, jfieldID p2, T p3) { \
- assert(p0 && p1 && p2); \
+ JNIEnv_Set##N##Field(JNIEnv* p0, jclass p1, jfieldID method, T p3) { \
+ assert(p0 && p1 && method); \
+ union { void (*fun)(JNIEnv*, jobject, T); void *ptr; } f; \
+ if ((f.ptr = jvm_wrap_method(jnienv_get_jvm(p0), (jmethodID)method))) \
+ f.fun(p0, p1, p3); \
}
// N == Property type name
// T == C type of return value
-#define gen_jnienv_property(N, T) \
- gen_jnienv_property_call(N, T) \
- gen_jnienv_property_call(Static##N, T)
-
-gen_jnienv_property(Object, jobject)
-gen_jnienv_property(Boolean, jboolean)
-gen_jnienv_property(Byte, jbyte)
-gen_jnienv_property(Char, jchar)
-gen_jnienv_property(Short, jshort)
-gen_jnienv_property(Int, jint)
-gen_jnienv_property(Long, jlong)
-gen_jnienv_property(Float, jfloat)
-gen_jnienv_property(Double, jdouble)
+#define gen_jnienv_property(N, T, D) \
+ gen_jnienv_property_call(N, T, D) \
+ gen_jnienv_property_call(Static##N, T, D)
+
+gen_jnienv_property(Object, jobject, jvm_stub_class_from_method(jnienv_get_jvm(p0), (jmethodID)method))
+gen_jnienv_property(Boolean, jboolean, false)
+gen_jnienv_property(Byte, jbyte, 0)
+gen_jnienv_property(Char, jchar, 0)
+gen_jnienv_property(Short, jshort, 0)
+gen_jnienv_property(Int, jint, 0)
+gen_jnienv_property(Long, jlong, 0)
+gen_jnienv_property(Float, jfloat, 0)
+gen_jnienv_property(Double, jdouble, 0)
static jmethodID
jvm_make_method(struct jvm *jvm, jclass klass, const char *name, const char *sig)