用 JNI 调用 C 或 C++ 动态联接库原来如此简单
因工作的缘故,有机会接触了 Java 本地方法调用( JNI )。本文中记下了初试 JNI 的过程和一点点体会。
使用 Java 的 JNI 调用 C/C++ 的动态联结库有个固定的步骤,下面将以一个最简单的 HelloWorld 例子程序来说明调用过程。这个 HelloWorld 的例子只是简单的显示 HelloWorld 消息。
第一步 编写 Java 类
首先,我们创建一个名为 jnitest 的 Eclipse 工程,并新建一个 src 源代码目录。
这里我们编写两个 Java 类,一个命名为 HelloWorld ,一个命名为 TestDLL 。 HelloWorld 类包含一个本地方法 displayHelloWorld() , TestDLL 用于测试这个本地方法。 HelloWorld 的源码清单如下:
List1. HelloWorld.java 源码
public class HelloWorld {
public native void displayHelloWorld(); ①
static {
System.loadLibrary( "HelloWorld" ); ②
}
}
TestDLL 源码如下:
List2. TestDLL.java 源码
public class TestDLL {
public static void main(String[] args){
HelloWorld helloWorld = new HelloWorld();
helloWorld.displayHelloWorld();
}
}
说明: ①是java本地方法申明; ②装入动态链接库, "HelloWorld" 是要装入的动态链接库名称。
第二步 编译 Java 类
在 Eclipse 工具中编译 Java 类。编译后的 class 文件会自动放入工程目录下的 bin 目录中。
第三步 生成 C/C++ 头文件
在 windows 中打开一个命令窗口,进入 jnitest 工程所在目录下的 bin 目录如: D:"workspace"jnitest"bin 。键入 javah -classpath D:"workspace"jnitest"bin HelloWorld 命令生成头文件 HelloWorld.h 。内容如下:
List3. HelloWorld.h 源码
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class HelloWorld */
#ifndef _Included_HelloWorld
#define _Included_HelloWorld
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: HelloWorld
* Method: displayHelloWorld
* Signature: ()V
*/
JNIEXPORT void JNICALL Java_HelloWorld_displayHelloWorld
(JNIEnv *, jobject);
#ifdef __cplusplus
}
#endif
#endif
注意,不要修改这个头文件。
第四步 编写本地方法实现
用 VC6 创建 HelloWorld Win32 动态链接库工程。将上述生成的头文件 HelloWorld.h 拷贝到
D:"Program Files"Microsoft Visual Studio"MyProjects"HelloWorld 目录下面。
将 D:"j2sdk1.4.2"include 目录下的 jni.h 和 D:"j2sdk1.4.2"include"win32"jni_md.h 两个头文件拷贝到 VC 安装目录下的 D:"Program Files"Microsoft Visual Studio"VC98"Include 目录下面。在 VC IDE 中新建 HelloWorld.cpp 文件,实现头文件中声明的方法并编译生成 DLL 。
List4. HelloWorld.cpp 源码
#include "HelloWorld.h"
#include <stdio.h>
/*
* Class: HelloWorld
* Method: displayHelloWorld
* Signature: ()V
*/
JNIEXPORT void JNICALL Java_HelloWorld_displayHelloWorld
(JNIEnv *, jobject)
{
printf( "Hello World!"n" );
return ;
}
第五部 运行测试程序
先将生成的 DLL 拷贝到 jnitest 工程的 D:"workspace"jnitest"bin 下面,然后设置 DLL 搜索路径(环境变量 PATH )为 D:"workspace"jnitest"bin ( JNI 并没有规定必须将 dll 放在与 class 文件相同的目录,只要确保 JVM 能搜索到 DLL 即可)③。重新启动 Elipse 后,运行测试程序,将看到控制台输出“ Hello World !”
注意,③必须设置好 DLL 搜索路径,或者将 dll 拷贝到 C:"WINDOWS"system32 下面。这里,我折腾了不少时间,才搞定。
参考资料
Java Native Tutorial
源代码下载
(http://www.matrix.org.cn/resource/article/44/44606_用JNI.html)