我试图在Rust中并行创建一个数组,并通过DLL绑定将其返回给C#。但前4个元素是无效的。
如果没有线程池和同步,我会得到正确的结果。实际计算更加复杂,但以下代码是一个简化版本,不涉及真正的计算。我还尝试过使用
最后,我对Rust很新,请随时提出任何改进代码的建议。
简化版Rust计算:
Rust输出:
有任何想法,是什么导致了这种行为?
如果没有线程池和同步,我会得到正确的结果。实际计算更加复杂,但以下代码是一个简化版本,不涉及真正的计算。我还尝试过使用
int*
代替IntPtr
,但得到了相同的无效结果。最后,我对Rust很新,请随时提出任何改进代码的建议。
简化版Rust计算:
#[no_mangle]
pub extern "C" fn create_array(len: libc::c_int, result:*mut *mut libc::c_int){
let mut result_vec: Vec<libc::c_int> = vec![0;len as usize];
let sync_result=Arc::new(Mutex::new(result_vec));
let pool=ThreadPool::new(6);
println!("From Thread");
for i in 0..(len){
pool.execute({
let clone = Arc::clone(&sync_result);
move||{
let mut result_vec = clone.lock().unwrap();
result_vec[i as usize]=i;
if i<10{
println!("{}:{}",i,result_vec[i as usize]);
}
}});
}
pool.join();
let mut result_vec = Arc::try_unwrap(sync_result).unwrap().into_inner().unwrap();
println!("Unwrapped Vector");
for i in 0..10{
println!("{}:{}",i,result_vec[i as usize]);
}
let result_data = result_vec.as_mut_ptr();
unsafe{
println!("Raw data");
*result=result_data;
for i in 0..10 as isize{
println!("{}:{}",i,ptr::read(result_data.offset(i)));
}
}
std::mem::forget(result_data);
}
C#数据绑定和函数调用
[DllImport(@"libs\OptimizationRust.dll", CallingConvention = CallingConvention.Cdecl)]
private static extern void create_array(int len, out IntPtr result);
public void RustCpuSerial()
{
IntPtr resultPtr;
int len = 10000;
create_array(len,out resultPtr);
int[] results = new int[len];
Marshal.Copy(resultPtr, results, 0, results.Length);
}
Rust输出:
From Thread
0:0
5:5
7:7
8:8
9:9
1:1
3:3
4:4
6:6
2:2
Unwrapped Vector
0:0
1:1
2:2
3:3
4:4
5:5
6:6
7:7
8:8
9:9
Raw data
0:0
1:1
2:2
3:3
4:4
5:5
6:6
7:7
8:8
9:9
C# 输出:
0:-314008176
1:672
2:-314139296
3:672
4:4
5:5
6:6
7:7
8:8
9:9
有任何想法,是什么导致了这种行为?
println!("Pointer address {:p}",result)
;则打印出“Pointer address 0x410437d650”——不一样,或者我需要以不同的方式获取值吗?但是result_data与C#中的相同。 - MiBa