再利用不同的语言来做功能开发的时候,各种不同语言所开的功能模块的融合是一个重要的问题。在Java中提供了一种调用本地方法的机制:JNI(Java Native Interface。虽然java不提倡使用本地接口,但是用C/C++开发的代码可以给我们的工作带来非常大的便利。
以下是编写第一个JNI程序的过程以及所遇到的问题:
第一:
创建一个类,里面包含了一个Native的方法。
例如:建立HelloNative.Java文件,内容如下:
public class HelloNative {
public static native void greet();
}
这里关键字Native说明该方法是一个本地方法。
第二:简历一个测试类来调用该类的本地方法:建立了Test.java如下:
public class Test {
/**
* @param args
*/
public static void main(String[] args) {
HelloNative.greet();
}
static
{
System.loadLibrary("Code");
}
}
这里,System.loadLibrary("Code");中的“Code”使我们要创建的库函数,是一个DLL文件(windows环境下)或者so文件(Linux)。
第三:编写本地方法。在本地方法编写的时候要满足Java的规范。虽然在Test.Java中的方法名是greet();但是我们在编写本地方法的时候却不能也按照这种方法来写。那怎么办呢?编译这个类文件,会产生一个头文件,在头文件中会指明这个方法的本地方法名。具体的步骤如下:
先编译HelloNative.java文件得到HelloNative.class文件,在利用javah命令来产生一个头文件HelloNative.h文件。这个头文件里面的内容不要做任何更改。
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class HelloNative */
#ifndef _Included_HelloNative
#define _Included_HelloNative
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: HelloNative
* Method: greet
* Signature: ()V
*/
JNIEXPORT void JNICALL Java_HelloNative_greet
(JNIEnv *, jclass);
#ifdef __cplusplus
}
#endif
#endif
用到的指令如下:
javac HelloNative.java得到HelloNative.class
javah HelloNative得到HelloNative.h这就是变异号的头文件。
接下来就是库文件的编写了。这里选择的是VS2010来编写库文件。
第四:打开VS2010,选择创建新的项目:Win32 项目。注意不是win32 控制台项目。将输出选择为DLL输出。并将之前所产生的HelloNative.h拷贝到本地的文件夹下面,这样就可以找到该头文件。从头文件中得到函数的方法名:JNIEXPORT void JNICALL Java_HelloNative_greet (JNIEnv *, jclass)
现在为这方法编写函数体实现。
#include "stdafx.h"
#include "jni.h"
#include"stdio.h"
extern "C"
JNIEXPORT void JNICALL Java_HelloNative_greet (JNIEnv *, jclass)
{
printf("this is the first JNI test");
}
这个函数体非常简单。但有些地方要注意:
第一:#include "jni.h"要包含这个头文件。
该头文件的位置位于:java/jdk/include
在VS 2010 中要将这个头文件包含进来。方法:右键“项目名”,选择属性,弹出属性页,选择配置属性中的VC++目录,在选择右侧的“包含目录”将头文件所在的文件夹包含进来。
第二:由于我们实在C++中编写方法体的,所以要加extern "C",避免实现与c++特定的代码。
完成之后,编译生成dll文件。然后将该Dll文件拷贝到jdk/bin目录下面,这样Eclipse中的代码可以找到。
第三,此时可能汇报如下的错误:Can't load IA 32-bit .dll on a AMD 64-bit platform
这个错误是由于生成的Dll是32位所导致的。虽然你用的是64位的机子。解决方法:
将工程的配置改为X64的平台在编译。方法如下:
选择配置管理器,改变活动方法解决平台,选择x64平台。这样就可以产生64位dll。
运行Eclipse的测试程序,就可以看到输出。