文檔列表見:Rust 移動端跨平臺復雜圖形渲染項目開發總結 - 目錄
判斷指針是否為NULL/nullptr
假設存在const T* ptr1
和T* ptr2
,分別判斷它們是否為空,C++和Rust實現如下所示。
if ((NULL == ptr1) || (nullptr == ptr2)) {
// do something
}
use std::ptr;
if ptr::null() == ptr1 || ptr::null_mut() == ptr2 {
// do something
}
返回nullptr/NULL
由前面可知,Rust提供C接口時返回nullptr或NULL的實現如下
#[no_mangle]
pub extern "C" fn init_engine() -> * const c_void {
// something goes wrong
std::ptr::null()
}
fn main() {
unsafe{
let engine = init_engine();
println!("{:?}", engine);
}
}
使用slice直接讀寫指針內容
寫指針
const int COUNT = 100;
int *int_ptr = new int[COUNT];
for (int i = 0; i < COUNT; ++i) {
int_ptr[i] = i;
}
將上述C++申請的ptr指針傳遞到Rust進行寫入,最差的辦法是在Rust內部創建一個長度相同的Vector
,將數據寫入Vector
,再通過std::ptr::copy
到int_ptr
中,示例如下:
use std::ptr;
#[no_mangle]
pub extern "C" fn write_to_c_buffers(n: usize, buffers: *mut i32) {
let mut tmp_buffers = Vec::with_capacity(n);
for index in 0..n {
tmp_buffers.push(index);
}
unsafe {
ptr::copy(tmp_buffers.as_ptr(), buffers, n);
}
}
上述的tmp_buffers
分配了一塊與buffers
等長的新內存,這樣多占用了內存,不科學。
使用std::slice
直接讀寫裸指針可實現前面C++式的做法,示例如下:
use std::slice;
#[no_mangle]
pub extern "C" fn write_to_c_buffers(n: usize, buffers: *mut i32) {
unsafe {
let mut slice = slice::from_raw_parts_mut(buffers, n);
for index in 0..n {
slice[index] = index;
}
}
}
進一步,可使用Rust類似C#的foreach進行循環,同時縮小unsafe代碼塊的影響空間。讀指針也可用這個方案。
use std::slice;
#[no_mangle]
pub extern "C" fn write_to_c_buffers(n: usize, buffers: *mut i32) {
let mut buffers = unsafe { slice::from_raw_parts_mut(buffers, n) };
for slice in buffers {
*slice = //do something;
}
}
讀指針
int summary(size_t count, int ptr*) {
int sum = 0;
for (int i = 0; i < count; ++i) {
sum += ptr[i];
}
return sum;
}
將ptr
傳遞到Rust進行求和,用slice可以直接操作,避免分配額外的內存,示例如下:
use std::slice;
#[no_mangle]
pub extern "C" fn summary_for_c_buffers(n: usize, buffers: *const i32) {
unsafe {
let slice = slice::from_raw_parts(buffers, n);
let mut sum = 0;
for index in 0..n {
sum += slice[index];
}
sum
}
}