您的位置:首页 > 编程语言 > C语言/C++

Java通过JNI调用C++动态链接库

2010-12-22 11:14 627 查看
参考:http://www.91linux.com/html/article/program/java/20090802/17735.html

Java通过JNI调用C++动态链接库
JAVA通过JNI调用本地方法,而本地方法是以库文件的形式存放的(在WINDOWS平台上是DLL文件形式,在UNIX机器上是SO文件形式)。通过调用本地的库文件的内部方法,使JAVA可以实现和本地机器的紧密联系,调用系统级的各接口方法。
一、JAVA中所需要做的工作
程序TestDll.java
public class TestDll {
//在JAVA程序中,首先需要在类中声明所调用的库名称。在这里,库的扩展名字可以//不用写出来,究竟是DLL还是SO,由系统自己判断 static
{
System.loadLibrary("hello");
}
//还需要对将要调用的方法做本地声明,关键字为native。并且只需要声明,而不需
//要具体实现。
public native static int get();
public native static void set(int i);

public static void main(String[] args)
{
TestDll test = new TestDll();
test.set(10);
System.out.println(test.get());
}
}
然后编译该JAVA程序文件,生成CLASS,再用JAVAH命令,JNI就会生成C/C++的头文件。

用javac TestDll.java编译它,会生成TestDll.class。

再用javah TestDll,则会在当前目录下生成TestDll.h文件,这个文件需要被C/C++程序调用来生成所需的库文件。

注意:将TestDll.java 放在D盘下(当然可以放在其他位置)。
C:/Documents and Settings/student>javac D:/ TestDll.java
则会在D盘下生成TestDll.class.
C:/Documents and Settings/student>javah D:/ TestDll
此时会提示错误:“javadoc:错误-非法的软件包名称:D:/ TestDll”。
解决办法:转换到TestDll.class所在目录,然后使用javah命令,即
C:/Documents and Settings/student>D:
D:/>javah TestDll
此时会在D盘下生成TestDll.h。内容如下所示。
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class TestDll */

#ifndef _Included_TestDll
#define _Included_TestDll
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: TestDll
* Method: get
* Signature: ()I
*/
JNIEXPORT jint JNICALL Java_TestDll_get
(JNIEnv *, jclass);
/*
* Class: TestDll
* Method: set
* Signature: (I)V
*/
JNIEXPORT void JNICALL Java_TestDll_set
(JNIEnv *, jclass, jint);

#ifdef __cplusplus
}
#endif
#endif
二、C/C++中所需要做的工作

对于已生成的testdll.h头文件,C/C++所需要做的,就是把它的各个方法具体的实现。然后编译连接成库文件即可。再把库文件拷贝到JAVA程序的路径下面,就可以用JAVA调用C/C++所实现的功能了。

用vs2005新建vc++ -> 类库项目,项目名称与 System.loadLibrary("hello"); 中的hello相同。将javah生成的testdll.h中内容拷贝到工程的hello.h文件,在hello.cpp文件中加入如下代码:

int i = 0;

JNIEXPORT jint JNICALL Java_testdll_get (JNIEnv *, jclass)

{

return i;

}

JNIEXPORT void JNICALL Java_testdll_set (JNIEnv *, jclass, jint j)

{

i = j;

}

编译时要用到一些Java里面的头文件,所以应该把位于下面目录 D:/jdk6/include

中的所有文件都拷到 C:/Program Files/Microsoft Visual Studio 8/VC/include 目录下。 上面两个路径依自己的机子而定 若不拷到这里的话,也可以明确指定路径。或者在java程序目录下建立一个include目录,将 D:/jdk6/include

中的所有文件都拷到该目录中。要不然会报错,说找不jni.h文件。

在vc2005中的工程项目属性中选中C/C++,在右边的附加包含目录项中加入目录:E:/ProgramLib/Java/testdll/include (这是我java程序所在的目录)。然后编译链接生成dll文件。

将生成的DLL文件放在 C:/WINDOWS/system32 目录下,或者放在与Java程序位于相同的目录下。

说明:修改TestDll.java,查看TestDll.h的变化。
修改后的TestDll.java如下。其中,test1、test2 、test3 、test4仅仅用来查看TestDll.h的变化。
public class TestDll {

//declare library name.
static
{
System.loadLibrary("hello");
}

//declare names of methods to be called.
public native static int get();
public native static void set(int i);
//just for test.
public void test1(){}
public void test2(){}
public String test3(){return null;}
public int test4(){return 0;}
public static void main(String[] args)
{
TestDll test = new TestDll();
test.set(10);
System.out.println(test.get());
}
}
对应修改后的TestDll.java,TestDll.h如下。
#define _Included_TestDll
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: TestDll
* Method: get
* Signature: ()I
*/
JNIEXPORT jint JNICALL Java_TestDll_get
(JNIEnv *, jclass);

/*
* Class: TestDll
* Method: set
* Signature: (I)V
*/
JNIEXPORT void JNICALL Java_TestDll_set
(JNIEnv *, jclass, jint);

#ifdef __cplusplus
}
#endif
#endif
可见,TestDll.h并无变化。因此,TestDll.h只是针对Java 要访问的库中的方法进行声明。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: