上一篇《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 __cplusplusextern "C" {#endifDLL_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.Librarypublic 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的调用,但二者各有优缺点,需要根据实际情况选择。