Согласованные идентификаторы типов для динамически загружаемых ящиков

У меня есть система плагинов, в которой я передаю &dyn Any динамически загружаемой функции ржавчины, но при понижении значения ссылки не получается, потому что TypeId различаются (для одного и того же типа), хотя я добавил rustflags = ["-Cmetadata=12345678"] в конфигурацию груза обоих ящиков. Также кажется, что затронуты только типы из внешних ящиков (я пробовал (), и он дал одинаковый 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 ящиков, и теперь я получаю тот же TypeId для toml::Value, однако TypeId типа в ящике 1, который я хочу уменьшить в ящике 2, по-прежнему отличается.


person TobiP64    schedule 17.08.2019    source источник
comment
Вы уверены, что это не проблема версии ящика? Например, для ящика 1 требуется toml 0.4.5, а для ящика 2 требуется 0.4.8 или что-то в этом роде?   -  person trentcl    schedule 17.08.2019
comment
Это было мое первое предположение, но я очистил, обновил и перестроил все ящики. Я также проверил зависимости, и версия во всех трех ящиках одинакова.   -  person TobiP64    schedule 17.08.2019
comment
Я не верю, что какие-либо -C параметры повлияют на идентификаторы типов; это для кодогенерации. Идентификаторы типа разрешаются внутри самого rustc, прежде чем он передается в LLVM.   -  person trentcl    schedule 17.08.2019
comment
Где-то читал, что влияет на TypeId ген. В любом случае, я удалил эту опцию из всех 3 ящиков, и теперь я получаю то же TypeId для toml::Value, но не для типа в ящике 3, который я хочу уменьшить в ящике 2. Так что это фактически влияет на TypeId, но не так, как я думал оно делает.   -  person TobiP64    schedule 18.08.2019
comment
По собственной некомпетентности забыл перекомпилировать один ящик. Теперь только TypeId типа в ящике загрузчика по-прежнему отличается.   -  person TobiP64    schedule 18.08.2019


Ответы (1)


После некоторого тестирования я обнаружил, что TypeIds разные, потому что ящик загрузчика (ящик 1) используется в качестве библиотеки в двух других ящиках, но выполняется как двоичный файл.

Чтобы обойти эту проблему, я извлек все типы ящика 1, которые я хотел использовать в загруженных ящиках, в новый ящик и добавил их в зависимости каждого ящика. Этот новый ящик всегда используется только как библиотека, а не как двоичный файл, поэтому TypeIds должны быть согласованными.

Краткое изложение всего, что мне нужно было сделать, чтобы он заработал:

  • использовать одну и ту же версию инструментальной цепочки для всех ящиков
  • использовать одни и те же версии зависимостей во всех ящиках
  • не используйте -Cmetadata, это больше не работает и фактически дает обратный эффект
  • извлеките все типы, которые используются в ящике загрузчика и загруженных ящиках, в новый ящик и добавьте его во все зависимости ящиков
  • всякий раз, когда вы что-то меняете в этом «ящике общих типов», вам нужно перекомпилировать все остальные ящики, чтобы TypeIdS были в актуальном состоянии

Если у вас все еще есть проблема, вы можете вернуться к небезопасной ржавчине (например, unsafe { &*(value as *const dyn Any as *const Type)}). Обратите внимание, что здесь вообще нет проверок, поэтому вы можете столкнуться с ошибками сегментации, если типы не совпадают.

Особая благодарность @trentcl за то, что указал мне в правильном направлении.

person TobiP64    schedule 18.08.2019