JNI基础(一):Java程序调用C/C++

时间:2020-12-13 20:20:18

JNI(Java Native Interface)

Java是跨平台的语言,但是在有些时候仍然是需要调用本地代码(这些代码通常是由C/C++编写的)

Sun公司提供的JNI是Java平台的一个功能强大的接口。这个JNI接口提供了Java与操作系统本地代码互相调用的功能


 

最简单的Java调用C/C++代码的步骤

1.首先在Java类中声明一个native的方法:

public class TestNative {
public native void sayHello();
……
}

2.使用Javah命令生成包含native方法定义的C/C++头文件(在JDK的bin目录下找javah.exe):javah com.xx.TestNative(完整包名class文件)

我的class文件是在D:\Users\Administrator\Workspaces\MyEclipse\TestNative\bin ,所以从命令行进入到此文件夹中,执行 javah com.jim.test.TestNative

得到com_jim_test_TestNative.h ,一个C++的头文件:

 1 /* DO NOT EDIT THIS FILE - it is machine generated */
2 #include "jni.h"
3 /* Header for class com_jim_test_TestNative */
4
5 #ifndef _Included_com_jim_test_TestNative
6 #define _Included_com_jim_test_TestNative
7 #ifdef __cplusplus
8 extern "C" {
9 #endif
10 /*
11 * Class: com_jim_test_TestNative
12 * Method: sayHello
13 * Signature: ()V
14 */
15 JNIEXPORT void JNICALL Java_com_jim_test_TestNative_sayHello
16 (JNIEnv *, jobject);
17
18 #ifdef __cplusplus
19 }
20 #endif
21 #endif

3.按照生成的C/C++头文件来写C/C++源文件

使用Visual Studio创建一个dll的控制台程序,并根据头文件中的方法编写源文件source.cpp:

1 #include <iostream>
2 #include "com_jim_test_TestNative.h"
3 using namespace std;
4
5 JNIEXPORT void JNICALL Java_com_jim_test_TestNative_sayHello(JNIEnv * env, jobject obj){
6 cout<<"Hello World!"<<endl;
7 }

本程序为显示,只打印Hello World!

4.将C++源文件编译成动态链接库(DLL)

但是此时编译肯定会出错,因为在com_jim_test_TestNative.h中的第二行,还行引入jni.h头文件,这个头文件在哪呢,在JDK底下的include目录下,但是还没完,这个头文件又引入了jni_md.h,所以我们还要引入include/win32下的jni_md.h,好了总算全部引入完了- -但还有些细微之处就是要把#include <xxx.h> 改成 #include "xxx.h" 从标准库路径开始查找变为从当前目录下查找,否则程序还是不能编译报错。

JNI基础(一):Java程序调用C/C++

5.将DLL文件加入到Java程序中

成功编译之后,我们离胜利就不远了,接下来要做的就是把编译生成的dll文件放在classpath下,一种方法是设置环境变量,另一种是将dll文件直接拷贝过去,反正随便你喜欢哪一种,我是把dll文件直接拷贝到java程序的工程目录下,这时候再执行java程序:

1 public class TestNative {
2 public native void sayHello();
3 public static void main(String[] args) {
4 System.loadLibrary("TestNative");//使用loadLibrary方法加载DLL文件
5 TestNative tn=new TestNative();
6 tn.sayHello();
7 }
8 }

不出意外的话成功显示:Hello World!

 

出意外的话那就不好说了,我第一次尝试用的CodeBlocks就悲剧了,因为自带的是gcc/g++的编译器,编译出来的dll文件是不能正常被JNI调用的,貌似编译的时候还要额外添加命令,具体可以在网上查找一下,我试了下太过麻烦,就直接换Visual Studio了,用VS是完全没有问题的。