50

我有一个有很多代码的板条箱,所以我把它分成了多个文件/模块。但是,有些模块有内部不安全的东西(例如原始指针),我需要将它们公开给不同的模块,但我不想暴露给我的 crate 的用户。我怎样才能做到这一点?

我能想到的唯一方法是实际上让我的板条箱只是一个大模块,但是没有办法将它分成不同的文件,除了这个似乎有点hacky的解决方案。

通常,当我遇到 Rust 文档中的简单示例无法充分解释的现实世界问题时,我只是复制一个流行的现实世界 crate,例如git2-rs,但这似乎有效地公开了所有内容,包括原始指针。

4

1 回答 1

72

为了从库 crate 中导出项目,必须至少有一个通向它的路径,其中每个组件都是公共的。这意味着你需要在你的 crate 中公开一个项目而不是从 crate 中导出(从现在开始我称之为“内部”,以模仿 C# 术语)就是将它放在 crate 根目录下的私有模块中.

但是,该解决方案具有很大的限制性。如果您想要一个具有导出函数内部函数的模块怎么办?为了导出某些功能,我们需要将模块设为公共,这意味着该模块中的所有公共项也将被导出。

Rust 1.18开始,有一个适合这种场景的解决方案:pub(restricted). 此功能可让您指定项目的“公开程度”。语法非常灵活(您可以使项目对特定模块树而不是整个 crate 可见),但如果您想保持简单,pub(crate)将使项目在 crate 中的任何位置都可访问,但对其他 crate 不可用(等效在internalC# 中)。

例如,假设我们想要一个模块util,其中foo导出(as mycrate::util::foo),bar是内部的并且baz是模块私有的。代码可能如下所示:

pub mod util {
    pub fn foo() {
        unimplemented!()
    }

    pub(crate) fn bar() {
        unimplemented!()
    }

    fn baz() {
        unimplemented!()
    }
}

如果你被 1.18 之前的 Rust 卡住了,有一个解决方法,但它有点笨拙。它涉及在私有模块中定义所有项目,并仅在仅包含重新导出的公共模块中重新导出您想要公开(使用pub use)的项目。上面的示例如下所示:

pub mod util {
    pub use util_impl::foo;
}

mod util_impl {
    pub fn foo() {
        unimplemented!()
    }

    pub fn bar() {
        unimplemented!()
    }

    fn baz() {
        unimplemented!()
    }
}

这不仅不容易阅读和理解,而且没有涵盖所有pub可以使用的情况。例如,如何使导出结构的某些字段在同一个 crate 中的其他模块中可访问,而不导出它们?唯一的选择是公开一个带有单个私有字段的包装器,其类型是具有公共字段的结构;如果您想从其他 crate 中隐藏所有字段,那效果很好,但如果您想公开一些字段在同一个结构中创建一些其他字段,则不行。

于 2017-01-15T22:48:35.767 回答