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

首先确保电脑要安装了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就成功了。














posted on   愤怒的苹果ext  阅读(40)  评论(0编辑  收藏  举报

编辑推荐:
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现

导航

< 2025年3月 >
23 24 25 26 27 28 1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31 1 2 3 4 5
点击右上角即可分享
微信分享提示