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

Rust-FFI复杂参数传递处理方式1--数组类型

预先知识点

1.FFI (Foreign Function Interface) 是 Rust 中非常重要的一个部分,它主要在两个领域应用较广泛:
第一个是系统开发,这部分包括对 OS 系统调用的封装,对系统底层 C 库的封装,广泛平台的嵌入式/IoT 开发,OS 开发,充分利用现代硬件平台的性能优势。
第二个是跨语言开发,可以使用 Rust 语言为其它(几乎任何)语言写调用库,互相调用等。
利用 FFI,Rust 终能迅速切入巨大的存量遗产,同时也能牢牢把握新兴增量领域。螃蟹怎么横着走?就是有了FFI。

2.C语言和Rust的相互调用,最核心的就是指针的操作,两边的代码使用的是同一个程序栈,栈上的指针能放心地传递,而不用担心被错误释放的问题(栈上内存被调用规则自动管理,C和Rust中都是如此)。两边的代码可能使用不同的堆分配器,因此,堆上的指针的传递需要严格注意,需要各自管理各自的资源,谁创建谁释放,指针传递过程中,需要分析所有权问题。栈和堆的操作是不同的,这里一定要注意。

复杂参数传递处理方式1–数组类型

前面两个例子是最简单的整型类型的参数传递,能说明 Rust 导出共享库的基本模板操作,但在函数参数这块儿,能说明的问题有限。
C调用Rust,传入一个数组并返回一个求和之后的数。
C语言代码:

#include <stdio.h>
#include <stdint.h>
 
extern uint32_t sum_of_array(const uint32_t *numbers, size_t length);
 
int main(void) {
  uint32_t numbers[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
  unsigned int length = sizeof(numbers) / sizeof(*numbers);
  uint32_t sum = sum_of_array(numbers, length);
  printf("print in c, sum is: %d\n", sum);
}

Rust代码:

use std::slice;
 
#[no_mangle]
pub extern "C" fn sum_of_array(array: *const u32, len: usize) -> u32 {
    let array = unsafe {
        assert!(!array.is_null());
        slice::from_raw_parts(array, len)
    };
   array.iter().sum()
}

对上面的代码解读:
1.对于数组的传递,分成了两个部分,一个是数组地址指针的传递(首元素指针),另一个是数组的长度(即元素的个数,非字节数)。
2.对于C语言中,数组是分配在栈上的,Rust 代码中,参数中的 *const u32 就对应 C 中的 const uint32_t *。
3.C语言传入的指针,Rust必须保证是绝对不能为空指针的,所以使用assert进行捕获。
4.slice::from_raw_parts(array,len)的作用是从一个指针和一个长度形成一个切片,长度还是元素的个数。这里的array就是切片类型了。
5.Rust 拿到 C 传递过来的指针后,标准的规范是:
尽早转换为 Rust 的安全类型进行操作。也就是说,保证不安全(unsafe块中的)的代码尽量少,并且直接使用这个指针的代码尽可能的少,转换成 Rust 中的标准类型再用。
尽量保证 zero cost。避免不必要的内存 copy 操作,影响性能。
为满足第一条规则,在转换前,我们的代码没有任何相关的代码。
为满足第二条规则,这里使用了 slice 类型,而不是 Vec 类型,slice切片属于部分引用,而vec属于堆分配部分的使用,会进行内存copy。

相关文章:

  • 数组新增方法:forEach(),map(),filter(),some(),every()
  • 卷妹的成长日记之javaweb day14
  • java架构知识点-大数据与高并发(学习笔记)
  • MATLAB下载_MATLAB中文版下载
  • 手把手怎么把照片修复高清,p图小白也能轻松上手
  • SSM+服装管理系统 毕业设计-附源码080948
  • 网课搜题公众号题库接口使用详情方法
  • 061_末晨曦Vue技术_过渡 动画之自定义过渡的类名
  • 渗透测试-不死马的创建和查杀
  • 肾囊肿有什么症状呢?
  • MATLAB | 全网唯一 ,MATLAB绘制阴影柱状图(填充斜线)
  • Docker之docker设置系统的环境变量(第十五篇)
  • 分享查题公众号制作过程
  • webpack原理 - 5分钟了解ModuleGraph
  • 几分钟来了解下什么是嵌入式开发?
  • [NodeJS] 关于Buffer
  • HTTP 简介
  • java中的hashCode
  • Magento 1.x 中文订单打印乱码
  • Vue2 SSR 的优化之旅
  • 面试题:给你个id,去拿到name,多叉树遍历
  • 三分钟教你同步 Visual Studio Code 设置
  • 实现简单的正则表达式引擎
  • 手写双向链表LinkedList的几个常用功能
  • 详解移动APP与web APP的区别
  • 学习笔记:对象,原型和继承(1)
  • 用Visual Studio开发以太坊智能合约
  • 在 Chrome DevTools 中调试 JavaScript 入门
  • 职业生涯 一个六年开发经验的女程序员的心声。
  • 白色的风信子
  • 3月27日云栖精选夜读 | 从 “城市大脑”实践,瞭望未来城市源起 ...
  • linux 淘宝开源监控工具tsar
  • ​MPV,汽车产品里一个特殊品类的进化过程
  • (3)(3.5) 遥测无线电区域条例
  • (7)STL算法之交换赋值
  • (ZT) 理解系统底层的概念是多么重要(by趋势科技邹飞)
  • (七)理解angular中的module和injector,即依赖注入
  • (区间dp) (经典例题) 石子合并
  • (推荐)叮当——中文语音对话机器人
  • (转)C#调用WebService 基础
  • (转)淘淘商城系列——使用Spring来管理Redis单机版和集群版
  • .equal()和==的区别 怎样判断字符串为空问题: Illegal invoke-super to void nio.file.AccessDeniedException
  • .NET CF命令行调试器MDbg入门(三) 进程控制
  • .NET Core 2.1路线图
  • .Net Core 中间件验签
  • .NET Core工程编译事件$(TargetDir)变量为空引发的思考
  • .NET Entity FrameWork 总结 ,在项目中用处个人感觉不大。适合初级用用,不涉及到与数据库通信。
  • .NET LINQ 通常分 Syntax Query 和Syntax Method
  • .so文件(linux系统)
  • /var/log/cvslog 太大
  • ??eclipse的安装配置问题!??
  • @require_PUTNameError: name ‘require_PUT‘ is not defined 解决方法
  • @Tag和@Operation标签失效问题。SpringDoc 2.2.0(OpenApi 3)和Spring Boot 3.1.1集成
  • [ vulhub漏洞复现篇 ] Hadoop-yarn-RPC 未授权访问漏洞复现
  • [.NET 即时通信SignalR] 认识SignalR (一)