3个版本
0.1.2 | 2020年7月1日 |
---|---|
0.1.1 | 2020年6月30日 |
0.1.0 | 2020年6月30日 |
#99 in #c
67KB
1.5K SLoC
FFIShim
许多常见的Rust类型(例如,例如,String)不能通过FFI传递,因为它们在内存中的布局与C ABI不匹配(String的末尾没有空字节)。这使得使用本地Rust类型并从FFI调用该代码变得困难。
此crate提供了一个垫片,将公开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类型,该类型包含一个指向错误消息的指针和一个有效负载。在发生错误的情况下,有效负载为nil,而消息包含错误字符串。
更多示例
您可以通过查看tests
文件夹来找到更多关于垫片行为的示例。测试的结构如下
src/lib.rs
:要公开的Rust库Cargo.toml
:Rust库的清单main.c
:使用此Rust库的C代码expected_output
:包含从运行C程序预期得到的输出
每个测试crate都是利用ffishim库的独立应用程序。它们将说明如何设置库并使用它。
C ABI免责声明
此crate目前不生成与C ABI兼容的绑定。这是因为它已被设计为与dustr一起使用,它在此ffi垫片之上生成Dart绑定。
由于dart ffi支持目前处于alpha阶段,因此它还不能完全消耗C ABI。例如,它不支持嵌套结构,并且结构不能按值传递给函数。
待办/限制
此crate仍处于beta阶段。目前不适合用于生产环境。
错误
- 标量类型到libc类型的转换应该只引用libc类型或都不引用
- 在.so文件中,crate之间会出现名称冲突:例如,如果2个crate中存在
Config
结构体,则函数名称free_config
需要名称混淆
特性
from
应该变为try_from
?(无效的Rust字符串 -> CString不安全)- 如果使用
feature(ffishim)
而不是ffi_
前缀来替换函数 - 明确重新考虑对
::anyhow::Error
的依赖 - chrono日期的类型行为
测试
- 添加一个“完整”的测试/示例场景
- 设计基准测试策略和框架
- 添加枚举的测试
文档
- 编写README.md简介,介绍此crate的功能
- 编写
ffishim_derive
文档,说明如何使用宏
依赖
~0.8–1.4MB
~30K SLoC