2311rust对接C

原文
为了与其他语言通信,Rust提供了(FFI)外部函数接口.FFIRustC间的函数调用,与C函数调用有相同性能的零成本抽象.

FFI绑定还可利用(如所有权和借用)语言功能来提供强制指针和其他资源协议的安全接口.

Rust与C对话

Rust调用C代码的简单示例开始.如下为C代码:

int double_input(int input) {return input * 2;
}

要从Rust调用它,可如下编写程序:

extern crate libc;
//外部仓库.
extern {fn double_input(input: libc::c_int) -> libc::c_int;//写签名.
}
fn main() {let input = 4;let output = unsafe { double_input(input) };//不安全中调用.println!("{} * 2 = {}", input, output);
}

就这样!在源码级,除了声明签名外,就行了.
但有些细节:
首先,看到extern crate libc.此libc仓库在与C语言通信时,为FFI绑定提供了许多有用的类型定义,且确保C和Rust跨语言边界类型上保持一致.
再看:

extern {fn double_input(input: libc::c_int) -> libc::c_int;
}

Rust中,这是外部可用函数的声明.可按C头文件对待.这里编译器要了解函数的输入和输出,可在上面看到,这与C中定义匹配.
接着,程序主体:

fn main() {let input = 4;let output = unsafe { double_input(input) };println!("{} * 2 = {}", input, output);
}

在此看到了RustFFI关键方面,即不安全块.编译器对double_input的实现一无所知,因此它必须假设调用外部函数时,都可能内存不安全.
再看看是否可验证零成本.
为了了解Rust做了什么,直接进入上述main函数对double_input调用的汇编代码:

mov    $0x4,%edi
callq  3bc30 <double_input>

如前,就是这样!在此可见,把参数移动到位后,从Rust调用C函数恰好涉及一个调用指令,这与C语言中的成本完全相同.

安全抽象

Rust中绑定C库时,不仅是零成本,还可比C更安全!
如,考虑解析tarballC库.该库公开取读tarball每个文件内容函数,可能如下:

 //在`tarball`中,在给定`索引`处,取文件的数据,如果不存在`该文件`,则返回`NULL`.如果成功,用文件大小`填充`,`"size"`指针.
const char *tarball_file_data(tarball_t *tarball, unsigned index, size_t *size);

但是,此函数假定返回的char*指针生命期不超过输入的tarball.绑定到Rust中时,此API可能如下:

pub struct Tarball { raw: *mut tarball_t }
impl Tarball {pub fn file(&self, index: u32) -> Option<&[u8]> {unsafe {let mut size = 0;let data = tarball_file_data(self.raw, index as libc::c_uint, &mut size);if data.is_null() {None} else {Some(slice::from_raw_parts(data as *const u8, size as usize))}}}
}

这里的*mut tarball_t指针,由Tarball所有,并由它负责析构和清理.
此外,file方法返回生命期隐式与源tarball自身生命期相关联(&self参数)的借用切片.

这是Rust指示,只能在tarball的生命期内使用返回slice,静态避免了直接使用C时易产生的悬挂针错误.

因为Rust的静态检查,使用Rust端的API根本不可能造成段错误.所有这些都是零成本的:无额外分配或成本,可在Rust中表示C语言中的原始类型.

Rust令人惊叹的社区,已围绕现有的C库构建了一些实质性的安全绑定,包括OpenSSL,libgit2,libdispatch,libcurl,sdl2,UnixAPIlibsodium.
1
2
3
4
5
6
7
更多.

C语言与Rust对话

零成本FFI不仅适合Rust调用C,也适合C调用Rust!
首先,从Rust代码开始:

#[no_mangle]
pub extern fn double_input(input: i32) -> i32 {input * 2
}

与之前Rust代码一样,首先,用#[no_mangle]属性标记了函数定义.
指示编译器不要装饰double_input函数的符号名.Rust使用类似C++混杂名来确保库名不会相互冲突.
extern,可与C函数兼容.编译为lib文件,而不是rlib库.

#include <stdint.h>
#include <stdio.h>
extern int32_t double_input(int32_t input);
int main() {int input = 4;int output = double_input(input);printf("%d * 2 = %d\n", input, output);return 0;
}

Rust没有垃集和运行时,因此实现了从C到Rust无缝过渡.外部C代码不需要安装Rust执行设置,使得过渡成本非常低.

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/142331.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

spark调优案例分享

做了一个Spark调优案例的分享 最近在整理了Spark相关的调优案例&#xff0c;并做了以下分享:spark调优案例 &#xff0c;注意是Mac Keynote

Unity 下载Zip压缩文件并且解压缩

1、Unity下载Zip压缩文件主要使用UnityWebRequest类。 可以参考以下方法&#xff1a; webRequest UnityWebRequest.Get(Path1); //压缩文件路径webRequest.timeout 60;webRequest.downloadHandler new DownloadHandlerBuffer();long fileSize GetLocalFileSize(Path2); …

小H靶场学习笔记:DC-2

DC-2 Created: November 10, 2023 3:01 PM Tags: WordPress, git提权, rbash逃逸 Owner: 只会摸鱼 靶场过程 信息收集 扫描存活主机&#xff0c;找到靶机ip&#xff1a;192.168.199.131&#xff08;本机是192.168.199.129&#xff09; 扫描端口开放协议 发现有80端口和77…

支持向量机基本原理,Libsvm工具箱详细介绍,基于支持向量机SVM的人脸朝向识别

目录 支持向量机SVM的详细原理 SVM的定义 SVM理论 Libsvm工具箱详解 简介 参数说明 易错及常见问题 完整代码和数据下载链接: 基于支持向量机SVM人脸朝向识别(代码完整,数据齐全)资源-CSDN文库 https://download.csdn.net/download/abc991835105/88527821 SVM应用实例, 基…

2023nacos源码解读第3集——nacos-client核心功能之微服务调用和配置管理测试

文章目录 1、测试项目2、项目注意事项3、 测试核心功能3.1 测试服务调用与负载均衡3.2 测试配置监听 4、参考文档 1、测试项目 项目地址 nacos-service-a nacos-service-b 2、项目注意事项 项目初始化可以使用aliyun spring initializer ,以更方便的使用springcloud alibaba…

hive里因为列名用了关键字导致建表失败

代码 现象 ParseException line 6:4 cannot recognize input near percent String COMMENT in column name or primary key or foreign key 23/11/13 11:52:57 ERROR org.apache.hadoop.hive.ql.Driver: FAILED: ParseException line 6:4 cannot recognize input near percent …

oracle 不支持的字符集 orai18n.jar ZHS16GBK 异常问题解决

项目场景&#xff1a; 项目中有使用到oracle数据库来存在数据。 问题描述 在使用查询语句是&#xff0c;oracle会报错。 java.sql.SQLException: 不支持的字符集 (在类路径中添加 orai18n.jar): ZHS16GBK 原因分析&#xff1a; 经排查发现缺少oracle字符集的依赖包导致的。…

雷达测角原理、测角精度、测角分辨率以及3DFFT角度估计算法汇总

1.角度测量方法 依据&#xff1a;电磁波的直线传播和雷达天线的方向性。 分类&#xff1a;振幅法测角、相位法测角 1.1 相位法测角 相位法测角利用多个天线所接收回波信号之间的相位差进行测角。如下图所示&#xff1b; 图 1 设在θ方向有一远区目标&#xff0c;则到达接收点…

一个破单机,也要用远程缓存?

大家好&#xff0c;豆小匠终于开始Coding了&#xff0c;这期来聊聊实战相关的杂谈。 正文开始&#xff01; 作为编程萌新的时候&#xff0c;总想着把程序做复杂&#xff0c;堆技术栈。 但是程序是为场景服务的&#xff0c;比如&#xff0c;我想提高接口的响应速度&#xff0c…

Vue3集成json-editor-vue3

安装依赖 npm install json-editor-vue3 --save引入 main.js import "jsoneditor";具体模块 import JsonEditorVue from json-editor-vue3;代码实现 <json-editor-vue ref"jsonEditor" class"editor" v-model"state.addFormField.p…

Linux应用层点亮硬件的LED灯

一 应用层操作硬件的两种方法 应用层想要对底层硬件进行操控&#xff0c;通常可以通过两种方式&#xff1a; /dev/目录下的设备文件&#xff08;设备节点&#xff09;&#xff1b;/sys/目录下设备的属性文件。 具体使用哪种方式需要根据不同功能类型设备进行选择&#xff0c;通…

docker应用实例及dockerfile

实际应用 神经网络项目由x86cpu的linux环境移到arm cpu架构上运行&#xff0c;使用docker进行测试以及环境配置。 docker load -i 镜像压缩文件.tar docker load -i命令用于从一个压缩的镜像存档文件&#xff08;通常是以.tar扩展名结尾&#xff09;中加载镜像到本地Docker引擎…

API支付接口

在数字化时代&#xff0c;API&#xff08;Application Programming Interface&#xff0c;应用程序编程接口&#xff09;支付接口已成为电子商务和移动支付领域的核心技术。它们作为软件之间的桥梁&#xff0c;使得商家能够无缝地整合各种支付服务&#xff0c;从而为消费者提供…

vscode设置vue3代码格式化

vscode设置vue3代码格式化 vscode设置vue3代码格式化 下载插件设置格式化时选用的插件实际使用 使用Prettier默认配置使用Prettier添加自定义配置使用Volar 完整配置文件参考链接 下载插件 可以使用Volar或Prettier 设置格式化时选用的插件 mac&#xff1a;【shift】【op…

【C++】类与对象 I

类与对象 I &#xff1a; 前言&#xff1a;&#xff08;C&#xff09;面向过程 和&#xff08;C&#xff09;面向对象 初步认识前言&#xff1a;类的引入一、类的介绍二、类的定义&#xff08;一&#xff09;class 语法&#xff08;二&#xff09;类的两种定义方式&#xff1a;…

【MySql系列】深入解析数据库索引

写在前面 MySQL索引是数据库中一个关键的概念&#xff0c;它可以极大地提高查询性能&#xff0c;加快数据检索速度。但是&#xff0c;要充分发挥索引的作用&#xff0c;需要深入理解它们的工作原理和使用方式。 在本文中&#xff0c;我们将深入解析MySQL索引&#xff0c;探讨它…

JavaWeb——CSS3的使用

目录 1. CSS概述 2. CSS引入方式 3. CSS颜色显示 4. CSS选择器 4.1. 元素&#xff08;标签&#xff09;选择器 4.2. id选择器 4.3. 类选择器 4.4. 三者优先级 5. 盒子模型 1. CSS概述 CSS&#xff0c;全称为“Cascading Style Sheets”&#xff0c;中文译为“层叠样式…

除了http还有哪些通信协议?

除了HTTP协议外&#xff0c;还存在许多其他通信协议。以下是一些常见的通信协议&#xff1a; 1&#xff1a;HTTPS&#xff1a;HTTPS&#xff08;HTTP Secure&#xff09;是HTTP的安全版本&#xff0c;通过使用SSL&#xff08;Secure Sockets Layer&#xff09;或TLS&#xff0…

三、Vue3中使用Pinia修改State的方法

修改Pinia仓库的值有5种方式 src/store/index.ts import { defineStore } from pinia; import { Names } from ./store-name; export const useTestStore defineStore(Names.Test, {state:()>{return {current:1111,name: 小满111}},getters:{ // 类似computed计算属性 同…

OpenMediaVault控制台web页面密码重置

要重置 OpenMediaVault&#xff08;OMV&#xff09;Web 控制台的密码&#xff0c;可以使用 omv-firstaid 命令行工具中的相应选项。按照以下步骤进行操作&#xff1a; 以管理员权限登录到 OMV 的命令行界面&#xff08;通过 SSH 或直接登录&#xff09;。 ssh登陆到root用户 运…