外部函数接口FFI

2023-12-17 03:12
文章标签 接口 函数 外部 ffi

本文主要是介绍外部函数接口FFI,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

在某些场景下,你的RUST代码可能需要与另外一种语言编写的代码进行交互。RUST为此提供了extern关键字来简化创建和使用外部函数接口(Foreign Function Interface,FFI)。FFI是编程语言定义函数的一种方式,它允许其它编程语言来调用这些函数。

extern "C" {fn abs(input: i32) -> i32;
}fn main() {unsafe {println!("Hello, world!{}", abs(-3));}
}

这段代码在extern "C"列出了我们想要调用的外部函数名称及签名,其中的"C"指明了外部函数使用的二进制接口(Application Binary Interface,ABI):它被用来定义函数在汇编层面的调用方式。我们使用的"C" ABI正是C编程语言的ABI,也是最常见的ABI格式之一。

ABI前世今生

我们浏览了Rust-ABI 的前世今生这篇博客。

在计算机软件中,应用二进制接口(ABI)是两个二进制程序模块之间的接口;通常这些模块之一是库或操作系统工具,而另一个是用户正在运行的程序。

C-ABI包含两个关键的内核:

  • 数据的内存布局方式
  • 函数如何调用

RUST目前的ABI并不稳定,即RUST不保证内存中数据结构的调用约定和内存布局不被改变。

这里有几个示例来说明什么是不稳定的ABI

// 虽然下面的结构体本质是相同的,但是 Rust 编译器不保证给予它们字段相同的内存偏移量
struct A(u32, u64);
struct B(u32, u64);// Rust 编译器不保证字段的顺序和定义的一样
struct Rect {x: f32,y: f32,w: f32,h: f32,
}

RUST编译器会对上面的结构体进行优化,如果内存布局是确定的,就不利于优化了。比如没有办法对结构体字段进行重排以便达到最小化内存占用的优化目标。内存布局不确定性也有利于模糊测试(Fuzzer),因为模糊测试需要将字段随机排列以便更容易地暴露潜在的问题。

#[repr(C)]
struct MyStruct {x: u32,y: Vec<u8>,z: u32,
}

对于该示例来说,虽然使用了#[repr(C)]让结构体字段的顺序确定了,但是字段的偏移量依然无法确定,因为Vec<8>没有任何确定性的排序,从而z的偏移量是无法确定的。所以这种类型不适合使用CFFI

作者尝试动态加载实现插件,发现RUST ABI不稳定带来的问题比想象的更加严重。在这之前,他一直认为即使RUST ABI不稳定,只要库和主二进制文件是用相同的编译器以及std等版本编译的,就可以安全地动态加载一个库。然而事实证明,ABI不仅仅是可能在不同编译版本之间发生”断裂“,在编译器执行的过程中也会发生断裂,即RUST编译器并不保证同一个类型的布局在每次执行的时候都一致,类型布局可以随着每次编译而改变。所以他的方案是使用#[repr(C)]C-ABI以及使用abi_stable来获得稳定的std库。

作者后面尝试使用abi_stable来开发插件系统。abi_stable是按模块来构建的,并且提供了很多FFI安全的类型(指FFI边界提供了稳定的内存布局),包括trait对象的支持及提供了处理FFI边界panic的方法。

这篇关于外部函数接口FFI的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/502886

相关文章

spring中的ImportSelector接口示例详解

《spring中的ImportSelector接口示例详解》Spring的ImportSelector接口用于动态选择配置类,实现条件化和模块化配置,关键方法selectImports根据注解信息返回... 目录一、核心作用二、关键方法三、扩展功能四、使用示例五、工作原理六、应用场景七、自定义实现Impor

Python中help()和dir()函数的使用

《Python中help()和dir()函数的使用》我们经常需要查看某个对象(如模块、类、函数等)的属性和方法,Python提供了两个内置函数help()和dir(),它们可以帮助我们快速了解代... 目录1. 引言2. help() 函数2.1 作用2.2 使用方法2.3 示例(1) 查看内置函数的帮助(

C++ 函数 strftime 和时间格式示例详解

《C++函数strftime和时间格式示例详解》strftime是C/C++标准库中用于格式化日期和时间的函数,定义在ctime头文件中,它将tm结构体中的时间信息转换为指定格式的字符串,是处理... 目录C++ 函数 strftipythonme 详解一、函数原型二、功能描述三、格式字符串说明四、返回值五

MybatisPlus service接口功能介绍

《MybatisPlusservice接口功能介绍》:本文主要介绍MybatisPlusservice接口功能介绍,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友... 目录Service接口基本用法进阶用法总结:Lambda方法Service接口基本用法MyBATisP

Java -jar命令如何运行外部依赖JAR包

《Java-jar命令如何运行外部依赖JAR包》在Java应用部署中,java-jar命令是启动可执行JAR包的标准方式,但当应用需要依赖外部JAR文件时,直接使用java-jar会面临类加载困... 目录引言:外部依赖JAR的必要性一、问题本质:类加载机制的限制1. Java -jar的默认行为2. 类加

Python中bisect_left 函数实现高效插入与有序列表管理

《Python中bisect_left函数实现高效插入与有序列表管理》Python的bisect_left函数通过二分查找高效定位有序列表插入位置,与bisect_right的区别在于处理重复元素时... 目录一、bisect_left 基本介绍1.1 函数定义1.2 核心功能二、bisect_left 与

java -jar命令运行 jar包时运行外部依赖jar包的场景分析

《java-jar命令运行jar包时运行外部依赖jar包的场景分析》:本文主要介绍java-jar命令运行jar包时运行外部依赖jar包的场景分析,本文给大家介绍的非常详细,对大家的学习或工作... 目录Java -jar命令运行 jar包时如何运行外部依赖jar包场景:解决:方法一、启动参数添加: -Xb

java中BigDecimal里面的subtract函数介绍及实现方法

《java中BigDecimal里面的subtract函数介绍及实现方法》在Java中实现减法操作需要根据数据类型选择不同方法,主要分为数值型减法和字符串减法两种场景,本文给大家介绍java中BigD... 目录Java中BigDecimal里面的subtract函数的意思?一、数值型减法(高精度计算)1.

C++/类与对象/默认成员函数@构造函数的用法

《C++/类与对象/默认成员函数@构造函数的用法》:本文主要介绍C++/类与对象/默认成员函数@构造函数的用法,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录名词概念默认成员函数构造函数概念函数特征显示构造函数隐式构造函数总结名词概念默认构造函数:不用传参就可以

C++类和对象之默认成员函数的使用解读

《C++类和对象之默认成员函数的使用解读》:本文主要介绍C++类和对象之默认成员函数的使用方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录一、默认成员函数有哪些二、各默认成员函数详解默认构造函数析构函数拷贝构造函数拷贝赋值运算符三、默认成员函数的注意事项总结一