I've written a wrapper for a camera library in Rust that commands and operates a 16-bit camera, and also saves an image to file, using bindgen. Once I command an exposure to start (basically telling the camera to take an image), I can grab the image using a function of the form:
pub fn GetQHYCCDSingleFrame(
handle: *mut qhyccd_handle,
w: *mut u32,
...,
imgdata: *mut u16,) -> u32 //(u32 is a retval)
In C++, this function was:
uint32_t STDCALL GetQHYCCDSingleFrame(qhyccd_handle: *handle, ..., uint8_t *imgdata)
In C++, I can pass in a buffer of the form imgdata = new unsigned char[length_buffer]
and the function would fill the buffer with image data from the camera.
In Rust, similarly, I can pass in a mut_ptr
of a buffer in the form of a Vec: let mut buffer: Vec<u16> = vec![0u16; length_buffer]
.
Currently, the way I have structured the code is that there is a main struct, with settings such as the width and height of image, the camera handle, and others, including the image buffer. The struct has been initialized as a mut
as:
let mut main_settings = MainSettings {
width: 9600,
...,
buffer: vec![0u16; length_buffer],
}
And when passing it to the GetQHYCCDSingleFrame
function, I pass it accordingly:
let retval = unsafe { GetQHYCCDSingleFrame(main_settings.cam_handle, ..., main_settings.image_buffer.as_mut_ptr()) };
This code works perfectly when I build the program with cargo build
or cargo build --release
and run using cargo run
or cargo run --release
. The program starts the exposure, waits until the exposure is done, and then "gets" the frame and populates the buffer with image data correctly.
However, initially when I was writing the program, I had mistakenly declared the GetQHYCCDSingleFrame function as:
pub fn GetQHYCCDSingleFrame(
handle: *mut qhyccd_handle,
w: *mut u32,
...,
imgdata: &mut [u16],) -> u32 //(u32 is a retval)
(Note the change in imgdata type from *mut u16
to &mut [u16]
).
When I passed in the same previous buffer as a slice and not a pointer:
let retval = unsafe { GetQHYCCDSingleFrame(main_settings.cam_handle, ..., &mut main_settings.image_buffer) };
the program worked perfectly when I built it with cargo build
and ran using cargo run
(dev build with 0 optimizations). The function and call worked, and the image buffer populated. However, the program segfaulted at GetQHYCCDSingleFrame when I built it using cargo build --release
or ran it using cargo run --release
(release build with opt-level = 3
).
Using rust-gdb
, the segfault error was:
Thread 1 "qsc" received signal SIGSEGV, Segmentation fault.
_memmove_sse2_unaligned_erms()
at ../sysdeps/x86_64/multiarch/memmove-vec-unaligned-erms.S:538
538
../sysdeps/x86_64/multiarch/memmove-vec-unaligned-erms.S: No such file or directory.
I haven't had much experience with Rust optimizations, and don't quite get what optimizations Rust is doing to cause the program to segfault when it runs perfectly with no optimizations. I do understand the correct thing to do is to send in a mut_ptr
as I do now, and everything works, but looking back, I would like to understand why the previous erroneous program worked but only in dev build and not release build? Is there a possibility it might be understanding the context in the C++ code the requirement there? Or is it something else going on?
If any more information might help understand, I'd be more than happy to provide that as well. Thanks!