4

我有一个插件系统,我在其中传递&dyn Any给动态加载的 rust 函数,但向下转换引用失败,因为TypeIds 不同(对于相同类型),尽管我添加rustflags = ["-Cmetadata=12345678"]到两个 crate 的货物配置中。此外,似乎只有来自外部板条箱的类型受到影响(我尝试过(),它在两个板条箱中都产生了相同的结果TypeId)。我目前正在使用原始指针 ( unsafe { &*(v as *const dyn Any as *const Type) }) 来解决这个问题,但我更喜欢没有不安全代码的解决方案。

例如下面的代码:

println!("CRATE 1: TypeId of `()`: `{:?}`, TypeId of `toml::Value`: `{:?}`",
                 TypeId::of::<()>(), TypeId::of::<toml::Value>());

产生这个输出:

CRATE 1: TypeId of `()`: `TypeId { t: 7549865886324542212 }`, TypeId of `toml::Value`: `TypeId { t: 9270396907601429078 }`
CRATE 2: TypeId of `()`: `TypeId { t: 7549865886324542212 }`, TypeId of `toml::Value`: `TypeId { t: 5704635987193303200 }`

编辑:这似乎不是不同依赖版本的问题,因为板条箱 2(它是动态加载的)取决于板条箱 3(它也是动态加载的)并且问题仍然存在,尽管板条箱 2 和板条箱 3,是本地依赖项(因此只有一个版本)。板条箱 1 是顺便说一句。装载板条箱 2 和 3 的板条箱。

编辑:我-Cmetadata从所有 3 个 crate 中删除了该选项,现在我得到了相同TypeIdtoml::Value,但是TypeId我想在 crate 2 中向下转换的 crate 1 中的类型仍然不同。

4

1 回答 1

1

经过一些测试,我发现TypeIds 是不同的,因为 loader crate (crate 1) 在其他 2 个 crate 中用作库,但作为二进制文件执行。

为了解决这个问题,我将我想在加载的 crate 中使用的所有 crate 1 的类型提取到一个新的 crate 中,并将其添加到每个 crate 的依赖项中。这个新的 crate 只用作库而不是二进制文件,因此TypeIds 应该是一致的。

我必须做的所有事情的总结才能让它工作:

  • 对所有 crate 使用相同的工具链版本
  • 在所有 crate 中使用相同的依赖版本
  • 不要使用-Cmetadata,这不再起作用,实际上具有相反的效果
  • 将 loader crate 和加载的 crate 中使用的所有类型提取到一个新的 crate 中,并将其添加到所有 crate 的依赖项中
  • 每当您更改此“通用类型板条箱”中的某些内容时,您都必须重新编译所有其他板条箱,因此TypeIdS 是最新的

如果您仍然有问题,您可以退回到不安全的生锈(例如unsafe { &*(value as *const dyn Any as *const Type)})。请注意,根本没有检查,因此如果类型不匹配,您可能会遇到分段错误。

特别感谢@trentcl 为我指明了正确的方向。

于 2019-08-18T09:27:41.117 回答