2023-01-21 301
我试图使用Android中的JNI从我的C代码中调用Java函数,但是我的情况有些尴尬.
我的C代码在传递给库的回调中在JNI函数之外执行.
这是Java代码的示例
package com.my.java.package;
class MyClass {
public function handleData(byte[] data) {
doSomethingWithThisData(data);
}
}
这是C代码的示例
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;
现在,每当C lib做需要做的事情时,它将触发回调.但是我无法将其发送回Java类来处理数据.
我注意到 brandons解决方案,特别是在您处理状态代码和不必要的方式的方式上, getJavaVM功能,所以我做了一些更改并添加了一些笔记.这是我设法工作的唯一功能版本.
请注意,出于某种原因,JNIEnv* getJNIEnv()返回的JNIEnv*在从另一个线程中使用 时,getJNIEnv()返回的Java类Loader .我不确定为什么.因此,在此示例中,我将静态实例存储到类中,将它们直接加载到JNI_OnLoad函数中,然后在需要时使用它们.
如果有人知道要解决JNIEnv* getJNIEnv()返回JNIEnv*以支持其他线程的Java类加载程序,请让我知道.
// JavaVM instance stored after JNI_OnLoad is called
JavaVM* javaVM = NULL;
// Since the class loader will not work with getJNIEnv(),
// you can store classes in GlobalRefs.
static jclass my_class_class;
/**
* Load the JNIEnv and store the JavaVM instance for ater calls to getJNIEnv().
*
* @param jvm The Java VM
* @param reserved Reserved pointer
*
* @return The supported version of JNI.
*/
JNIEXPORT jint JNICALL
JNI_OnLoad(
JavaVM* jvm,
void* reserved
) {
javaVM = jvm;
// Here we load the classes since getJNIEnv() does
// not work with the class loader from other threads
JNIEnv* env = getJNIEnv();
my_class_class= (*env)->NewGlobalRef(env, (*env)->FindClass(env, "com/my/java/package/MyClass"));
// Return the supported JNI version.
return JNI_VERSION_1_6;
}
/**
* Retrieve an instance of JNIEnv to use across threads.
*
* Note that the class loader will not work with this instance (unsure why).
*
* @return a JNIEnv instance
*/
JNIEnv* getJNIEnv() {
JNIEnv *env;
// If the current thread is not attached to the VM,
// sets *env to NULL, and returns JNI_EDETACHED.
//
// If the specified version is not supported, sets *env to NULL,
// and returns JNI_EVERSION.
//
// Otherwise, sets *env to the appropriate interface, and returns JNI_OK.
int status = (*javaVM)->GetEnv(javaVM, (void**)&env, JNI_VERSION_1_6);
// Check if the JVM is not currently attached to the
// calling thread, and if so attempt to attach it.
if (status == JNI_EDETACHED) {
// Attaches the current thread to a Java VM.
// Returns a JNI interface pointer in the JNIEnv argument.
status = (*javaVM)->AttachCurrentThread(javaVM, &env, NULL);
}
// If the result of GetEnv was JNI_EVERSION,
// we want to abort.
assert(status != JNI_EVERSION);
// Return the ENV if we have one
return env;
}
void handleData(uint8_t *data, size_t len) {
JNIEnv* env = getJNIEnv();
// ... call jni function using env and my_class_class ...
}
在某些版本的Android NDK,JNI_GetCreatedJavaVMs可以使用当前的VM.但是,更好的选择是覆盖JNI_OnLoad并保存在此处.使用这两种方法,一旦拥有VM,就可以连接到当前线程并获取函数.
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);
}
}
}
以上所述是小编给大家介绍的在JNI函数(Android)外从C中调用Java的功能?,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对77isp云服务器技术网的支持!
原文链接:https://77isp.com/post/26229.html
=========================================
https://77isp.com/ 为 “云服务器技术网” 唯一官方服务平台,请勿相信其他任何渠道。
数据库技术 2022-03-28
网站技术 2022-11-26
网站技术 2023-01-07
网站技术 2022-11-17
Windows相关 2022-02-23
网站技术 2023-01-14
Windows相关 2022-02-16
Windows相关 2022-02-16
Linux相关 2022-02-27
数据库技术 2022-02-20
抠敌 2023年10月23日
嚼餐 2023年10月23日
男忌 2023年10月22日
瓮仆 2023年10月22日
簿偌 2023年10月22日
扫码二维码
获取最新动态