This is my Rust fn passing back I hope a pointer to an array of f32.
#[no_mangle]
pub extern "C" fn sdrlib_disp_data() -> *mut f32 {
let mut out_real = [0.0; (common_defs::DSP_BLK_SZ ) as usize];
dsp::dsp_interface::wdsp_get_display_data(0, &mut out_real);
println!("out_real[100] {}", out_real[100]);
let v_out_real = out_real.to_vec();
println!("v_out_real[100] {}", v_out_real[100]);
let data = Box::new(v_out_real);
println!("data[100] {}", data[100]);
let r = Box::into_raw(data) as *mut _;
unsafe {println!("r[100] {}", *((r as *mut f32).add(100)));}
return r;
}
This is the output on the Rust side:
out_real[100] -113.57421
v_out_real[100] -113.57421
data[100] -113.57421
r[100] 1473573000000000000000000000
and on the client side
x[100] 1.473572992698795e+27
The data appears to get across the interface OK but is rubbish. Clearly I'm not understanding something about what this line does.
Box::into_raw(data) as *mut _;
Yandros
December 19, 2022, 5:33pm
2
This heap-allocates the array of f32
s twice (you can see a Vec<f32>
as a Box<[T]>
).
So you end up having a Box<Vec<f32>>
, so kind of like a Box<Box<[f32]>>
, which as a raw pointer would be a *mut *mut f32
, but you treat it as a single-layer pointer, so you are missing one layer of indirection .
In a way, you shouldn't need to as
cast in your code :
- let data = Box::new(v_out_real);
- let r = Box::into_raw(data) as *mut _;
+ let (r, _len, _capacity) = v_out_real.into_raw_parts();
Don't forget that Vec::into_raw_parts()
is still unstable. If I were writing this, I'd skip the Vec
altogether and just use a boxed array:
#[no_mangle]
pub extern "C" fn sdrlib_disp_data() -> *mut f32 {
let mut out_real = Box::new([0.0; (common_defs::DSP_BLK_SZ) as usize]);
dsp::dsp_interface::wdsp_get_display_data(0, &mut out_real);
println!("out_real[100] {}", out_real[100]);
let r = Box::into_raw(out_real) as *mut f32;
unsafe { println!("r[100] {}", *r.add(100)); }
r
}
1 Like
Yandros
December 19, 2022, 5:43pm
4
Yeah, if the length is a const
(which it looks to be the case), then
1 Like
Thanks. Looks like the to_vec does mess it up even though it had the correct data in it once Boxed it was messed up. Need to check it out a bit further but the data looks correct now.
Yandros
December 19, 2022, 5:52pm
6
You may have been fooled by the […]
indexing sugar in Rust, which is allowed to implicitly dereference:
is actually: (*v_out_real)[100]
,
and:
is actually (**data)[100]
, indirection-wise
Yes I was but the data in the client was wrong and is now correct. The fn is simplified to this.
#[no_mangle]
pub extern "C" fn sdrlib_disp_data() -> *mut f32 {
let mut out_real = [0.0; (common_defs::DSP_BLK_SZ ) as usize];
dsp::dsp_interface::wdsp_get_display_data(0, &mut out_real);
return Box::into_raw(Box::new(out_real)) as *mut _;
}
system
Closed
March 19, 2023, 5:58pm
8
This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.