【CXX】6.10 *mut T,*const T原始指针

通常情况下,你应该尽可能使用引用(&mut T, &T)或 std::unique_ptr 而不是原始指针,但原始指针也可以作为一种不安全的备选方案。

限制:

接受原始指针作为参数的 extern 函数和函数指针必须声明为 unsafe fn,即调用是不安全的。这不适用于仅返回原始指针的函数,尽管通常对返回的指针进行任何有用的操作都会在其他地方涉及不安全的代码。

示例

此示例展示了如何对涉及 char *argv\[\] 的典型 C 风格主函数签名进行 Rust 调用。

cpp 复制代码
// include/args.h
#pragma once
void parseArgs(int argc, char *argv[]);
cpp 复制代码
// src/args.cc
#include "example/include/args.h"
#include <iostream>

void parseArgs(int argc, char *argv[]) {
	std::cout << argc << std::endl;
	for (int i = 0; i < argc; i++) {
	std::cout << '"' << argv[i] << '"' << std::endl;
	}
}
rust 复制代码
// src/main.rs

use std::env;
use std::ffi::CString;
use std::os::raw::c_char;
use std::os::unix::ffi::OsStrExt;
use std::ptr;

#[cxx::bridge]
mod ffi {
extern "C++" {
include!("example/include/args.h");

复制
    unsafe fn parseArgs(argc: i32, argv: *mut *mut c_char);
}
}

fn main() {
// 将 OsString 转换为以 nul 结尾的 CString,如果存在内部 nul 字节,则在第一个 nul 字节处截断每个参数。
let args: Vec<CString> = env::args_os()
.map(|os_str| {
let bytes = os_str.as_bytes();
CString::new(bytes).unwrap_or_else(|nul_error| {
let nul_position = nul_error.nul_position();
let mut bytes = nul_error.into_vec();
bytes.truncate(nul_position);
CString::new(bytes).unwrap()
})
})
.collect();

// 将拥有的字符串的 Vec<CString> 转换为借用的字符串指针的 Vec<*mut c_char>。
//
// 一旦 extern 类型稳定(https://github.com/rust-lang/rust/issues/43467)
// 并且 https://internals.rust-lang.org/t/pre-rfc-make-cstr-a-thin-pointer/6258
// 被实现,并且 CStr 指针变为瘦指针,我们可以通过预先将参数累积为 Vec<Box<CStr>> 来绕过此步骤,
// 然后简单地从 *mut [Box<CStr>] 转换为 *mut [*mut CStr] 再到 *mut *mut c_char。
let argc = args.len();
let mut argv: Vec<*mut c_char> = Vec::with_capacity(argc + 1);
for arg in &args {
    argv.push(arg.as_ptr() as *mut c_char);
}
argv.push(ptr::null_mut()); // Nul 终止符。

unsafe {
    ffi::parseArgs(argc as i32, argv.as_mut_ptr());
}

// CStrings 在此处超出范围。C 函数不得在此点之后持有指针。
}
相关推荐
Tairitsu_H9 小时前
[C++] 深入理解红黑树:封装set与map
开发语言·c++·set·map·红黑树·模拟实现
小灰灰搞电子9 小时前
Rust+Slint 实现左右伸缩式图片浏览器源码分享
rust·slint·图片伸缩浏览器
HugoStudio_SWAN9 小时前
洛谷 B4450 / B3867 / B3923 智慧购物、储蓄与做题——从程序到生活
c++·学习·程序人生·算法·生活
会周易的程序员11 小时前
5Draft(五帝)测试报告
服务器·c++·分布式·raft·共识算法·共识·算力服务器
UIU11411 小时前
scanf与cout的误区:探究其内部的机制
c++·学习·c#·scanf
闻缺陷则喜何志丹11 小时前
【栈 运算系统】P3719 [AHOI2017初中组] rexp|普及+
c++·算法··洛谷·运算系统
bnmoel12 小时前
C++ 基础入门篇(一):命名空间,输入&输出,缺省参数,函数重载
c++·函数重载·语法·命名空间·缺省参数
Zixhy12 小时前
多点巡检机器人项目技术总结
linux·c++·机器人·自动驾驶
Pointer Pursuit14 小时前
C++11特性(二)
前端·c++·算法
tudousisi22215 小时前
CSP 第3题训练 Day 5|CSP202509C HTTP 头信息|Blog A
c++