问题
I'm trying to call a Java function from my C code using the JNI in Android, but I'm in a somewhat awkward situation.
My C code is being executed outside of a JNI function in a callback that is passed to a library.
Here is an example of the java code
package com.my.java.package;
class MyClass {
public function handleData(byte[] data) {
doSomethingWithThisData(data);
}
}
Here is an example of the C code
void handleData(uint8_t *data, size_t len) {
// I need to call handleData in my java
// class instance from here, but i have
// no access to a JNIEnv here.
// I don't think I can create one, since
// it has to be the same object that's
// sending JNI calls elsewhere.
}
. . .
myCLibInstance.callback = handleData;
Now whenever the C Lib does what it needs to do, it will trigger the callback. But I have no way to send it back to the java class to handle the data.
回答1:
On some version of the Android NDK, JNI_GetCreatedJavaVMs
could be used to get the current VM.. however, the better option is to override JNI_OnLoad
and save the VM there. Using either method, once you have the VM, you can attach to the current thread and get call the function..
extern jint JNI_GetCreatedJavaVMs(JavaVM **vm, jsize size, jsize *size2);
static JavaVM *jvm = NULL;
static jint JNI_OnLoad(JavaVM* vm, void* reserved) {
jvm = vm;
JNIEnv *env = NULL;
if (jvm && (*jvm)->GetEnv(jvm, (void**)&env, JNI_VERSION_1_6) == JNI_OK)
{
return JNI_VERSION_1_6;
}
return -1;
}
JavaVM* getJavaVM() {
if (jvm)
{
return jvm;
}
jint num_vms = 0;
const jint max_vms = 5;
JavaVM* vms[max_vms] = {0};
if (JNI_GetCreatedJavaVMs(vms, max_vms, &num_vms) == JNI_OK)
{
for (int i = 0; i < num_vms; ++i)
{
if (vms[i] != NULL)
{
return vms[i];
}
}
}
return NULL;
}
void handleData(uint8_t *data, size_t len) {
JavaVM *jvm = getJavaVM();
if (jvm)
{
JNIEnv *env = NULL;
if ((*jvm)->AttachCurrentThread(jvm, (void **)&env, NULL) == JNI_OK)
{
if (env)
{
//Call function with JNI..
}
(*jvm)->DetachCurrentThread(jvm);
}
}
}
来源:https://stackoverflow.com/questions/44447454/call-a-function-in-java-from-c-outside-of-a-jni-function-android