JNI之HelloWorld

笔者最近有需求:

在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.用java语言,编写一个api(接口函数),通过javah自动生成 .h头文件

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.编写.c,gcc生成.so文件

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生成


3.再写java类,测试调用封装的接口

为了图方便,笔者,继续在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();
	}
}

System.load()中,参数为.so文件的绝对路径

main是我的测试函数

然后再此javac

最后通过 java com.HelloApi可以看到输出





你可能感兴趣的:(jni)