上一篇《JAVA本地接口(JNI)》中介绍了JAVA的JNI技术,通过JAVA自有的方式调用动态链接库,这一篇将继续为大家介绍使用其他方式调用动态链接库。
首先,我们编写一个用于测试的链接库
头文件 print.h
#ifdef DLL_IMPLEMENT
#define DLL_API __declspec(dllexport)
#else
#define DLL_API __declspec(dllimport)
#endif
#ifndef _Included_PRINT
#define _Included_PRINT
#ifdef __cplusplus
extern "C" {
#endif
DLL_API void print();
DLL_API void print2(int i);
DLL_API int print3(int i);
#ifdef __cplusplus
}
#endif
#endif
源文件 print.c
#define DLL_IMPLEMENT
#include <stdio.h>
#include "print.h"
DLL_API void print()
{
printf("invoke print...");
}
DLL_API void print2(int i)
{
printf("invoke print %d...", i);
}
DLL_API int print3(int i)
{
return i;
}
使用c编译器对其进行编译:cl -LD print.c -Feprint.dll
然后我们将生成的print.dll
放在系统的system32文件夹下,至此准备工作完成。
JNative
JNative是Java to native interface的缩写,使用JNative,我们可以很方便的调用动态链接库,使用示例如下:
import org.xvolks.jnative.JNative;
import org.xvolks.jnative.Type;
public class JNativeTest
{
public static void main(String[] args) throws Exception
{
// 加载动态链接库
JNative print = new JNative("print.dll", "print");
// 执行函数
print.invoke();
JNative print2 = new JNative("print.dll", "print2");
// 设置函数形参
print2.setParameter(0, 2);
print2.invoke();
JNative print3 = new JNative("print.dll", "print3");
// 设置返回值类型
print3.setRetVal(Type.INT);
print3.setParameter(0, 3);
print3.invoke();
// 获得运行结果
String result = print3.getRetVal();
System.out.println("print3:" + result);
}
}
下面再给出一个使用JNative获得系统时间的示例:
import org.xvolks.jnative.JNative;
import org.xvolks.jnative.exceptions.NativeException;
import org.xvolks.jnative.misc.basicStructures.AbstractBasicData;
import org.xvolks.jnative.pointers.Pointer;
import org.xvolks.jnative.pointers.memory.MemoryBlockFactory;
import org.xvolks.jnative.util.Kernel32.SystemTime;
public class JNativeDemo extends AbstractBasicData<JNativeDemo>
{
public short wYear;
public short wMonth;
public short wDayOfWeek;
public short wDay;
public short wHour;
public short wMinute;
public short wSecond;
public short wMilliseconds;
/**
* 分配内存,并返回指针
*/
public Pointer createPointer() throws NativeException
{
pointer = new Pointer(MemoryBlockFactory.createMemoryBlock(getSizeOf()));
return pointer;
}
/**
* 内存大小
*/
public int getSizeOf()
{
return 8 * 2;
}
/**
* 获取通过内存指针解析出结果
*/
public JNativeDemo getValueFromPointer() throws NativeException
{
wYear = getNextShort();
wMonth = getNextShort();
wDayOfWeek = getNextShort();
wDay = getNextShort();
wHour = getNextShort();
wMinute = getNextShort();
wSecond = getNextShort();
wMilliseconds = getNextShort();
return this;
}
public JNativeDemo() throws NativeException
{
super(null);
createPointer();
}
public String toString()
{
return wYear + "/" + wMonth + "/" + wDay + " at + " + wHour + ":"
+ wMinute + ":" + wSecond + ":" + wMilliseconds;
}
public static SystemTime GetSystemTime() throws NativeException,
IllegalAccessException
{
// 创建对象
JNative nGetSystemTime = new JNative("Kernel32.dll", "GetSystemTime");
SystemTime systemTime = new SystemTime();
// 设置参数
nGetSystemTime.setParameter(0, systemTime.getPointer());
nGetSystemTime.invoke();
// 解析结构指针内容
return systemTime.getValueFromPointer();
}
public static void main(String[] args) throws NativeException,
IllegalAccessException
{
System.err.println(GetSystemTime());
}
}
JNA
JNA(Java Native Access )提供一组Java工具类用于在运行期动态访问系统本地库(native library:如Window的dll)而不需要编写任何Native/JNI代码。开发人员只要在一个java接口中描述目标native library的函数与结构,JNA将自动实现Java接口到native function的映射。
使用示例:
import com.sun.jna.Library;
import com.sun.jna.Native;
public class JNADemo
{
// 定义接口CLibrary,继承自com.sun.jna.Library
public interface CLibrary extends Library
{
// 定义并初始化接口的静态变量
CLibrary Instance = (CLibrary) Native
.loadLibrary("print", CLibrary.class);
// 函数声明
void print();
void print2(int i);
int print3(int i);
}
public static void main(String[] args)
{
CLibrary.Instance.print();
CLibrary.Instance.print2(2);
System.out.println("print3:" + CLibrary.Instance.print3(3));
}
}
JNative和JNA都可以实现对DLL的调用,但二者各有优缺点,需要根据实际情况选择。