Ubuntu环境下编译so-jni调用c语言

时间:2022-09-29 11:24:51

首先确保电脑要安装了jdk和gcc编译环境。

1.这是我写的一个Java程序:

public class TestJNI {
static{
System.loadLibrary("diaoyong"); //程序在加载时,自动加载libdiaoyong.so库
}
public native void set(int value); //声明原生函数。注意要添加native关键字
public native int get();
public static void main(String[] args) {
TestJNI test=new TestJNI();
test.set(1);
System.out.println(test.get());
}
}



2.直接用命令编译它   javac TestJNI.java得到class文件

3.再用javah带-jni参数编译TestJNI.class文件生成TestJNI.h文件。该文件中定义了c的函数原型。在实现c函数的时候需要。 命令:javah -jni TestJNI

这时候生成一个TestJNI.h的头文件,内容:

/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class TestJNI */

#ifndef _Included_TestJNI
#define _Included_TestJNI
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: TestJNI
* Method: set
* Signature: (I)V
*/
JNIEXPORT void JNICALL Java_TestJNI_set
(JNIEnv *, jobject, jint);

/*
* Class: TestJNI
* Method: get
* Signature: ()I
*/
JNIEXPORT jint JNICALL Java_TestJNI_get
(JNIEnv *, jobject);

#ifdef __cplusplus
}
#endif
#endif
 这里JNIEXPORT和JNICALL都是JNI的关键字,表示此函数是要被JNI调用的。而jint是以JNI为中介使Java的int类型与本地的int沟通的一种类型,我们可以视而不见,就当做int使用。函数的名称是Java_再加上Java程序的package路径再加函数名组成的。参数中, 我们也只需要关心在Java程序中存在的参数,至于JNIEnv*和jclass我们一般没有必要去碰它。

4.现在我们就去编写一个C程序,实现里面的方法:testJni.c文件

#include <stdio.h> 
#include "TestJNI.h" //引用刚才的头文件
int i=0;
JNIEXPORT void JNICALL Java_TestJNI_set (JNIEnv * env, jobject obj, jint j) //j 就是TestJin.java set方法里面<pre name="code" class="java" style="color: rgb(51, 51, 51); font-size: 16px; line-height: 28px; text-align: justify;">的value参数
{ i=j+1; //这里实现自己的代码逻辑} JNIEXPORT jint JNICALL Java_TestJNI_get (JNIEnv * env, jobject obj) { printf("congratulations success\n"); //这里实现自己的代码逻辑 return i; }

 


5.现在就生成 生成对象文件TestJNI.o。命令:

gcc -Wall -fPIC -c testJni.c -I ./ -I /usr/local/jdk1.7.0_67/include/linux/ -I /usr/local/jdk1.7.0_67/include/

/usr/local/jdk1.7.0_67/include/linux/是我的jdk安装的路径-Wall:打开警告开关。-fPIC:表示编译为位置独立的代码,不用此选项的话编译后的代码是位置相关的所以动态载入时是通过代码拷贝的方式来满足不同进程的需要,而不能达到真正代码段共享的目的。这时生成一个testJni.o的文件。



6.然后生成动态链接库libdiaoyong.so文件,(注意:动态链接库的名字必须是 lib*.so,因为编译器查找动态连接库时有隐含的命名规则,即在给出的名字前面加上lib,后面加上.so来确定库的名称。这里是libdiaoyong.so对应于Java程序里的diaoyong) 选项 -rdynamic 用来通知链接器将所有符号添加到动态符号表中。-shared指编译后会链接成共享对象。命令是:

gcc -Wall -rdynamic -shared -o libdiaoyong.so testJni.o    

生成libdiaoyong.so文件。


运行java TestJni结果打出 congratulations success  和2就成功了。