当前位置:首页 > 移动端 > Android NDK开发三:java和C\C++交互

Android NDK开发三:java和C\C++交互

2022年08月04日 20:04:36移动端2
转自: http://www.cnblogs.com/shangdahao/archive/2013/05/02/3053971.html

1、定义native方法并加载动态链接库:
public class HelloJni extends Activity
{
    @Override
    public void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);

        TextView  tv = new TextView(this);
        tv.setText( stringFromJNI() );
        setContentView(tv);
    }


    public native String  stringFromJNI();


    public native String  unimplementedStringFromJNI();


    static {
        System.loadLibrary("hello-jni");
    }
}

2、实现native方法:
#include <string.h>
#include <jni.h>
jstring
Java_com_example_hellojni_HelloJni_stringFromJNI( JNIEnv* env,
jobject thiz )
{
return (*env)->NewStringUTF(env, "Hello from JNI !"); //in c
return env->NewStringUTF("Hello from JNI !");         //in c++

}

若要定义静态方法:
JNIEXPORT jstring JNICALL Java_com_example_hellojni_HelloJni_stringFromJNI
(JNIEnv * env, jclass clazz);

头文件可以用javah工具生成:
进入命令行,切换到项目的bin目录下的classes下面,执行 javah -classpath . -jni 包.类名。
或者:cd 到src目录中,执行 javah 包.类名

3、数据
原始数据类型:
Android NDK开发三:java和C\C++交互 _ JavaClub全栈架构师技术笔记

引用数据类型:
Android NDK开发三:java和C\C++交互 _ JavaClub全栈架构师技术笔记

4、字符窜的操作:
1)新建字符串:
jstring javaString;

javaString = (*env)->NewStringUTF(env, "Hello World!");

2)把java string转换成c string
const jbyte* str;
jboolean isCopy;
str = (*env)->GetStringUTFChars(env, javaString, &isCopy);
if (0 != str) {
printf("Java string: %s", str);
if (JNI_TRUE == isCopy) {
printf("C string is a copy of the Java string.");
} else {
printf("C string points to actual string.");
}
(*env)->ReleaseStringUTFChars(env, javaString, str);

5、数组的操作:
1)新建java数组:
jintArray javaArray;
javaArray = (*env)->NewIntArray(env, 10);
if (0 != javaArray) {
/* You can now use the array. */
}

2)获取数组的值:
jint nativeArray[10];
//将java array 复制到 c array
(*env)->GetIntArrayRegion(env, javaArray, 0, 10, nativeArray);
//将 c array 还原城 java array
(*env)->SetIntArrayRegion(env, javaArray, 0, 10, nativeArray);

获取数组指针:
jint* nativeDirectArray;
jboolean isCopy;
nativeDirectArray = (*env)->GetIntArrayElements(env, javaArray, &isCopy);
//...
(*env)->ReleaseIntArrayElements(env, javaArray, nativeDirectArray, 0);

6、C\C++获取java成员变量
public class JavaClass {
/** Instance field */
private String instanceField = "Instance Field";
/** Static field */
private static String staticField = "Static Field";
...
}

1)获取Field ID
jclass clazz;
clazz = (*env)->GetObjectClass(env, instance);
 
jfieldID instanceFieldId;
instanceFieldId = (*env)->GetFieldID(env, clazz,
"instanceField", "Ljava/lang/String;");
 
jfieldID staticFieldId;
staticFieldId = (*env)->GetStaticFieldID(env, clazz,
"staticField", "Ljava/lang/String;");

2)获取Static Field
jstring staticField;
staticField = (*env)->GetStaticObjectField(env, clazz, staticFieldId);

7、C\C++调用java函数
public class JavaClass {
/**
* Instance method.
*/
private String instanceMethod() {
return "Instance Method";
}
/**
* Static method.
*/
private static String staticMethod() {
return "Static Method";
}
...
}

1)获取Method ID:
成员函数:
jmethodID instanceMethodId;
instanceMethodId = (*env)->GetMethodID(env, clazz,
"instanceMethod", "()Ljava/lang/String;");

静态函数:
jmethodID staticMethodId;
staticMethodId = (*env)->GetStaticMethodID(env, clazz,
"staticMethod", "()Ljava/lang/String;");

2)调用:
jstring instanceMethodResult;
instanceMethodResult = (*env)->CallStringMethod(env,
instance, instanceMethodId);

变量和函数的描述符:
Android NDK开发三:java和C\C++交互 _ JavaClub全栈架构师技术笔记
javap工具可以提取从编译过的class files 中提取这些描述符:
javap –classpath bin/classes –p –s com.example.hellojni.HelloJni

8、处理异常:
public class JavaClass {
/**
* Throwing method.
*/
private void throwingMethod() throws NullPointerException {
   throw new NullPointerException("Null pointer");
}
/**
* Access methods native method.
*/
private native void accessMethods();
}

jthrowable ex;
...
(*env)->CallVoidMethod(env, instance, throwingMethodId);
ex = (*env)->ExceptionOccurred(env);
if (0 != ex) {
(*env)->ExceptionClear(env);
/* Exception handler. */
}

从c\c++抛异常:
jclass clazz;
...
clazz = (*env)->FindClass(env, "java/lang/NullPointerException");
if (0 ! = clazz) {
(*env)->ThrowNew(env, clazz, "Exception message.");
}

9、本地和全局变量:
1)本地变量在函数结束时自动释放内存:
jclass clazz;
clazz = (*env)->FindClass(env, "java/lang/String");

2)新建全局变量:
jclass localClazz;
jclass globalClazz;
...
localClazz = (*env)->FindClass(env, "java/lang/String");
globalClazz = (*env)->NewGlobalRef(env, localClazz);
...
(*env)->DeleteLocalRef(env, localClazz);

3)释放全局变量:
(*env)->DeleteGlobalRef(env, globalClazz);

4)弱全局引用:
弱全局引用可以被内存自动回收:
jclass weakGlobalClazz;
weakGlobalClazz = (*env)->NewWeakGlobalRef(env, localClazz);
if (JNI_FALSE == (*env)->IsSameObject(env, weakGlobalClazz, NULL)) {
/* Object is still live and can be used. */
} else {
/* Object is garbage collected and cannot be used. */
}
(*env)->DeleteWeakGlobalRef(env, weakGlobalClazz);

10、线程:
synchronized(obj) {
/* Synchronized thread-safe code block. */
}

if (JNI_OK == (*env)->MonitorEnter(env, obj)) {
/* Error handling. */
}
/* Synchronized thread-safe code block. */
if (JNI_OK == (*env)->MonitorExit(env, obj)) {
/* Error handling. */
}

native线程不能和java直接通信,必须先绑定到javaVM
JavaVM* cachedJvm;
...
JNIEnv* env;
...
/* Attach the current thread to virtual machine. */
(*cachedJvm)->AttachCurrentThread(cachedJvm, &env, NULL);
/* Thread can communicate with the Java application
using the JNIEnv interface. */
/* Detach the current thread from virtual machine. */
(*cachedJvm)->DetachCurrentThread(cachedJvm);





来源链接:https://www.cnblogs.com/sesexxoo/p/6189938.html

版权声明:
1、JavaClub(https://www.javaclub.cn)以学习交流为目的,由作者投稿、网友推荐和小编整理收藏优秀的IT技术及相关内容,包括但不限于文字、图片、音频、视频、软件、程序等,其均来自互联网,本站不享有版权,版权归原作者所有。

2、本站提供的内容仅用于个人学习、研究或欣赏,以及其他非商业性或非盈利性用途,但同时应遵守著作权法及其他相关法律的规定,不得侵犯相关权利人及本网站的合法权利。
3、本网站内容原作者如不愿意在本网站刊登内容,请及时通知本站(javaclubcn@163.com),我们将第一时间核实后及时予以删除。


本文链接:https://www.javaclub.cn/mobile/17381.html

分享给朋友:

“Android NDK开发三:java和C\C++交互” 的相关文章

Flutter 深入探索混合开发的技术演进

Flutter 深入探索混合开发的技术演进

关于 Flutter 混合 PlatformView 的实现已经介绍过两次,随着 5 月份谷歌 IO 的接近,新的 PlatformView 实现应该也会随之而来,本次就从头到尾来一个详细的关于 PlatformView 的演进总结。 F...

HBuilder X 连接苹果手机(IOS)详细教程。Windows: 连接iOS手机调试项目

HBuilder X 连接苹果手机(IOS)详细教程。Windows: 连接iOS手机调试项目

手机:苹果11,IOS版本:15.0 1.HBuilder X要是最新版本。 2.需要下载iTunes,注意事项: Windows 32位 itunes下载地址 Windows 64位 itunes下载地址 建议从如上地址下载...

flutter中state详解

flutter中state详解

State 在说到StatefulWidget之前,先说下State。State的作用有两点: 在widget构建的时候可以被同步读取; 在widget的生命周期中可能会被改变。 State生命周期 State...

Flutter 调用地图软件(高德、百度、腾讯、苹果)同时实现另类国际化

文章目录 Flutter 调用地图软件(高德、百度、腾讯、苹果) 一、说明 第 1 类:App 集成导航功能 第 2 类:跳转...

android studio 第一个程序显示radle d 'https://services.gradle.org/distributions/gradle

android studio 第一个程序显示radle d 'https://services.gradle.org/distributions/gradle

复制链接下载https://services.gradle.org/distributions/gradle-5.4.1-all.zip 并复制到C盘 C:\Users\luckly.gradle\wrapper\dists\gradle-5.4.1-a...

在Flutter中解析复杂的JSON(一篇顶十篇)

在Flutter中解析复杂的JSON(一篇顶十篇)

文章目录 JSON结构#1:简单 map 访问对象 Snippet #1 : imports **Snippet #2 : **加载Json Asset(可选)**...

flutter分平台主题定制

有时候,为了满足不同平台的用户需求,我们希望针对特定的平台设置不同的样式。比如,在 iOS 平台上设置浅色主题,在 Android 平台上设置深色主题。面对这样的需求,我们可以根据 defaultTargetPlatform 来判断当前应用所运行...

国内常用的学习flutter地址

国内常用的学习flutter地址 https://flutter.cn/ https://flutterchina.club/ https://www.kancloud.cn/alex_wsc/flutter_demo/1559...

flutter项目如何打包(android)

flutter项目如何打包(android)

打包前要做的 1.更换图标 andriod–》app–app–》src—》main-》Java----》res–》minpmap 其实这个打包的坑还是比较多的,官方文档显然是站在大神级程序员的角度写的,所以如果你看文档,特别是前...

flutter实现底部弹出框以及特色功能

flutter实现底部弹出框以及特色功能

今天项目中要实现底部弹出框并且实现圆角功能,先来预览一下 可以看出实现的公告有 底部圆角,以及朋友圈,微信转发等 实现逻辑我直接代码列出 定义 List<String> nameItems = <S...

发表评论

访客

◎欢迎参与讨论,请在这里发表您的看法和观点。