title:2_jni基础
JNI的一般开发流程:(java访问native)
1 2 3 4 5
| 1.1定义好本地的 native 方法 1.2javah 命令生成h 头文件 1.3 拷贝 xxx.h、jni_md.h、jih 到 VS 的工程目录并添加依赖进来 1.4实现我们头文件中的 native 方法 1.5 生成 dll 动态,java 引 dl 动态库运行即可
|
流程细节:
// ecplise
1.定义好本地的 native 方法(NdkSimple.java)
1 2 3 4 5 6 7 8 9
| package com.tyl.myStudy; public class NdkSimple { public static void main(String[] args) { NdkSimple ndkSimple = new NdkSimple(); String signaturePassword = ndkSimple.getSingnaturePassword(); System.out.println("秘钥 = "+signaturePassword); } public static native String getSingnaturePassword(); }
|
2.cmd中cd到本文件的路径下执行javah,查看支持的命令;
1 2 3 4 5 6
| 错误:'javah' 不是内部或外部命令 原因:jdk版本太新了,在jdk10及以上的版本中,已经删除了javah,使用"javac -h"命令替代"javah" 解决方案:javac -h ./ NdkSimple.java (错误: 编码 GBK 的不可映射字符 (0x9B) 原因:不能有中文哪怕是注释,添加-encoding UTF-8 解决方案:javac -h ./ NdkSimple.java -encoding UTF-8
|
3.本地路径上出现新生成的文件:com_tyl_myStudy_NdkSimple.h
// visualStudio
4.将com_tyl_myStudy_NdkSimple.h复制到visualStudio的项目根目录中(如:D:\C++Projects\C++Study\Project1)
5.本地java的安装目录中搜索jni,然后将jni.h及jni_md.h文件复制到visualStudio的项目根目录中(如:D:\C++Projects\C++Study\Project1)
6.vs中点击头文件->添加->现有项->将com_tyl_myStudy_NdkSimple.h和jni.h及jni_md.h文件添加进来;
![image-20230710095206945](/../../../../images/image-20230710095206945.png)
![image-20230710095236313](/../../../../images/image-20230710095236313.png)
7.生成dll动态库
7-1:调试–>调试属性->常规->配置类型->动态库(.dll)->应用->确定
7-2:生成->配置管理器->平台处新建->x64或其他根据本地环境->确定
7-3:生成->生成解决方案;提示:生成: 1 成功,0 失败,0 最新,0则成功,文件在项目根目录-x86-debug下的dll文件就是
//ecplise NdkSimple.java
8.引入加载我们的本地库
1 2 3 4 5
| static{ //System.loadlibrary:android加载apk中的libs目录下.so库 // System.load:更载一个具体路径上的.so 库,可以去服务器上下载后下载 System.load("D:\\C++Projects\\C++Study\\Project1\\x64\\Debug\\Project1.dll"); }
|
9.执行调用
10.com_tyl_myStudy_NdkSimple.h头文件字段说明:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| #include "jni.h"
#ifndef _Included_com_tyl_myStudy_NdkSimple #define _Included_com_tyl_myStudy_NdkSimple #ifdef __cplusplus
extern "C" { #endif
JNIEXPORT jstring JNICALL Java_com_tyl_myStudy_NdkSimple_getSingnaturePassword (JNIEnv *, jclass);
#ifdef __cplusplus } #endif #endif
|
11.jni.c的字段说明:
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| #include "com_tyl_myStudy_NdkSimple.h"
JNIEXPORT jstring JNICALL Java_com_tyl_myStudy_NdkSimple_getSingnaturePassword (JNIEnv* env, jclass jobj) { return (*env)->NewStringUTF(env,"5555"); }
|
12.native修改java参数:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| JNIEXPORT void JNICALL Java_com_darren_ndk12_NdkSimple1_changeName (JNIEnv *env, jobject jobj){ jclass j_clz = (*env)->GetObjectClass(env, jobj); jfieldID j_fid = (*env)->GetFieldID(env, j_clz, "name", "Ljava/lang/String;"); jstring j_str = (*env)->GetObjectField(env, jobj, j_fid); char* c_str = (*env)->GetStringUTFChars(env,j_str,NULL); printf("name is %s",c_str); jstring jackName = (*env)->NewStringUTF(env,"Jack"); (*env)->SetObjectField(env, jobj, j_fid, jackName); }
|
13.native调用java方法:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| public int add(int numberl,int number2){ return numberl+number2; }
JNIEXPORT void JNICALL Java_com_darren_ndk12_NdkSimple1_callAddMathod (JNIEnv *env, jobject jobj){ jclass j_clz = (*env)->GetObjectClass(env,jobj); jmethodID j_mid = (*env)->GetMethodID(env, j_clz, "add", "(II)I"); jint sum = (*env)->CallIntMethod(env, jobj, j_mid,2,3); printf("sum = %d",sum); }
|