读书人

JNA调用C兑现的DLL

发布时间: 2012-12-24 10:43:13 作者: rapoo

JNA调用C实现的DLL
, TestJnaLib.class);//标蓝的地方一定要这么写

此实例由jna通过反射自动生成。

?

此接口支持在Java端多线程、并发调用本地方法。如果本地类库不是线程安全的,可用

TestJnaLib INSTANCE2 =? Native.synchronizedLibrary(INSTANCE);

来阻止多线程同时访问本地代码。


6、在表示链接库的接口里定义对应dll里的方法

?

int ik_release_enroll_device(Object devHandle);


7、调用本地方法

TestJnaLib.INSTANCE.ik_release_enroll_device(devHandle);

?

第三部分:DLL函数对JNA的回调

1、dll中定义了如下带回调函数的函数

IRIS_SDK_API int STDCALL ik_init_enroll_module (ik_ipaddress_t?? listened_addr,

?????????????????????????????????????????????????? int (__stdcall * IK_IDEN_CALLBACK_FUNC)

(IK_IDEN_DEVICE_HANDLE dev_handle, // 设备句柄

int type, // 回调类型

void *param); )
红色加粗部分是函数指针。

2、Java部分定义一个回调接口
必须继承自com.sun.jna.Callback接口 (如果回调函数是以stdcall输出,有时候可能引起jvm崩溃,可以改成继承StdCallCallback接口试试,)

子接口必须定义单个公有方法或一个名为callback的公有方法。必须持有到回调对象的一个存活引用。一个回调应该不抛出异常。

public interface FunCallBack extends StdCallCallback{

?????? public int callback(IntByReference devHandle,int type,Pointer para);

}


callback方法里的参数顺序,类型及返回类型必须与C函数的相关类型对应上

3、定义回调接口的实现

public class CallbackFunImpl implements FunCallBack {

?????? @Override

?????? public synchronized int callback(IntByReference devHandle, int type, Pointer para){

????? //已知para是指向IkIdenresultArray类型的指针

????????????? IkIdenresultArray ikArray = new IkIdenresultArray(para);

??????????????? int count = ikArray.result_count;

??????????????? if(ikArray.presult == null || count <= 0){

??????????????????? log.info("识别结果数不大于0!");

??????????????????? return 0;

??????????????? }

??????????????? IkIdenresult[] rels = (IkIdenresult[])ikArray.presult.toArray(count);

??????????????? if (rels == null || rels.length == 0) {

??????????????????? log.info("识别结果为空!");

??????????????????? return 0;

??????????????? }

?????? }

}

?

上文涉及的结构体的定义如下:

//识别结果列表

??? public static class IkIdenresultArray extends Structure{

?????? ?public IkIdenresultArray(Pointer p) {

????????????? super(p);

????????????? useMemory(p);

????????????? read();

?????????? }

?????? ?

?????? public IkIdenresultArray() {

?????????? super();

?????? }

?

?????? public static class ByReference extends IkIdenresultArray implements Structure.ByReference { }

??????? public static class ByValue extends IkIdenresultArray implements Structure.ByValue{ }

???????

?????? public IkIdenresult.ByReference presult = new IkIdenresult.ByReference(); // 识别结果列表(表示指针)

??????? public int result_count ; // 识别结果个数

??? }

4、在表示链接库实现的接口里定义要回调的本地函数

void methodWithCallback(StdCallCallback callback, int left, int right);

本地函数的函数指针用Callback 接口替代。

5、调用带函数指针的本地函数

TestJnaLib.INSTANCE.methodWithCallback(new CallbackFunImpl(), 4, 6)

最好将标红的地方定义一个static的变量引用它,否则回调函数的内存区域可能被GC回收而引起JVM崩溃,调用如下:

StdCallCallback callback = new CallbackFunImpl();

TestJnaLib.INSTANCE.methodWithCallback(callback, 4, 6)

?

第四部分:JAVAC类型的对应

1、? 基本类型的对应可以到网上查找对应表

2、? 特殊的struct类型

1>Structure属性传递给本地字段必须是public的。

2>虽然结构体和结构体字段的名字可以是任意的,但他们应该尽可能接近本地定义。参数名及参数顺序对应一样。

3> Structure类的write()方法会把结构体的所有字段固定住,是原生函数可以访问。

4> C语言是不知道你Java的引用的。它只能访问固定的内存地址。因此,在使用JNI和JNA时,都会把Java对象锁住。GC不再管理。不删除,也不移动位置。即把传递给C的struct对象A固定住内存,如果这个A种还嵌套了struct对象,则也被固定住,但是如果嵌套的是struct的引用B,则不会固定,需要把B手动固定,如:

B.ByReference b = new B.ByReference();

b.write();

5> 结构体的定义如:

//识别结果

??? public static class IkIdenresult extends Structure{

?????? //属性都定义为public类型

?????? public IkIdenresult() {

?????????? super();

?????? }

?????? public IkIdenresult(Pointer p) {

?????????? super(p);

?????????? useMemory(p);

?????????? read();

?????? }

?????? public static class ByReference extends IkIdenresult implements Structure.ByReference { }//通过ByReference定义的是指针

??????? public static class ByValue extends IkIdenresult implements Structure.ByValue{ }//通过ByValue定义的是对象

???????

??????? public IntByReference dev_handle; // 识别设备句柄

??????? public byte []dev_sn = new byte[128];// 设备标志

??????? public byte []iden_date_time = new byte[32]; // 识别时间

??????? public int person_id; // personID

??????? public byte [] person_name= new byte[128]; // 人员姓名

??????? public int feature_id; // featureID

??????? public int eye_flag; // 眼睛标志

??? }

读书人网 >编程

热点推荐