定义一个可以使用多个“后端”之一来实现其需要执行的操作的板条箱的惯用方法是什么?

Ber*_*ard 6 rust rust-cargo

我正在编写一个 Rust,它包含一些特定于平台的 API 调用(在本例中,用于打开文件选择器)。

在 Linux 上,有两种方法(“后端”)打开文件选择器 - 使用 GTK 或使用 Portal(它们实际上是什么对于这个问题的目的并不重要 - 只需将它们视为两个不同的系统库可以用来打开文件选择器)。通常,选择取决于应用程序开发人员是否想要可移植性 (GTK) 还是“本机”性 (Portal),并且后端的选择会影响我的库需要链接的库(在 build.rs 中指定)。不可能同时使用两者,因为向用户公开的接口是相同的(这就是要点 - 调用我的库的代码不必关心正在使用的后端,而只与系统库之一链接) 。

应该如何编写 Cargo.toml 文件以允许我的库的用户选择他们想要的后端?

在 CMake 中,这通常如下所示:

set(BACKEND "GTK" CACHE STRING "Select the backend (GTK or Portal)")
Run Code Online (Sandbox Code Playgroud)

在 Cargo 中,我们有“功能”。然而,功能只能“启用”或“禁用”,并且从语义上讲,功能似乎意味着有条件地将代码添加到要编译的库中。虽然有一个关于互斥功能的部分,但它看起来非常像黑客,并且其他选项似乎也不理想。

理想情况下,如果其他库依赖于我的库,他们不需要(甚至尝试)选择所需的后端。最终可执行应用程序的开发人员应该是做出决定的人。

Fin*_*nis 3

我不确定这是否惯用,但我会这样解决你的问题:

  • 创建一个trait描述后端所需功能的文件。
  • 创建一个struct包含库的所有状态的文件。
  • 要求将实际后端通过构造函数参数(作为特征对象)传递到您的库中并将其存储在状态结构中
  • 如果其他库需要使用您的库,请通过引用或类似方式将所述状态结构传递给他们

或者:

  • 创建一个trait描述后端所需功能的文件。
  • 在您的库中创建一个静态Option<dyn BackendTrait>文件和一个需要在开始时调用的初始化函数,main以设置所需的后端。

无论哪种方式,实际的后端都可以在单独的包中交付,最终的可执行文件负责链接正确的后端并在运行时设置它。