如何从Rust调用C ++动态库?

Chi Wei Shen

我想从Rust调用一个C ++动态库(* .so),但是我不想从Rust构建它。像这样,

cc::Build::new()
    .file("src/foo.cc")
    .shared_flag(true)
    .compile("libfoo.so");

在某些情况下,我只需要调用几个函数,而不是所有函数。如何使用?

星系

在继续之前,请确保您具有Rust FFI(外部功能接口)的基本概念

在Rust中,调用C很容易,但是很难调用C ++。

要在Rust中调用C函数,只需将其包装起来extern,并进行一些基本的类型转换unsafe

要调用C ++函数,由于Rust没有内置的C ++功能知识,您可能需要做很多手动翻译。例如,这是Rust-Qt的文档的一部分

许多事情直接从C ++转换为Rust:

  • 基本类型映射到Rust的基本类型(如bool)和libc crate提供的类型(如libc::c_int)。
  • 固定大小的数值类型(例如int8_tqint8)被映射到Rust的固定大小类型(例如i8)。
  • 指针,引用和值映射到Rust的相应类型。
  • C ++名称空间被映射到Rust子模块。
  • C ++类和结构映射到Rust结构。这也适用于库API中遇到的所有模板类实例化,包括依赖项的模板类。
  • 自由功能映射到自由功能。
  • 类方法映射到结构的实现。
  • 析构函数映射到DropCppDeletable实现。
  • 函数指针类型映射到Rust的等效表示形式。不支持带有引用或类值的函数指针。
  • static_cast并且dynamic_cast可以通过相应的性状在Rust中使用。

Rust标识符的名称根据Rust的命名约定进行了修改。

如果无法直接翻译:

  • C ++库的每个包含文件的内容都放置在单独的子模块中。
  • 通过在元组中包装参数并创建描述每个方法可接受的元组的特征来模拟方法重载。具有默认参数的方法以相同的方式处理。
  • 单继承被翻译成DerefDerefMut实现,允许呼吁派生的对象基类的方法。当deref强制不足时,static_cast应使用将其从派生转换为基类。
  • 将为每个公共类字段创建Getter和setter方法。

尚未实施,但已计划:

  • 将C ++转换typedef为Rust类型的别名。
  • 基于C ++运算符方法(issue为结构实现运算符特征当前,运算符公开为带有op_前缀的常规函数
  • 如果C ++方面存在适用的方法,请为结构实现Debug和Display特性。
  • 实现集合的迭代器特征。
  • 子类化API(问题)。
  • 提供对类的公共变量(问题)的访问。
  • 提供从枚举到int的转换(在Qt API中使用)。
  • 支持嵌套在模板类型中的C ++类型,例如Class1<T>::Class2

不打算支持:

  • 高级模板用法,例如带有整数模板参数的类型。
  • 模板部分专业化。
  • 模板方法和功能。

我的建议是将C ++库包装为C库,然后将其称为正式FFI方式,或者使用rust-bindgen自动进行包装。

如果您仍然想在Rust中调用C ++,则rustcxx似乎是一个方便的工具。

关于库链接,这很简单:

  • 将库放入系统库搜索路径中,例如/usr/lib/usr/local/lib/,确保可以通过找到ldconfig -p
  • 或使用环境变量LD_LIBRARY_PATH来指定cargo从CLI运行时库所在的路径

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章