java操作dll库的方法有好几种,今天分享一个jawin方式操作dll的方法。
1.首先下载jawin-2.0-alpha1的jar包和jawin.dll文件,可在官网http://sourceforge.net/projects/jawinproject/处下载也可通过作者上传的资源http://download.csdn.net/detail/u011563755/9107917处免费得到,里边有关于jawin的官方文档和一些官方的demos。
2.第二步将jawin.jar这个jar包拷贝到工程目录,并添加到环境变量中,
3.第三步拷贝jawin.dll文件到工程目录下。
4.第四步找到压缩包中的jawin-2.0-alpha1\demos\demos\HelloDll.java这个文件,将其复制到工程目录下运行之。这个demo是调用win32系统的USER32.DLL库,并且通过
msgBox.invoke_I(0, "Hello From a DLL", "From Jawin", 1, ReturnFlags.CHECK_FALSE);`
向库中传参弹出windows的MessageBox。
当然网上我查阅的资料中都是这样介绍jawin方式调用dll的,但是这个demo还不能全面的使用jawin,因为有些dll中是通过参数[out](传出)数据的,jawin通过什么方式获得参数中的返回值呢?
这里通过查阅jawin的文档,可以找到这样一种方式获得参数中的返回值。
invoke
public byte[] invoke(java.lang.String instructions,
int stackSize,
int argStreamSize,
byte[] argStream,
java.lang.Object[] objectArgs,
ReturnFlags flags)
throws COMException
generic method for calling native methods that do not match any of the invoke_* methods. If the caller is using a NakedByteStream for building the stack-bytes, the invoke(String, int, NakedByteStream, Object[], ReturnFlags) shortcut method is prefered.
Parameters:
instructions - the marshalling instructions for marshalling both the stack-array onto the native stack (this is the [in]-parameters) and marshalling the [return] and [out]-parameters onto the returned byte array. Is on the form xx:y:zz, where xx is for the [in]-marshalling, y is for the [return]-marshalling, and zz is for any [out]-marshalling if present. See the Jawin documentation for more about the instruction-strings.
stackSize - the size of the call stack on the native side that the content of the argStream-array should be marshalled to.
argStreamSize - the number of relevant bytes in the argStream-array (often a NakedByteStream is used for the argStream-array, in which case the array will not be full.
argStream - the bytes that should be marshalled to the stack on the native side. The length of this array can NOT be smaller than argStreamSize.
objectArgs - [in/out] used if any java-object should be passed back and forth into the native code.
flags - used for specifying the native error handling, can not be null.
Returns:
the [return] and [out] parameters from the native call, serialized following the marshalling-instructions given the second and third part of the instructions string.
Throws:
COMException - if the native method failed.
java.lang.NullPointerException - if flags is null.
java.lang.ArrayIndexOutOfBoundsException - if argStreamSize is bigger than the length of the argStream-array.
java.lang.IllegalStateException - if this FuncPtr has been closed.
这是api中的函数介绍,都是英语有点烦,然后我们通过一个例子来说明问题。
1.在vs2010中建立一个dll工程,创建头文件DllDlg.h
#define MYLIBDLL extern "C" _declspec(dllimport)
#else
#define MYLIBDLL extern "C" _declspec(dllexport)
#endif
MYLIBDLL int ReturnValue();
MYLIBDLL void OpenDlg(int a);
MYLIBDLL int ReturnParam(int a,int& b,int& d);
#endif
其中定义了三个导出函数,ReturnValue() OpenDlg() 和 ReturnParam(),接下来看三个函数的实现。
DllDlg.cpp
#include "stdafx.h"
#include "DllDlg.h"
#include "TestDlg.h"
void OpenDlg(int a)
{
TestDlg dlg;
dlg.number = a;
dlg.DoModal();
}
int ReturnValue()
{
int a = 88;
return a;
}
int ReturnParam(int a,int& b,int& d)
{
int c = 3;
b = a + 1;
d = a + 2;
return a + c;
}
TestDlg是一个可以做加法运算的对话框在此不介绍。
ReturnValue是一个极其普通的返回一个int数字的函数,ReturnParam的b,d参数则是返回型的参数。接下来编译生成我们的dll库。
2.在eclipse修改demo HelloDll.java如下:
import org.jawin.COMException;
import org.jawin.FuncPtr;
import org.jawin.ReturnFlags;
import org.jawin.io.LittleEndianOutputStream;
import org.jawin.io.NakedByteStream;
import org.jawin.marshal.StructConverter;
/**
* Demo that uses the Win32 MessageBoxW API-method.
*
* @version $Revision: 1.3 $
* @author Stuart Halloway, http://www.relevancellc.com/halloway/weblog/
*/
public class HelloDll {
public static void main(String[] args) throws Exception {
FuncPtr funPoint = null;
try {
funPoint = new FuncPtr("E:\\VS2010 Project\\Java_Dll\\Debug\\Java_Dll.dll","ReturnParam");//得到dllReturnParam的函数指针
NakedByteStream nbs = new NakedByteStream();//创建数据流
LittleEndianOutputStream leos = new LittleEndianOutputStream(nbs);
leos.writeInt(6);//在数据流中传入参数([in]类型参数这里指int ReturnParam(int a,int& b,int& d)中的a)
//IAA:I:L4n4n4字符串是jawin规定的一种伪指令具体书写格式按照文档instruction_docs.html中介绍
//第一个I表示[in] long parameters 也就是ReturnParam的参数a,第二个和第三个AA表示[out] long* parameters也就是ReturnParam的参数b c,第一个:后表示返回值的类型,
//第二个:后表示数据类型所占位数a是int型所以是long类型4字节,&b &c都是int型指针也占4字节,
byte[] result = funPoint.invoke("IAA:I:L4n4n4", 12/*返回值所占字节数*/, nbs, null, ReturnFlags.CHECK_FALSE);
System.out.println(StructConverter.bytesIntoInt(result, 0));//得到的返回值result中前四位表示的是返回值6+3
System.out.println(result[4]);//参数返回值6+1
System.out.println(result[8]);//参数返回值6+2
/*ReturnParam()函数
* int ReturnParam(int a,int& b,int& d)
{
int c = 3;
b = a + 1;
d = a + 2;
return a + c;
}*/
} catch (COMException e) {
// handle exception
e.printStackTrace();
throw e;
} finally {
if (funPoint != null) {
try {
funPoint.close();
} catch (COMException e) {
// handle fatal exception
e.printStackTrace();
throw e;
}
}
}
}
}
E:\VS2010 Project\Java_Dll\Debug\Java_Dll.dll为刚才vs2010创建的dll库。得到结果:
9
7
8
工程下载路径:
http://download.csdn.net/detail/u011563755/9108083
作者的jawin测试demo是在32为系统上运行的,在64位的系统上运行会报错,提示不能加载32位的dll到64位系统,目前没找到更好的解决方案,希望大神们给出意见。