JNA进阶应用,访问Union

Java想访问C代码编译的动态库,一般通过JNA方式实现,该方式好处是不用像JNI方式那样编写C wrapper代码,省去在Java工程里管理C代码的麻烦,但类型转换的坑却变多了。
最近在调试一款工业相机,它的主机接口有USB、GIGE、CameraLink等,SDK在枚举设备时会返回一个相机列表,每个表项都是一个相机,其类型按主机接口分类可能是上述3种任意一种,所以SDK一般都用联合体(Union)来表示,见下面结构体的SpecialInfo字段。

typedef struct _MV_CC_DEVICE_INFO_
{
    unsigned short      nMajorVer;
    unsigned short      nMinorVer;

    union
    {
        MV_GIGE_DEVICE_INFO stGigEInfo;
        MV_USB3_DEVICE_INFO stUsb3VInfo; 
        MV_CamL_DEV_INFO       stCamLInfo;
        // more ...
    }SpecialInfo;

}MV_CC_DEVICE_INFO;

应用程序想通过JNA读取nMajorVer字段,只需要cameraInfo.nMajorVer即可,但访问联合体却不像普通结构体那样简单,因为JNA的Union类JavaDoc里明确写着:

The current field is always unset by default to avoid accidentally attempting to read a field that is not valid.

即不告知JNA结构体的实际类型就读取的话,读到的永远是0

想读到有效值,需要

  1. cameraInfo.SpecialInfo.setType(MV_GIGE_DEVICE_INFO.class); // 设置这段内存实际存储的结构体类型
  2. cameraInfo.SpecialInfo.read(); // 按实际结构体类型反序列化这块内存段
  3. MV_GIGE_DEVICE_INFO gigeInfo = cameraInfo.SpecialInfo.stGigEInfo; // 按字段偏移读取结构体内的指定字段

如果只读取不写入,可以用一个快捷方法getTypedValue,下面代码先用getTypedValue提取结构体的内容,然后读取

MV_GIGE_DEVICE_INFO gigeInfo = (MV_GIGE_DEVICE_INFO)cameraInfo.SpecialInfo.getTypedValue(MV_GIGE_DEVICE_INFO.class);
byte[] rawCameraName = gigeInfo.chUserDefinedName;

相应的,如果只写入不读取,则用setTypedValue,用法类似。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章