JNA進階應用,註冊回調

回調通常用僅含一個方法的接口表示

假如有個C語言接口的SDK函數,用於註冊幀回調,當相機拍攝到一幀照片時,SDK調用用戶註冊的回調函數對這塊圖像幀進行處理(一般就是將其壓縮編碼成jpg碼流)。它的聲明長這樣

MV_CAMCTRL_API int __stdcall MV_CC_RegisterImageCallBackEx(void* handle, 
                                                         void(__stdcall* cbOutput)(unsigned char * pData, MV_FRAME_OUT_INFO_EX* pFrameInfo, void* pUser),
                                                         void* pUser);

JNAerator將上述聲明轉換成一個JNA Library方法和一個JNA Callback

int MV_CC_RegisterImageCallBackEx(Pointer handle, MV_CC_RegisterImageCallBackEx_cbOutput_callback cbOutput, Pointer pUser);

	public interface MV_CC_RegisterImageCallBackEx_cbOutput_callback extends Callback {
		void apply(Pointer pData, MV_FRAME_OUT_INFO_EX pFrameInfo, Pointer pUser);
	};

回調通常以匿名內部類的形式註冊

注意,不要先定義一個子類去繼承MV_CC_RegisterImageCallBackEx_cbOutput_callback接口,然後將子類實例傳遞給註冊函數MV_CC_RegisterImageCallBackEx,這在JDK 11上會報錯

Exception in thread "main" java.lang.ClassCastException: class com.lanplus.HikJnaCamera$CaptureCallback cannot be cast to class com.lanplus.HikLibrary$MV_CC_RegisterImageCallBackEx_cbOutput_callback (com.lanplus.HikJnaCamera$CaptureCallback and com.lanplus.HikLibrary$MV_CC_RegisterImageCallBackEx_cbOutput_callback are in unnamed module of loader 'app')

官方教程也提示了

The simplest usage resembles using anonymous inner classes to register event listeners.

所以只能定義一個匿名內部類

// 定義回調
private HikLibrary.MV_CC_RegisterImageCallBackEx_cbOutput_callback captureCallback
            = (Pointer pData, MV_FRAME_OUT_INFO_EX frameInfo, Pointer handle) -> {
        		String cameraName = mCameraNames.get(handle);
        		// ...
        }
};

// 註冊回調
int res_reg_cb = HikLibrary.INSTANCE.MV_CC_RegisterImageCallBackEx(handle.getValue(),
                    captureCallback, camera.mPtrRef.getValue());

回調通常在另一個線程裏執行

對於相機,SDK通常會啓動一個子線程,不停地從相機提取幀到緩衝區,然後執行用戶回調,此時回調函數是在子線程中運行的,運行完畢後通常要告訴主線程結果,這就牽扯到線程同步。
關於此類話題的文章很多,不再贅述。

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