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,用法類似。

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