使用JNI在JAVA和C++之间进行交互操作
2017-04-26 16:36
656 查看
原文链接地址:
https://library.vuforia.com/articles/Solution/How-To-Communicate-Between-Java-and-C-using-the-JNI
本文旨在描述如何使用JNI(Java Native Interface)实现JAVA和C++之间的互相调用。
1.在JAVA中调用C++方法
假设在ImageTargets.java中,C++方法会被声明为以public native开头的函数,例如:public native int initTracker();
在C++代码文件ImageTargets.cpp 中函数会被声明为:
首先,需要注意的是所有在C++中暴漏的JNI函数都被extern"C"代码块包裹,函数的返回值的前后会有两个宏:JNIEXPORT 和JNICALL。函数名也必须遵循一定的格式:Java_package_class_function。在Java中你可以像调用其他Java函数一样调用JNI函数,例如:
2.在JNI函数中调用Java代码
假设在ImageTargets.java中有函数:
你如果想在C++中调用上面的函数,首先需要从ImageTargets对象查询隶属的ImageTargets类,然后在ImageTargets类中查找getTextureCount 函数,具体实现的C++代码如下:
下面解释一下GetMethodID 函数的最后一个参数“()I”:
将Java函数的参数类型依次放在小括号内;
在小括号后面添加返回值类型;
例如(IF)Z代表入参一个Int一个Float,返回值为Boolean
3.在非JNI函数中调用Java代码
为了在C++中调用Java代码,我们需要JNIEnv对象和Jobject,在JNI函数中这没有问题,因为JNIEnv 和Jobject为前两个入参,但是如果你想在其他的非JNI函数中调用Java函数,就需要将JNIEnv 和Jobject保存为全局变量。
但是将JNIEnv 保存为全局变量是非常危险的,因为JNIEnv不是线程安全的,下面的代码演示了一种安全的方法来使用JNIEnv,那就是使用NewGlobalRef来对Jclass和Jobject做全局的引用:
https://library.vuforia.com/articles/Solution/How-To-Communicate-Between-Java-and-C-using-the-JNI
本文旨在描述如何使用JNI(Java Native Interface)实现JAVA和C++之间的互相调用。
1.在JAVA中调用C++方法
假设在ImageTargets.java中,C++方法会被声明为以public native开头的函数,例如:public native int initTracker();
在C++代码文件ImageTargets.cpp 中函数会被声明为:
#include <jni.h> #ifdef __cplusplus extern "C" { #endif JNIEXPORT int JNICALL Java_com_qualcomm_QCARSamples_ImageTargets_ImageTargets_initTracker(JNIEnv *, jobject) { ... } #ifdef __cplusplus } #endif
首先,需要注意的是所有在C++中暴漏的JNI函数都被extern"C"代码块包裹,函数的返回值的前后会有两个宏:JNIEXPORT 和JNICALL。函数名也必须遵循一定的格式:Java_package_class_function。在Java中你可以像调用其他Java函数一样调用JNI函数,例如:
int result = initTracker();
2.在JNI函数中调用Java代码
假设在ImageTargets.java中有函数:
public int getTextureCount() { return mTextures.size(); }
你如果想在C++中调用上面的函数,首先需要从ImageTargets对象查询隶属的ImageTargets类,然后在ImageTargets类中查找getTextureCount 函数,具体实现的C++代码如下:
JNIEXPORT void JNICALL Java_com_qualcomm_QCARSamples_ImageTargets_ImageTargets_initApplicationNative( JNIEnv* env, jobject obj, jint width, jint height) { ... jclass activityClass = env->GetObjectClass(obj); jmethodID getTextureCountMethodID = env->GetMethodID(activityClass, "getTextureCount", "()I"); if (getTextureCountMethodID == 0) { LOG("Function getTextureCount() not found."); return; } textureCount = env->CallIntMethod(obj, getTextureCountMethodID); ... }
下面解释一下GetMethodID 函数的最后一个参数“()I”:
将Java函数的参数类型依次放在小括号内;
在小括号后面添加返回值类型;
例如(IF)Z代表入参一个Int一个Float,返回值为Boolean
3.在非JNI函数中调用Java代码
为了在C++中调用Java代码,我们需要JNIEnv对象和Jobject,在JNI函数中这没有问题,因为JNIEnv 和Jobject为前两个入参,但是如果你想在其他的非JNI函数中调用Java函数,就需要将JNIEnv 和Jobject保存为全局变量。
但是将JNIEnv 保存为全局变量是非常危险的,因为JNIEnv不是线程安全的,下面的代码演示了一种安全的方法来使用JNIEnv,那就是使用NewGlobalRef来对Jclass和Jobject做全局的引用:
JavaVM* javaVM = NULL; jclass activityClass; jobject activityObj; JNIEXPORT void JNICALL Java_com_qualcomm_QCARSamples_ImageTargets_ImageTargets_initApplicationNative( JNIEnv* env, jobject obj, jint width, jint height) { env->GetJavaVM(&javaVM); jclass cls = env->GetObjectClass(obj); activityClass = (jclass) env->NewGlobalRef(cls); activityObj = env->NewGlobalRef(obj); } void myNativeMethod() { JNIEnv *env; javaVM->AttachCurrentThread(&env, NULL); jmethodID method = env->GetMethodID(activityClass, "myJavaMethod", "()V"); env->CallVoidMethod(activityObj, method); }
相关文章推荐
- 使用JNI进行混合编程:在Java中调用C/C++本地库
- java与c/c++之间的数据交互-----jni点滴
- 关于cocos2dx如何通过jni进行c++与java的交互
- 1 通过JNI混合使用Java和C++ -----> 操作字符串
- 使用JNI进行Java与C/C++语言混合编程(1)--在Java中调用C/C++本地库
- 使用JNI进行混合编程:在C/C++中调用Java代码
- 使用JNI进行Java与C/C++语言混合编程(1)--在Java中调用C/C++本地库
- Java中JNI的使用详解第五篇:C/C++中操作Java中的数组
- Java中JNI的使用详解第五篇:C/C++中操作Java中的数组
- Java中JNI的使用详解第五篇:C/C++中操作Java中的数组
- 使用JNI进行混合编程:在Java中调用C/C++本地库
- 【转】使用JNI进行混合编程:在C/C++中调用Java代码
- 使用JNI进行Java与C/C++语言混合编程(2)--在C/C++中调用Java代码
- java与c/c++之间的数据交互—–jni点滴
- 使用JNI进行混合编程:在C/C++中调用Java代码
- 使用JNI进行混合编程:在Java中调用C/C++本地库
- 使用JNI进行混合编程:在C/C++中调用Java代码--------------------cocos2d-x 3.0正式版本(7.5)
- java与c/c++之间的数据交互-----jni点滴【转】
- Java中JNI的使用详解第五篇:C/C++中操作Java中的数组
- java与c/c++之间的数据交互-----jni点滴【转】【有用】