1、 起源
Java原生的调用本地函数(C/C++)的机制是JNI(JavaNative Interface),但是由于其使用的复杂,还需要写C代码,对许多入门级程序员来说实在不是个好的选择。JNA(Java Native Access)是Sun公司主导开发的基于JNI的java调用原生函数的机制,是对JNI的再次封装。其优点是,使用简单,只需要编写一个包含指定函数的接口即可。JNA提供了动态的C 语言编写的转发器,可以自动实现Java 和C 的数据类型映射。而不必像使用JNI一样完全自己去做数据类型映射,不再需要编写那个烦人的C 动态链接库。当然,JNA相比于JNI,效率不高,会有部分性能损失,毕竟是对JNI的扩展。类似的优秀框架还有JNative。
2、 数据类型映射(来源于JNA的官方JavaDoc文档首页)
Java types must be chosen to match native types of the samesize. Following are the types supported by the JNA library. (简单类型映射)
Java Type | C Type | Native Representation |
boolean | int | 32-bit integer (customizable) |
byte | char | 8-bit integer |
char | wchar_t | platform-dependent |
short | short | 16-bit integer |
int | int | 32-bit integer |
long | long long, __int64 | 64-bit integer |
float | float | 32-bit floating point |
double | double | 64-bit floating point |
pointer | platform-dependent (32- or 64-bit pointer to memory) | |
<T>[] (array of primitive type) | pointer | 32- or 64-bit pointer to memory (argument/return) |
In addition to the above types, which aresupported at the native layer, the JNA Java library automatically handles thefollowing types. All but NativeMapped
and NativeLong
are converted to Pointer
before being passed to the native layer.(复杂类型映射)
char* | NUL-terminated array (native encoding or jna.encoding) | |
wchar_t* | NUL-terminated array (unicode) | |
char** | NULL-terminated array of C strings | |
wchar_t** | NULL-terminated array of wide C strings | |
struct* | pointer to struct (argument or return) (or explicitly) | |
union | same as Structure | |
struct[] | array of structs, contiguous in memory | |
<T> (*fp)() | function pointer (Java or native) | |
varies | depends on definition | |
long | platform-dependent (32- or 64-bit integer) | |
pointer | same as Pointer |
3、 Eclipse中使用DLL
在Eclipse中,导入JNA的jar包(如jna-3.5.1.jar),在需要使用DLL的项目的根目录下放置.dll文件,使用例子如下:
Dll文件为:MyDll.dll,其中申明的外部可调用方法有:
void add1(int a,int b);
void add2(int *a,int*b);//a和b是指向int型的指针
void add3(int *a,int *b);//a和b是指向int[]的指针
void add4(int a[],int b[]);
对应的java文件JNATest.java:
importcom.sun.jna.ptr.IntByReference;
public interface JNATestextends Library {
JNATest JNATestIntance = (JNATest) Native.loadLibrary(
" MyDll ", JNATest.class);
//c中的函数void add1(int a,int b);
public void add1(int a,int b);
//void add2(int *a,int*b);//a和b是指向int型的指针
public void add2(IntByReference a,IntByReference b);
//void add3(int *a,int *b);//a和b是指向int[]的指针
public void add3(int []a,int []b);
//void add4(int a[],int b[]);
public void add4(int []a,int []b);
public static void main(String args[])
{
int a=9;
int b=4;
int array1={1,4,5};
int array2={3,1,5};
JNATest.JNATestIntance.add1(a,b);
JNATest.JNATestIntance.add2(newIntByReference(a),new IntByReference(b));
JNATest.JNATestIntance.add3(array1,array2);
JNATest.JNATestIntance. add4(array1,array2);
}
}
其中IntByReference在表示指向int型的指针,类似的还有ByteByReference, DoubleByReference,
FloatByReference,LongByReference, NativeLongByReference, PointerByReference,ShortByReference,
W32API.HANDLEByReference, X11.AtomByReference,X11.WindowByReference
PointerByReference 类表示指向指针的指针。
当然,涉及指针时也可以使用Pointer这个类,它是一个单例,不允许用构造函数创建。可以使用PointerType自定义。具体实现参考JavaDoc文档。Pointer使用:
import com.sun.jna.ptr.IntByReference;
public interface JNATestextends Library {
JNATest JNATestIntance = (JNATest) Native.loadLibrary(
"Sense2020Dll", JNATest.class);
//c中的函数void add1(int a,int b);
public void add1(int a,int b);
//void add2(int *a,int*b);//a和b是指向int型的指针
public void add2(Pointer a,Pointer b);
public static void main(String args[])
{
int a=9;
int b=4;
JNATest.JNATestIntance.add1(a,b);
JNATest.JNATestIntance.add2(newIntByReference(a). getPointer(),
newIntByReference(b). getPointer());
}
}