前言
本文主要描述了利用jni传递和返回基本数据类型(int),采用了java和c语言,操作系统为ubuntu linux,无ide
1 java程序
采用最基本的java程序,无任何复杂操作
/**
* Created by act64 on 2017/5/25.
*/
public class JniHello {
static{
//在linux系统下,含android ,此命令自动解析为
//加载 lib目录下的libnativehello.so文件
System.loadLibrary("nativehello");
}
public static void main(String[]arg){
JniHello jniHello =new JniHello();
System.out.println( jniHello.hello(1));
}
//native 表示这是个native方法
public native int hello(int num);
}
c 文件
之前写过的博客简单起见,用javac javah命令生成 头文件,然后使用,这次采取jniOnload的方式自定义适配,更灵活也更明确
程序名hello.c
#include <stdio.h>
#include <jni.h>
//这是c程序的实现函数,基本数据类型的使用比较简单
jint c_hello(JNIEnv * env, jobject mJobject,jint val){
printf("hello,%d,jni",val);
return 100;
}
//这是jni.h提供的方法映射结构体,用于映射
//java方法和c方法
//三个参数为 java函数名 , 描述符,和c的函数指针
const JNINativeMethod methods[]={
{"hello","(I)I",(jint *)c_hello},
};
//此JNI_OnLoad是系统函数
//当java loadlibrary时会自动调用
//
JNIEXPORT jint JNICALL
JNI_OnLoad(JavaVM *jvm, void *reserved)
{
JNIEnv *env;
jclass cls;
//获得context,并且取得目标java类
if ((*jvm)->GetEnv(jvm, (void **)&env, JNI_VERSION_1_4)) {
return JNI_ERR; /* JNI version not supported */
}
cls = (*env)->FindClass(env, "JniHello");
if (cls == NULL) {
return JNI_ERR;
}
//将java方法和对应的c方法映射,第四个参数是映射的条数
if((*env)->RegisterNatives(env,cls,methods,1)<0){
return JNI_ERR;
}
return JNI_VERSION_1_4;
}
编译
- 1 需要确保java文件和c文件在一个目录下
- 2 cd 所在目录 编译so文件
gcc -fPIC -I /usr/lib/jvm/java-1.7.0-openjdk-amd64/include -shared -o libnativehello.so hello.c
这里面 -I 后面的/usr/lib/jvm/java-1.7.0-openjdk-amd64/include目录指的是jni.h所在的目录,使用时请自行查找替换
- 3 编译java文件
javac JniHello.java
- 4 测试代码
//先 标示lib的目录
//此操作在当前terminal一直有些
export LD_LIBRARY_PATH=./
java JniHello
输出结果如下:
结语
折腾了一阵子,算是弄好了一个简单地了,下一篇写一写jni和java类之间的交互