当前位置: 首页 > article >正文

Rust: CString、CStr和String、str

在FFI与C交互中,少不了与C中字符串交互。在Rust中,有

各种String存在的意义:
OsString:因为要与操作系统等复杂的世界交互;
因为Rust世界中的Strings 始终是有效的 UTF-8。对于非 UTF-8 字符串,可以用到OsString。
CString: 与C的世界进行交互;
String:在Rust的世界中交互;

一、CString、String等代码探析

因为有用到外部libc库,所以:

1、toml文件


[dependencies]
libc = "0.2"

2、相关代码

use std::ffi::{CStr, CString,c_char};
use std::borrow::Cow;
fn main() {println!("Hello, world!");show_cstring_bytes(CString::new("Hello, world!").expect("CString::new failed"));show_string_bytes("Hello, world!".to_string());}// as:不consume
// from/into:consume ownship
// into_bytes(),as_bytes()返回的缓冲区不包含尾随 nul 终止符,并且保证不包含任何内部 nul 字节。
// 必须用as_bytes_with_nul()返回的缓冲区包含 nul 终止符。
fn show_cstring_bytes_no_null(s:CString){let c_string_bytes = s.as_bytes();println!("c_string_bytes no null   : {:?}  len: {:?}", c_string_bytes,c_string_bytes.len());
}
fn show_cstring_bytes(s:CString){let c_string_bytes = s.as_bytes_with_nul();println!("c_string_bytes with null : {:?}  len: {:?}", c_string_bytes,c_string_bytes.len());}
fn show_string_bytes(s:String){let string_bytes = s.into_bytes();println!("  string_bytes           : {:?} len :{:?}", string_bytes,string_bytes.len());
}
// CString ->&CStr
fn cstring_to_cstr(s:&CString) ->&CStr{s.as_c_str()}
fn show_cstr_bytes_no_null(s:&CStr){let c_str_bytes = s.to_bytes();println!("c_str_bytes   no null: {:?}  len: {:?}", c_str_bytes,c_str_bytes.len());
}
fn show_cstr_bytes_with_null(s:&CStr){let c_str_bytes = s.to_bytes_with_nul();println!("c_str_bytes with null: {:?}  len: {:?}", c_str_bytes,c_str_bytes.len());
}
fn cstring_to_str(s:&CString) ->&str{s.to_str().expect("CString to str failed")
}
fn cstr_to_cstring(s:&CStr) ->CString{s.to_owned()
}
// *const c_char具体是*const i8 还是 *const u8由平台决定。
fn get_ptr_c_char() ->*const c_char{const BYTES: &[u8] = b"Hello, world! to c_char!\0";//或是:BYTES.as_ptr().cast()BYTES.as_ptr() as *const _ 
}fn get_cstr_from_bytes<'a>() ->&'a CStr{const BYTES_: &[u8] = b"Hello, world! from bytes!\0";let cstr = CStr::from_bytes_with_nul(BYTES_).expect("CStr::from_bytes_with_nul failed");cstr
}
fn get_cstr_from_ptr_c_char<'a>(s:*const c_char) ->&'a CStr{unsafe { CStr::from_ptr(s) }
}fn get_cstring() ->CString{let c_string = CString::new("Hello, world! from c string!").expect("CString::new failed");c_string}
fn check_cstring(s: *const c_char) -> bool{unsafe {let slice = CStr::from_ptr(s);let my_str = slice.to_str();match my_str{Ok(_) => return true,Err(_) => return false,};//println!("my_str: {}", my_str.expect("CStr::from_ptr failed"));}}fn cstr_to_str(s:&CStr) ->&str{s.to_str().expect("CStr::from_ptr failed")
}
fn cstring_to_cow_str(s:&CString) ->Cow<'_,str>{//let c_string = CString::new("Hello, world! from c string!").expect("CString::new failed");let c_string_ptr = s.as_ptr();let cow = unsafe { CStr::from_ptr(c_string_ptr).to_string_lossy() }; // COW<'_,str>cow
}
fn cstr_to_cow_str(s:&CStr) ->Cow<'_,str>{s.to_string_lossy()
}fn cstring_to_box_cstr(s:CString) ->Box<CStr>{s.into_boxed_c_str()
}
fn box_cstr_to_cstring(s:Box<CStr>) ->CString{s.into_c_string()
}fn vec_u8_with_null_to_cstring_unchecked(v:Vec<u8>) ->CString{unsafe{CString::from_vec_with_nul_unchecked(v)}
}
fn vec_u8_with_null_to_cstring_checked(v:Vec<u8>) ->CString{CString::from_vec_with_nul(v).expect("CString::from_vec_with_nul failed")
}fn vec_u8_no_null_to_cstring(v:Vec<u8>) ->CString{unsafe{CString::from_vec_unchecked(v)}
}
fn bytes_with_null_to_cstr_unchecked(bytes:&[u8]) ->&CStr{unsafe{ CStr::from_bytes_with_nul_unchecked(bytes) }
}
fn bytes_with_null_to_cstr_check(bytes:&[u8]) ->&CStr{unsafe{ CStr::from_bytes_with_nul(bytes).unwrap() }
}
fn bytes_no_null_to_cstr(bytes:&[u8]) ->&CStr{unsafe{ CStr::from_bytes_until_nul(bytes).unwrap() }
}
// MUST *mut : move ownership
fn ptr_to_cstring(ptr:*mut c_char) ->CString{unsafe{ CString::from_raw(ptr) }
}
// MUST:*mut : consume ownership
fn cstring_to_ptr_with_consume(s:CString) ->*mut c_char{s.into_raw() // s 被消耗,不能再使用
}
fn cstring_to_ptr_no_consume(s:&CString) ->*const c_char{s.as_ptr()
}
fn ptr_to_cstr<'a>(ptr: *const i8) ->&'a CStr{unsafe{ CStr::from_ptr(ptr) }
}
fn cstring_to_string(s:CString) ->String{// let c_string_ptr = s.as_ptr();// let my_string = unsafe { CStr::from_ptr(c_string_ptr).to_string_lossy() }; // COW<'_,str>// println!("my_string: {}", my_string);s.into_string().unwrap() // 消耗s,不能再使用}
fn string_to_cstring(s: String) ->CString{let c_string = CString::new(&*s).expect("CString::new failed");c_string
}
//C中分配内存,C中释放内存
fn c_allocate_for_rust_as_cstring(){#[allow(unused_extern_crates)]extern crate libc; //toml文件中,需要添加libc = "0.2"// 分配内存来存储一个字符串let size = 12; // 例如,分配足够存储 "Hello, world" 的内存let ptr = unsafe { libc::malloc(size) as *mut c_char };if !ptr.is_null() {// 使用 C 字符串格式填充内存let c_str = CString::new("Hello, world").unwrap();unsafe{std::ptr::copy_nonoverlapping(c_str.as_ptr(), ptr, size);}// 使用 CStr 来安全地访问这个内存let rust_str = unsafe { CStr::from_ptr(ptr) };println!("{}", rust_str.to_str().unwrap());unsafe{// 释放内存libc::free(ptr as *mut _);}} else {println!("Memory allocation failed");}
}

二、输出结果

Hello, world!
c_string_bytes with null : [72, 101, 108, 108, 111, 44, 32, 119, 111, 114, 108, 100, 33, 0]  len: 14string_bytes           : [72, 101, 108, 108, 111, 44, 32, 119, 111, 114, 108, 100, 33] len :13  

可以看到,在CString和String转化为字节后的本质区别。

相关的转化具体见上面的代码,有助于加深认识。

相关文章:

Rust: CString、CStr和String、str

在FFI与C交互中&#xff0c;少不了与C中字符串交互。在Rust中&#xff0c;有 各种String存在的意义&#xff1a; OsString:因为要与操作系统等复杂的世界交互&#xff1b; 因为Rust世界中的Strings 始终是有效的 UTF-8。对于非 UTF-8 字符串&#xff0c;可以用到OsString。 CSt…...

力扣每日一题——连接两棵树后最大目标节点数目 ||

目录 题目链接&#xff1a;3373. 连接两棵树后最大目标节点数目 II - 力扣&#xff08;LeetCode&#xff09; 题目描述 解法一&#xff1a;​​双树贡献分离法​​ Java写法&#xff1a; C写法&#xff1a; 运行时间 时间复杂度和空间复杂度 总结 题目链接&#xff1a;…...

【学习笔记】Sparse Crosscoders for Cross-Layer Features and Model Diffing

Sparse Crosscoders for Cross-Layer Features and Model Diffing Abstract 本说明介绍了稀疏跨编码器(sparse crosscoders)&#xff0c;它是一种稀疏自编码器(sparse autoencoders)或transcoders的变体&#xff0c;旨在用于理解叠加中的模型结构。SAEs是在单一层中编码和预测…...

VSCode无法转到定义python源码(ctrl加单击不跳转)

已经尝试的方案&#xff1a; 1.确保对应python环境正确激活 在 VSCode 中&#xff0c;打开命令面板&#xff08;CtrlShiftP&#xff09;&#xff0c;输入并选择 Python: Select Interpreter&#xff0c;然后从列表中选择正确的 Python 解释器。 2.重新卸载Python插件再重新安装…...

【华为战报】4月、5月 HCIP考试战报!

了解更多往期考试→点 【考试战报】 华为认证 HCIP 4、5月微思 | HCIP 考试战报 学员成绩单 华为认证 最新开班 厦门面授 全国直播 新生代网工必看&#xff1a;华为模拟器eNSP安装教程&#xff08;附下载链接&#xff09;...

开发指南120-表格(el-table)斑马纹

el-table实现斑马纹简单否&#xff0c;看起来很简单&#xff0c;网上给的例子都是加stripe&#xff0c;例如 <el-table :data"tableData" stripe>连官网上的例子都是这样。然并卵。也许是版本问题。这么写&#xff0c;怎么折腾都没有效果。 必须这样写才行 …...

数字化转型全场景安全解析:从产品到管理的防线构建与实施要点

在数字化转型中&#xff0c;安全已从“可选配置” 升级为 “必需底座”&#xff0c;贯穿于产品生命周期、生产过程、供应链及管理决策全场景。以下从南京市场景清单出发&#xff0c;结合技术实践与政策要求&#xff0c;分析安全在各核心场景中的具体内涵与实施要点&#xff1a;…...

AIGC工具平台-GPT-SoVITS-v4-TTS音频推理克隆

声音克隆与语音合成的结合&#xff0c;是近年来生成式AI在多模态方向上的重要落地场景之一。随着预训练模型能力的增强&#xff0c;结合语音识别、音素映射与TTS合成的端到端系统成为初学者可以上手实践的全流程方案。 围绕 GPT-SoVITS-v4-TTS 模块&#xff0c;介绍了其在整合…...

el-table配置表头固定而且高度变化

根据官网提示只要在 el-table 元素中定义了 height 属性&#xff0c;即可实现固定表头的表格&#xff0c;而不需要额外的代码。 如果你想既要固定表头&#xff0c;又要下方表格高度自适应&#xff0c;可以设置为 height"100%" &#xff1a; 然后外层设置scroll:...

设计模式——组合设计模式(结构型)

摘要 组合设计模式是一种结构型设计模式&#xff0c;用于将对象组合成树形结构以表示“部分-整体”的层次结构&#xff0c;使客户端对单个对象和组合对象具有一致的访问方式。它包含抽象组件、叶子节点和组合节点&#xff0c;具有统一处理、支持递归结构和易扩展等优点&#x…...

PostgreSQL 在生物信息学中的应用

PostgreSQL&#xff08;简称PG&#xff09;是一种强大的开源关系型数据库管理系统&#xff0c;因其高可靠性、扩展性和支持复杂查询的特性&#xff0c;在生物信息学领域得到广泛应用。以下是其核心应用场景及优势分析&#xff1a; 一、生物数据存储与管理 生物信息学涉及海量…...

EMO2:基于末端执行器引导的音频驱动虚拟形象视频生成

今天带来EMO2&#xff08;全称End-Effector Guided Audio-Driven Avatar Video Generation&#xff09;是阿里巴巴智能计算研究院研发的创新型音频驱动视频生成技术。该技术通过结合音频输入和静态人像照片&#xff0c;生成高度逼真且富有表现力的动态视频内容&#xff0c;值得…...

计算机总线技术深度解析:从系统架构到前沿演进

计算机系统中的总线是连接多个部件的信息传输线&#xff0c;是各部件间传输信息的公共通道。以下将从总线的定义、功能、分类、性能指标等方面进行详细介绍&#xff1a; 一、总线的定义与功能 1.定义&#xff1a;总线是一组能为多个部件分时共享的公共信息传送线路&#xff0…...

Python打卡训练营Day43

DAY 43 复习日 作业&#xff1a; kaggle找到一个图像数据集&#xff0c;用cnn网络进行训练并且用grad-cam做可视化 数据集地址&#xff1a;Lung Nodule Malignancy 肺结核良恶性判断 进阶&#xff1a;并拆分成多个文件 import os import pandas as pd import numpy as np from…...

PHP7+MySQL5.6 查立得轻量级公交查询系统

# PHP7MySQL5.6 查立得轻量级公交查询系统 ## 系统简介 本系统是一个基于PHP7和MySQL5.6的轻量级公交查询系统(40KB级)&#xff0c;支持线路查询、站点查询和换乘查询功能。系统采用原生PHPMySQL开发&#xff0c;无需第三方框架&#xff0c;适合手机端访问。 首发版本&#x…...

如何做好一个决策:基于 Excel的决策树+敏感性分析应用(针对多个变量)

本文是对《如何做好一个决策:基于 Excel的决策树+敏感性分析应用》一文的补充。 示例背景 决策问题:是否开发新产品? 关键变量: 开发成本(B2):$500K, $700K, $1M高需求概率(B4):30%, 50%, 70%高需求收入(C4...

Azure DevOps 管道部署系列之一本地服务器

Azure DevOps 是一个帮助改进 SDLC(软件开发生命周期)的平台。 在本文中,我们将使用 Azure Pipelines 创建自动化部署。 Azure DevOps 团队将 Azure Pipelines 定义为“使用 CI/CD 构建、测试和部署,适用于任何语言、平台和云平台”。 在这里,我将解释如何在 Azure Dev…...

DeepSeekMath:突破开放式语言模型中数学推理能力的极限

摘要 由于数学推理具有复杂且结构化的特性,这对语言模型构成了重大挑战。在本文中,我们介绍了 DeepSeekMath 7B 模型,该模型在 DeepSeek-Coder-Base-v1.5 7B 模型的基础上,使用从 Common Crawl 获取的 1200 亿个与数学相关的标记,以及自然语言和代码数据继续进行预训练。…...

QT 5.15.2 程序中文乱码

1. 在.pro文件中添加&#xff1a; msvc { QMAKE_CXXFLAGS /source-charset:utf-8 /execution-charset:utf-8 }备注&#xff1a;.pro文件只有在选择 qmake 方式才会生成。 [Cmake 只会生成 CMakeLists.txt 文件] 2. 在文件首部增加以下程序行 #pragma execution_character_s…...

Celery简介

一、什么是异步任务队列 异步任务队列是指一种用于管理和调度异步执行任务的机制。具体来说&#xff0c;它允许将任务放入队列中&#xff0c;然后由后台进程异步处理这些任务&#xff0c;而不会阻塞主线程的执行。这种设计使得系统能够高效地处理耗时操作&#xff0c;同时保持…...

StarRocks物化视图

## 引言 在大数据时代&#xff0c;企业对实时数据分析的需求日益增长&#xff0c;而传统OLAP系统在处理复杂查询时往往面临性能瓶颈。StarRocks作为新一代极速全场景MPP分析型数据库&#xff0c;通过其独特的**物化视图&#xff08;Materialized View, MV&#xff09;**技术&a…...

vue2源码解析——响应式原理

文章目录 引言数据劫持收集依赖数组处理渲染watchervue3中的响应式 引言 vue的设计思想是数据双向绑定、数据与UI自动同步&#xff0c;即数据驱动视图。 为什么会这样呢&#xff1f;这就不得不提vue的响应式原理了&#xff0c;在使用vue的过程中&#xff0c;我被vue的响应式设…...

基于 GitLab CI + Inno Setup 实现 Windows 程序自动化打包发布方案

在 Windows 桌面应用开发中&#xff0c;实现自动化构建与打包发布是一项非常实用的工程实践。本文以我在开发PackTes项目时的为例&#xff0c;介绍如何通过 GitLab CI 配合 Inno Setup、批处理脚本、Qt 构建工具&#xff0c;实现版本化打包并发布到共享目录的完整流程。 项目地…...

做好 4个基本动作,拦住性能优化改坏原功能的bug

缺陷分析 “小李&#xff0c;202504300989这个现场缺陷你负责测试漏测分析&#xff0c;要求用5why方法找到漏测根因&#xff0c;根据找到的根因制定改进措施。你今天下班前完成&#xff0c;完成后立刻通知我&#xff0c;质量部现在每天都在催现场缺陷分析结果。”周二刚上班&a…...

【HarmonyOS 5】针对 Harmony-Cordova 性能优化,涵盖原生插件开发、线程管理和资源加载等关键场景

1. ‌原生图片处理插件&#xff08;Java&#xff09; package com.example.plugin; import ohos.media.image.ImageSource; import ohos.media.image.PixelMap; import ohos.app.Context; public class ImageProcessor { private final Context context; public ImagePro…...

零基础认知企业级数据分析平台如何落实数据建模(GAI)

理解数据建模的基本概念 数据建模是将业务需求转化为数据结构和关系的过程&#xff0c;核心目标是构建可支撑分析、预测或决策的数据模型。零基础需从以下维度入手&#xff1a; 业务理解&#xff1a;明确业务问题&#xff08;如销售预测、用户分群&#xff09;&#xff0c;与…...

web架构2------(nginx多站点配置,include配置文件,日志,basic认证,ssl认证)

一.前言 前面我们介绍了一下nginx的安装和基础配置&#xff0c;今天继续来深入讲解一下nginx的其他配置 二.nginx多站点配置 一个nginx上可以运行多个网站。有多种方式&#xff1a; http:// ip/域名 端口 URI 其中&#xff0c;ip/域名变了&#xff0c;那么网站入口就变了…...

AI 的早期萌芽?用 Swift 演绎约翰·康威的「生命游戏」

文章目录 摘要描述题解答案题解代码分析示例测试及结果时间复杂度空间复杂度总结 摘要 你有没有想过&#xff0c;能不能通过简单的规则模拟出生与死亡&#xff1f;「生命游戏」正是这样一种充满魅力的数学模拟系统。这篇文章我们来聊聊它的规则到底有多神奇&#xff0c;并用 S…...

【DBA】MySQL经典250题,改自OCP英文题库中文版(2025完整版)

【DBA】MySQL经典250题&#xff0c;改自OCP英文题库中文版&#xff08;2025完整版&#xff09; ——2025.5.15 文章目录 P1&#xff1a;1-50&#xff08;划重点&#xff09;P2&#xff1a;51-100&#xff08;划重点&#xff09;P3&#xff1a;101-150&#xff08;划重点打标记&…...

Cursor 编辑器介绍:专为程序员打造的 AI 编程 IDE

在现代软件开发中&#xff0c;AI 辅助编程正逐步改变开发者的工作方式。Cursor 正是这场变革中的佼佼者&#xff0c;它不仅是一个现代化的代码编辑器&#xff0c;更是将强大的 AI 编程助手深度集成到 IDE 的一次探索性尝试。 一、什么是 Cursor&#xff1f; Cursor 是一款基于…...