您的位置:首页 > 编程语言 > Java开发

Java动态库调用

2015-08-21 15:50 309 查看

1. 方法简介

a). JNI调用动态库: JNI是安装JDK的时候自带的内容,适用场景为开发前就知道动态库需要供Java程序调用,且需要Java程序提供动态库开发的头文件内容。使用相对复杂,且如果是对于已经存在的动态库需要开发中间库来适配

 b). Jacob 调用动态库:Jacob是SUN提供的一个用于调用动态库的类库,使用相对简单,不需要二次开发,但是需要手动进行一些配置工作

 c). JNA 调用动态库:JNA是对JNI的二次封装,使用简单,不需要进行二次开发,同样不需要手动进行配置,导入jar包就可以工作

2. JNI调用动态库

假设已经存在一个动态库add.dll,里面存在一个函数int add(int a,int b);现在需要通过JNI去调用这个方法。

 ·=> 编写调用中间动态库myAdd.dll的类TestDll.java

 ·=> 通过命令javah得到中间动态库的头文件TestDll.h

 ·=> 编写生成中间动态库myAdd.dll

 ·=> 将生成的myAdd.dll放到TestDll.class同目录下,运行java TestDll查看结果

2.1编写调用中间动态库的类生成TestDll.h

【TestDll.java】

public class TestDll {
	private native static int add(int a, int b);

	static {
		System.loadLibrary("myAdd"); // 该动态库名称为中间动态库,由java程序使用,负责调用需要使用的动态库。
	}

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		System.out.println(add(4, 5));
	}
}


进入cmd执行javac TestDll;javah TestDll





【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:    add
 * Signature: (II)I
 */
JNIEXPORT jint JNICALL Java_TestDll_add
  (JNIEnv *, jclass, jint, jint);

#ifdef __cplusplus
}
#endif
#endif

2.2 编写中间动态库myAdd.dll

使用vc工具先生成win32 Dynamic-Link Library空工程,将上面生成的头文件TestDll.h添加进去,同时还需要添加jdk下include目录中 的jni.h、jni_md.h这两个头文件,最好将jni.h文件放入安装目录下include的目录下,添加调用需要使用的动态库的实现文件TestDll.cpp

【TestDll.cpp】

//TestDll.cpp
#include <windows.h>
#include "TestDll.h"
typedef int (*padd)(int,int);
JNIEXPORT jint JNICALL Java_TestDll_add
  (JNIEnv *, jclass, jint x, jint y)
{
 HINSTANCE hins = ::LoadLibrary("add.dll");
 if(hins == NULL)
 {
  return 0;
 }
 int res;
 padd pa = (padd)GetProcAddress(hins,"add");
 if(pa != NULL)
 {
  res = pa(x,y);
 }
 ::FreeLibrary(hins);
 return res;
}


编译生成myAdd.dll,将myAdd.dll和add.dll放到TestDll.class同目录下,运行java TestDll查看结果为: 9

至此JNI调用动态库完成~

3. Jacob 调用动态库

3.1 Jacob开发环境配置

下载jacob需要的库 Jacob.zip

解压后将jacob.jar复制到项目中,或者将其加入到ClassPath中。将jacob-1.18-x86.dll放入到jdk的bin目录中

3.2 注册动态库获取ClassID以及ProgID

设动态库名称为mydll.dll

=> 编写windows批处理文件regMyDll.bat,记事本打开编辑regsvr32 mydll.dll双击执行,在win8下可能要右键以管理员身份运行

=>Win + R输入regedit打开注册表,编辑->查找mydll.dll,得到ClassID: 135CB56E-FDB4-43B6-A386-CD0C15295C07;ProgID: WebScan.WScan.1 (一般我们只取ProgID 即可)



3.3 编写调用动态库的类

创建ActiveX控件对象,由于classid每次注册可能会不一样,所以取ProgID作为ActiveXComponent初始化的入参

【TestJcob.java】

public class TestJcob {
 private static ActiveXComponent activeX;//ActiveX控件对象
 private static Dispatch dispath;//MS级别的调度对象
 static
 {
  //创建ActiveX控件对象
  //activeX = new ActiveXComponent("CLSID:135CB56E-FDB4-43B6-A386-CD0C15295C07");
  activeX = new ActiveXComponent("WebScan.WScan.1");
  //获得调度对象
  dispath = activeX.getObject();
 }
 public static int add(int a,int b){
  Variant ret = Dispatch.call(dispath, "add",a,b);
     return ret.getInt();
 }
 /**
  * @param args
  */
 public static void main(String[] args) {
  System.out.println(add(4,5));
 }
}

3.4 读取未知dll的函数接口(感兴趣的可以研究下)

将未知dll或者ocx或其他注册,使用VS提供的C:\Program Files\Windows Kits\8.0\bin\x86工具oleview.exe来查看dll的内部变量定义以及函数结构

使用方法:打开工具File->View TypeLib选择未知dll查看

4. JNA 调用动态库

下载jna.jar文件,复制并依赖到项目中

设调用的动态库名字为Add.dll内部函数为int add(int a,int b);

【TestJNA.java】

public class TestJNA {
 public interface Add extends StdCallLibrary {
  Add instance = (Add) Native.loadLibrary(System.getProperty("user.dir") + "\\Add.dll", Add.class);
  int add(int a,int b);
 }
 public static int add(int a,int b){
  return Add.instance.add(a, b);
 }
 
 public static void main(String[] args) {
  System.out.println(add(4,5));
 }

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: