文档列表见:
判断指针是否为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 }}复制代码