use vimba_sys::{ VmbAccessModeType, VmbCameraInfo_t, VmbErrorType, VmbFrameStatusType, VmbFrame_t, VmbHandle_t, VmbVersionInfo_t, }; fn err_str(err: i32) -> &'static str { use VmbErrorType::*; #[allow(non_upper_case_globals)] match err { VmbErrorSuccess => "VmbErrorSuccess", VmbErrorInternalFault => "VmbErrorInternalFault", VmbErrorApiNotStarted => "VmbErrorApiNotStarted", VmbErrorNotFound => "VmbErrorNotFound", VmbErrorBadHandle => "VmbErrorBadHandle", VmbErrorDeviceNotOpen => "VmbErrorDeviceNotOpen", VmbErrorInvalidAccess => "VmbErrorInvalidAccess", VmbErrorBadParameter => "VmbErrorBadParameter", VmbErrorStructSize => "VmbErrorStructSize", VmbErrorMoreData => "VmbErrorMoreData", VmbErrorWrongType => "VmbErrorWrongType", VmbErrorInvalidValue => "VmbErrorInvalidValue", VmbErrorTimeout => "VmbErrorTimeout", VmbErrorOther => "VmbErrorOther", VmbErrorResources => "VmbErrorResources", VmbErrorInvalidCall => "VmbErrorInvalidCall", VmbErrorNoTL => "VmbErrorNoTL", VmbErrorNotImplemented => "VmbErrorNotImplemented", VmbErrorNotSupported => "VmbErrorNotSupported", VmbErrorIncomplete => "VmbErrorIncomplete", VmbErrorIO => "VmbErrorIO", _ => "unknown error", } } fn vimba_err(err: i32) -> anyhow::Result<()> { if err == VmbErrorType::VmbErrorSuccess { Ok(()) } else { Err(anyhow::anyhow!("vimba error {}: {}", err, err_str(err))) } } macro_rules! vimba_call { ($expr: expr) => {{ vimba_err(unsafe { $expr }) }}; } fn main() -> anyhow::Result<()> { let vimba_handle: VmbHandle_t = 1 as _; #[cfg(target_os = "windows")] let vimbac_path = r#"C:\Program Files\Allied Vision\Vimba_6.0\VimbaC\Lib\Win64\VimbaC.dll"#; #[cfg(not(target_os = "windows"))] let vimbac_path = "/opt/vimba/Vimba_6_0/VimbaC/DynamicLib/x86_64bit/libVimbaC.so"; let vimba_lib = unsafe { vimba_sys::VimbaC::new(vimbac_path) }?; // start vimba vimba_call!(vimba_lib.VmbStartup())?; // print version let mut version_info = VmbVersionInfo_t { major: 0, minor: 0, patch: 0, }; vimba_call!(vimba_lib.VmbVersionQuery( &mut version_info, std::mem::size_of::() as u32 ))?; println!( "Vimba API Version: {}.{}.{}", version_info.major, version_info.minor, version_info.patch ); // check if GigE is available let mut is_gige_avail = 0; let data = std::ffi::CString::new("GeVTLIsPresent")?; vimba_call!(vimba_lib.VmbFeatureBoolGet(vimba_handle, data.as_ptr(), &mut is_gige_avail))?; println!("GigE is available: {}", is_gige_avail); // get camera list let mut n_count = 0; vimba_call!(vimba_lib.VmbCamerasList(std::ptr::null_mut(), 0, &mut n_count, 0))?; println!("{} cameras found", n_count); let mut cameras: Vec = vec![ VmbCameraInfo_t { cameraIdString: std::ptr::null_mut(), cameraName: std::ptr::null_mut(), modelName: std::ptr::null_mut(), serialString: std::ptr::null_mut(), permittedAccess: 0, interfaceIdString: std::ptr::null_mut(), }; n_count as usize ]; let mut n_found_count = 0; vimba_call!(vimba_lib.VmbCamerasList( cameras[..].as_mut_ptr(), n_count, &mut n_found_count, std::mem::size_of::().try_into()? ))?; assert_eq!(n_count, n_found_count); for i in 0..n_found_count as usize { println!("Camera {}:", i); println!(" cameraIdString: {}", unsafe { std::ffi::CStr::from_ptr(cameras[i].cameraIdString).to_str() }?); println!(" cameraName: {}", unsafe { std::ffi::CStr::from_ptr(cameras[i].cameraName).to_str() }?); println!(" modelName: {}", unsafe { std::ffi::CStr::from_ptr(cameras[i].modelName).to_str() }?); println!(" serialString: {}", unsafe { std::ffi::CStr::from_ptr(cameras[i].serialString).to_str() }?); println!(" permittedAccess: {}", cameras[i].permittedAccess); println!(" interfaceIdString: {}", unsafe { std::ffi::CStr::from_ptr(cameras[i].interfaceIdString).to_str() }?); } let mut camera_handle = std::ptr::null_mut(); // VmbHandle_t cameraHandle = NULL; let camera_access_mode = VmbAccessModeType::VmbAccessModeFull; // We open the camera with full access if cameras.len() > 0 { println!("Opening camera 0..."); vimba_call!(vimba_lib.VmbCameraOpen( cameras[0].cameraIdString, camera_access_mode as u32, // API bug? Should not require cast. &mut camera_handle, ))?; println!("...OK"); // Get the pixel format let mut pixel_format: *const std::os::raw::c_char = std::ptr::null(); let data = std::ffi::CString::new("PixelFormat")?; vimba_call!(vimba_lib.VmbFeatureEnumGet(camera_handle, data.as_ptr(), &mut pixel_format))?; println!("PixelFormat: {}", unsafe { std::ffi::CStr::from_ptr(pixel_format).to_str() }?); // Get the payload size let mut payload_size = 0; let data = std::ffi::CString::new("PayloadSize")?; vimba_call!(vimba_lib.VmbFeatureIntGet(camera_handle, data.as_ptr(), &mut payload_size,))?; println!("PayloadSize: {}", payload_size); let mut frame = std::mem::MaybeUninit::::uninit(); let mut payload: Vec = vec![0; payload_size.try_into().unwrap()]; unsafe { // This truly is unsafe - we must manually ensure `payload` has a // longer lifetime than `frame`. (*frame.as_mut_ptr()).buffer = payload.as_mut_ptr() as _; (*frame.as_mut_ptr()).bufferSize = payload.len().try_into().unwrap(); } vimba_call!(vimba_lib.VmbFrameAnnounce( camera_handle, frame.as_mut_ptr(), std::mem::size_of::().try_into().unwrap() ))?; vimba_call!(vimba_lib.VmbCaptureStart(camera_handle))?; vimba_call!(vimba_lib.VmbCaptureFrameQueue(camera_handle, frame.as_mut_ptr(), None))?; let data = std::ffi::CString::new("AcquisitionStart")?; vimba_call!(vimba_lib.VmbFeatureCommandRun(camera_handle, data.as_ptr(),))?; let n_timeout = 2000; vimba_call!(vimba_lib.VmbCaptureFrameWait(camera_handle, frame.as_mut_ptr(), n_timeout))?; let frame = unsafe { frame.assume_init() }; if frame.receiveStatus == VmbFrameStatusType::VmbFrameStatusComplete { println!("frame complete"); println!("imageSize {}", frame.imageSize); println!("{}x{}", frame.width, frame.height); } else { println!("frame not complete. status: {}", frame.receiveStatus); } } // shutdown unsafe { vimba_lib.VmbShutdown() }; Ok(()) }