Plugins 惯用生锈插件系统

Plugins 惯用生锈插件系统,plugins,rust,Plugins,Rust,我想外包一些插件系统的代码。在我的项目中,我有一个叫做Provider的特性,它是我的插件系统的代码。如果你激活“消费者”功能,你可以使用插件;如果你没有,你就是插件的作者 我希望插件的作者通过编译到一个共享库,将他们的代码输入到我的程序中。共享库是一个好的设计决策吗?插件的局限性是无论如何都要使用Rust 插件主机加载共享库是否必须采用C方式:加载非混合函数 我只想让作者使用trait提供者来实现他们的插件,就这样。 在查看和之后,似乎不可能以惯用的方式加载插件 我只想将trait对象加载到我

我想外包一些插件系统的代码。在我的项目中,我有一个叫做
Provider
的特性,它是我的插件系统的代码。如果你激活“消费者”功能,你可以使用插件;如果你没有,你就是插件的作者

我希望插件的作者通过编译到一个共享库,将他们的代码输入到我的程序中。共享库是一个好的设计决策吗?插件的局限性是无论如何都要使用Rust

插件主机加载共享库是否必须采用C方式:加载非混合函数

我只想让作者使用trait
提供者
来实现他们的插件,就这样。 在查看和之后,似乎不可能以惯用的方式加载插件

我只想将trait对象加载到我的
ProviderLoader

// lib.rs

pub struct Sample { ... }

pub trait Provider { 
    fn get_sample(&self) -> Sample;
}

pub struct ProviderLoader {
    plugins: Vec<Box<Provider>>
}
如果插件被编译成共享libs,这是可能的吗?这也会影响插件板条箱类型的决定

你还有其他想法吗?也许我走错了路,所以共享lib不是圣杯


我第一次把这个贴在网上。一位朋友建议我尝试一下堆栈溢出。

没有正式的插件系统,你不能在运行时用纯Rust加载插件。我看到了一些关于做一个本地插件系统的讨论,但是现在还没有决定,也许永远不会有这样的事情。您可以使用以下解决方案之一:

  • 您可以使用本机动态库扩展代码。要使用C ABI,您必须使用,
    no_mangle
    属性,
    extern
    等。您可以通过在Internet上搜索Rust FFI来查找更多信息。在这个解决方案中,您必须使用原始指针:它们没有安全保证(即,您必须使用不安全的代码)

    当然,您可以用Rust编写动态库,但是要加载它并调用函数,您必须通过C ABI。这意味着生锈的安全保证不适用于该区域。此外,不能在库和二进制文件之间使用Rust的最高级别功能,如
    trait
    enum

  • 如果您不想要这种复杂性,您可以使用一种适合于扩展Rust的语言:通过这种语言,您可以动态地向代码中添加函数,并以与Rust中相同的保证执行它们。在我看来,这是一种更简单的方法:如果您有选择,并且执行速度不是很关键,使用它来避免复杂的C/Rust接口

    下面是一个(并非详尽的)可以轻松扩展的语言列表:

    • ,一种类似Haskell的函数式语言
    • ,一种小型但功能强大的脚本语言,用于视频游戏
    • 卢阿与奥特
    您还可以使用或Javascript,或查看中的列表

  • 更新日期:2018年3月27日: 在以这种方式使用插件一段时间后,我不得不提醒大家,根据我的经验,事情确实会变得不同步,调试起来可能会非常令人沮丧(奇怪的segfaults、奇怪的操作系统错误)。即使在我的团队独立验证依赖项是同步的情况下,在动态库二进制文件之间传递非原始结构也会由于某种原因在OSX上失败。我想重温一下,看看它发生在什么情况下,也许会引起生锈的问题,但我建议今后要谨慎行事

    LLDB和valgrind对于调试这些问题几乎至关重要

    简介 我自己也一直在调查这些事情,我发现几乎没有关于这方面的官方文件,所以我决定四处玩玩

    首先让我注意到,由于没有关于这些属性的官方说法,请不要依赖任何代码,如果你试图阻止飞机在空中或核导弹错误发射,至少在没有进行比我更全面的测试的情况下。如果这里的代码删除了你的操作系统,并通过电子邮件向你当地的警察发送了一份犯下黄道带谋杀罪的含泪认罪书,我对此不负责;我们正处在生锈的边缘,从一个版本或工具链到另一个版本,情况可能会发生变化

    我曾在Windows 10(
    stable-x86\u 64-pc-Windows-msvc
    )和Cent OS 7(
    stable-x86\u 64-unknown-linux-gnu
    )上的调试和发布配置中,在Rust 1.20 stable上对其进行了个人测试

    方法 我采取的方法是共享
    common
    板条箱,这两个板条箱都列为定义common
    struct
    trait
    定义的依赖项。起初,我还打算测试两个库中独立定义的具有相同结构或相同定义的trait的结构,但我选择了它,因为它太脆弱,您不希望在实际设计中使用它。也就是说,如果有人想测试这个,可以在上面的存储库上随意做一个PR,我会更新这个答案

    此外,Rust插件被声明为
    dylib
    。我不确定编译为
    cdylib
    时会如何交互,因为我认为这意味着加载插件时会有两个版本的Rust标准库(因为我相信
    cdylib
    静态地将Rust stdlib链接到共享对象)

    测验 一般说明
    • 我测试的结构没有声明为
      #repr(C)
      。这可以通过保证布局提供额外的一层安全性,但我最感兴趣的是编写“纯”的锈菌插件,尽可能少地“像C一样处理锈菌”。我们已经知道你可以通过FFI使用Rust,方法是用不透明的指针包装东西,手动放置,等等,所以测试这一点不是很有启发性
    • 我使用的函数签名是
      pub fn foo(args)->output
      [no#mangle]
      指令,结果是
      rustfmt
      自动将
      外部“Rust”fn
      更改为