笔者最近有需求:
在linux环境下,需要用c封装一段算法(考虑到保密性比较高),然后主程序逻辑用java开发,然后用java取调用c语言开发的算法。
其实这样的例子网上也有很多。
本文参考了这篇博客:http://www.2cto.com/kf/201602/490934.html
用java语言,调用c语言封装的函数,打印hello world
ubuntu,openjdk8,sublime text(编辑c和java),gcc
1.用java语言,编写一个api(接口函数),通过javah自动生成 .h头文件
2.编写.c,gcc生成.so文件
3.再写java类,测试调用封装的接口
1.1编写JniHelloWorldApi.java
package com; public class HelloApi{ native void helloworld(); }
helloworld就是交互的函数名
需要注意的是包名是com,如果写了包名,但实际的物理关系与包名不一样,后面会碰到一些问题(写过java的应该都明白我是啥意思)
我的目录结构是这样
1.2编译.java
cd 到helloworld目录下
java com/HelloApi.java
编译成功之后,在com目录下,能看到一个HelloApi.class
1.3动态的生成.h头文件
javah -jni com.HelloApi
-jni
Causes the javah command to create an output file containing
JNI-style native method function prototypes. This is the default
output; use of -jni is optional.
成功之后,可以看到,有com_HelloApi.h生成
.h文件的内容就不展示了
2.1引入.h头文件,编写.c
com_HelloApi.c
#include <stdio.h> #include <jni.h> #include "com_HelloApi.h" JNIEXPORT void JNICALL Java_com_HelloApi_helloworld (JNIEnv * env, jobject obj){ printf("hello world\n"); }
#include <jni.h>和#include "com_HelloApi.h"
函数参数 JNIEnv * env, jobject obj env和obj是笔者加上去的
2.2编译成.o
命令为:gcc -fPIC -D_REENTRANT -I /usr/lib/jvm/java-8-openjdk-i386/include -I /usr/lib/jvm/java-8-openjdk-i386/include/linux -c com_HelloApi.c
其中 /usr/lib/jvm/java-8-openjdk-i386是jdk的位置,如果不清楚,可以使用whereis java命令进行确认
2.3编译成.so
gcc -shared com_HelloApi.o -o com_HelloApi.so
成功之后可以看到 com_HelloApi.so生成
为了图方便,笔者,继续在HelloApi中修改,代码为:
package com; public class HelloApi{ native void helloworld(); static{ System.load("/home/robin/文档/jni-test/helloworld/com_HelloApi.so"); } public static void main(String[] args) { HelloApi ha=new HelloApi(); ha.helloworld(); } }
main是我的测试函数
然后再此javac
最后通过 java com.HelloApi可以看到输出