3个版本
0.1.2 | 2020年7月1日 |
---|---|
0.1.1 | 2020年6月30日 |
0.1.0 | 2020年6月30日 |
#1243 in 过程宏
用于 2 crate
58KB
1.5K SLoC
FFIShim
许多常见的Rust类型(例如,像String
)不能通过FFI传递,因为它们的内存布局与C ABI不匹配(String
的末尾没有空字节)。这使得使用原生的Rust类型和从FFI调用该代码变得困难。
这个crate提供了一个shim,该shim将公开FFI兼容的数据结构和函数包装器,用于原生Rust类型和函数。
以下是一个使用原生String
并从C调用它的Rust代码的快速示例
#[ffishim_function]
fn hello(s: String) -> String {
format!("Hello, {}!", s)
}
您应该能够如下从C调用它
#include "ffishim/header.h"
extern result_t *ffi_hello(char *s);
int main() {
char *ffi = malloc(sizeof(char) * 4);
ffi[0] = "f";
ffi[1] = "f";
ffi[2] = "i";
ffi[3] = "\0";
result_t *res = ffi_hello(ffi)
if (res->message != NULL) {
printf("error: %s\n", res->message);
free(res->message);
} else {
printf("%s\n", res->payload);
free(res->payload);
}
free(res);
}
这将打印
Hello, ffi!
由于某些类型转换可能会失败,函数总是返回一个result_t
类型,该类型包含指向错误消息的指针和有效负载。在出现错误的情况下,有效负载为空,消息包含错误字符串。
更多示例
您可以通过查看tests
文件夹来找到更多关于shim行为的示例。测试的结构如下
src/lib.rs
:要公开的Rust库Cargo.toml
:Rust库的清单main.c
:使用此Rust库的C代码expected_output
:包含运行C程序时预期的输出
每个测试crate都是一个利用ffishim库的独立应用程序。它们将说明如何设置库并使用它。
C ABI免责声明
这个crate目前不生成与C ABI兼容的绑定。这是因为它已被设计为与dustr一起使用,该工具在ffi shim之上生成Dart绑定。
由于Dart ffi支持仍处于alpha阶段,它还不能完全消费C ABI。例如,它不支持嵌套结构,并且结构不能按值传递给函数。
TODO/限制
这个crate仍处于beta阶段。它还不适合用于生产。
错误
- 从标量类型到libc类型的映射应该只引用libc类型或者都不引用
- 在.so文件中不同crate之间可能会出现名称冲突:例如,如果有两个crate中存在名为
Config
的结构体,那么函数名free_config
就会发生冲突。需要使用名称混淆
功能
- 将
from
改为try_from
?(无效的Rust字符串转换为CString的不安全操作) - 如果使用
feature(ffishim)
而不是ffi_
前缀,则替换函数 - 明确重新考虑对
::anyhow::Error
的依赖 - chrono日期的类型行为
测试
- 添加一个“完整”的测试/示例场景
- 设计基准测试策略和框架
- 添加枚举的测试
文档
- 编写README.md介绍,说明这个crate的功能
- 编写
ffishim_derive
文档,说明如何使用宏
依赖
~0.7–1.3MB
~28K SLoC