java中怎样调用现有的dll文件

java中怎样调用现有的dll文件,第1张

使用jni调用

具体如下:

JAVA通过JNI调用本地方法,而本地方法是以库文件的形式存放的(在WINDOWS平台上是DLL文件形式,在UNIX机器上是SO文件形式)。通过调用本地的库文件的内部方法,使JAVA可以实现和本地机器的紧密联系,调用系统级的各接口方法。

简单介绍及应用如下:

一、JAVA中所需要做的工作

在JAVA程序中,首先需要在类中声明所调用的库名称,如下:

static {

System.loadLibrary(“goodluck”)

}

在这里,库的扩展名字可以不用写出来,究竟是DLL还是SO,由系统自己判断。

还需要对将要调用的方法做本地声明,关键字为native。并且只需要声明,而不需要具体实现。如下:

public native static void set(int i)

public native static int get()

然后编译该JAVA程序文件,生成CLASS,再用JAVAH命令,JNI就会生成C/C++的头文件

例如程序testdll.java,内容为:

public class testdll

{

static

{

System.loadLibrary("goodluck")

}

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())

}

}

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

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

二、C/C++中所需要做的工作

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

接上例子。我们先看一下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

在具体实现的时候,我们只关心两个函数原型

JNIEXPORT jint JNICALL Java_testdll_get (JNIEnv *, jclass)

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

这里JNIEXPORT和JNICALL都是JNI的关键字,表示此函数是要被JNI调用的。而jint是以JNI为中介使JAVA的int类型与本地的int沟通的一种类型,我们可以视而不见卖羡,就当做int使用。函数的名称是JAVA_再加上java程序的package路径再加函数名组成的。参数中,我们也只需要关心在JAVA程序中存在的参数,至于JNIEnv*和jclass我们一般没有必要去碰它。

好,下面我们用testdll.cpp文件具体实现伍配搜这两个函数:

#include "testdll.h"

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

}

编译连接成库文件,本例是在WINDOWS下做的,生成的是DLL文件。并且名称要与JAVA中需要调用的一致,这里就是goodluck.dll

把goodluck.dll拷贝到testdll.class的目录下,java testdll运行它,就可以观察到结果了。

1. “DLL的头文件”是个模糊概念,其实应该包含“DLL模块自己用的头文件”和“给DLL以外卜旁的模块用的头文件”,但一般地,通过条件编译开关,都把这两个文件合并在一起。

2. 给DLL以外的模块用的“DLL的头文件”中不启弊唤要“定义”全局变量,而应该“声明”全局变量。

3. DLL中用的全局变量应该在DLL模块内定义。(无论是DLL的cpp文件或在“DLL模块自己用的头文件”中)

下面给个例子。(例子中将“DLL模块自己用的头文件”和“给DLL以外的模块用的头文悄凯件”合并在一起)

A。DLL的cpp文件:(dlltest.cpp)

#define DLL_EXPORT //这是编译DLL模块本身 或编译其他使用者的开关

#include "dlltest.h"

long g_count = 0

int dllmul(int i, int j) { g_count++ return i*j}

B。DLL的头文件:(dlltest.h)

#ifndef DLL_TEST

#define DLL_TEST

#ifndef DLL_EXPORT

extern "C" __declspec(dllimport) int dllmul(int i, int j)

extern __declspec(dllimport) long g_count

#else

extern "C" __declspec(dllexport) int dllmul(int i, int j)

extern __declspec(dllexport) long g_count

#endif

#endif

C。使用上述DLL的程序

#include "dlltest.h"

#include "stdio.h"

int main(){

printf("The count is %d\n",g_count)

printf("5*6=%d\n",dllmul(5,6))

printf("The count is %d\n",g_count)

getchar()

return 0

}

最后提醒:如果有多个线程或进程使用你的DLL模块,注意共享变量和共享保护。可以看看Jetfrey Richter写的《Windows核心编程》

使用VC下的cl和link手工创建dll并实现函数导入

1、创建dll头文件:

/*

* dllmain.h

*/

#ifndef _DLLMAIN_H

#define _DLLMAIN_H

int getNumber()

#endif

2、创建dll源文件:

/*

* dllmain.c

*/

#include "dllmain.h"

int getNumber()

{

return 10

}

3、 创建def文件:

export.def

LIBRARY MY_DLLMAIN MY_DLLMAIN 将成为生成的dll的名称

EXPORTS

getNumber @1 这个名称即为函数的实际导出名称 @1为函数的导出编州腊尺号

4、生成dll文件:

cl dllmain.c /c

link /def:export.def /dll dllmain.obj

这时,工程中已经包含了 dllmain.h dllmain.c export.def dllmain.obj dllmain.lib dllmain.exp MY_DLLMAIN.dll 其中,后4个文件是编译链接过程中生成的文件

5、创建dlltest.c:

/*

* dlltest.c

*/

#include <stdio.h>

#include "dllmain.h" //dll库的头文件

#pragma comment(lib,"dllmain.lib") //dllmain.lib即是上一步生成的文件

int main()

{

printf("%dn",getNumber())

}

6、册高编译、链接dlltest.c

cl dlltest.c /c

link dlltest.obj

注意:这里dllmain.lib和dllmain.h应该和dlltest.c在同一个目录中。此步的结果将生成 dlltest.exe

7、运行:

dlltest

这时,系统将载入my_dllmain.dll这个动态链接库,将调用其中的getNubmer函数局凳。


欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/tougao/12222808.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-05-21
下一篇 2023-05-21

发表评论

登录后才能评论

评论列表(0条)

保存