JNI
java native interface
c的基本数据类型
int:4字节 数据范围-2的31次方到2的31次方-1;
unsigned 数据范围为0-2的32次方-1;
java基本数据长度与C对比
- byte:1
- short:2 与c中short int型字节长度相同
- int:4
- long:8 !!与c中long long型字节长度相同
- boolean:1 !!
- char:2 !!与c中short int型字节长度相同
- float:4
- double:8
BufferReader stdin =new BufferReader(new InputStreamReader(System.in));
String str=stdin.readLine();
System.out.println(str);
*的三种用法
- 乘法
- int *p:定义存放的数据是int型;
- *p:取出p中保存的地址所存放的数据;
数据传递
- 所有语言所有平台,都只有值传递,引用传递传递的值是内存地址
栈
- 系统自动分配和释放
- 保存全局、静态、局部变量
- 在栈上分配内存叫静态分配
- 大小一般是固定的
堆
- 程序员手动分配(malloc/new)和释放(free/java不用手动释放)
- 在堆上分配内存叫动态分配
- 一般硬件内存有多大就有多大
交叉编译
- 在一个平台下,编译出另一个平台能够执行的二进制代码。
- 平台:windows,mac os,linux
- 处理器:x86,arm,mips(开源的)
交叉编译的原理
- 源代码->编译->链接->可执行程序
- 模拟其他平台的特性
交叉编译的工具链
- 多个工具的集合,一个工具使用完使用下一个工具
常用工具
- NDK:native develop kit:开发jni必备,就是模拟其他平台特性来编译代码的工具
- CDT:C/C++ development tools:高亮显示关键字
- cygwin:一个模拟器,可以在windows下运行linux命令
Ndk目录结构
- docs:帮助文档
- build/tools:linux的批处理文档
- platforms:编译c代码使用的头文件和类库
- prebuilt:预编译使用的二进制可执行文件
- sample:jni的使用例子
- source:ndk的源码
- toolchains:工具链
- ndk-build.cmd:编译打包c代码的一个指令。
使用jni
- 在项目根目录下创建jni文件夹
- 在jni文件中创建一个c文件
在java代码中,创建一个本地方法helloFromC
public native String helloFromC();
在jni中定义函数实现这个方法,函数名必须为
jstring Java_com_itheima_helloworld1_MainActivity_helloFromC(JNIEnv* env, jobject obj)
返回一个字符串,用c定义一个字符串
char* cstr = "hello from c";
把c的字符串转换成java的字符串
jstring jstr = (*env)->NewStringUTF(env, cstr); return jstr;
- 在jni中创建Android.mk文件
- 在c文件中添加
常见错误
findLibrary returned null
- CPU平台不匹配
- 加载类库时,写错类库名字
本地方法找不到
- 忘记加载类库
- c代码中方法名写错了
javah 自动生成c方法名
*1.7:在src目录下执行javah 包名.类名
*1.6:在bin/classes目录下执行
javap
- 在bin/class目录下执行javap -s 包名.类名
- 打印方法签名
c向c++改造
- 把c文件后缀名换成cpp
- Android.mk对应名称改为cpp文件
- c++中对应jni.h文件,需要修改的地方将方法里面含有env的去掉。
- 访问函数env指针时,env->就可以了,env为一级指针。
- clean整个项目,清除原来c文件。