У меня есть пара ящиков X и Y. Первый управляет низкоуровневыми вещами и определяет точку входа. Затем он должен передать управление Y, который выполняет лог c высокого уровня. Я хотел бы явно объявить функцию Y в X и вызвать ее (чтобы компоновщик соединял их при создании Y-ящика).
Я знаю, что Rust имеет нестабильный ABI, но я использую оба этих ящика в одном рабочая область с тем же компилятором.
Я пробовал использовать следующий пример, но компоновщик не может найти real_main
(неопределенная ссылка ...):
// X's main.rs
#[link(name = "y_lib_name", link = "static")]
extern "Rust" {
fn real_main();
}
fn main() {
// is it possible to avoid unsafe here, btw?
unsafe { real_main() }
}
// Y's lib.rs
pub fn real_main() { .. }
Хотя символ существует:
$ nm target/debug/deps/liby_lib_name-8ade2b95fe4044c6.rlib | rg real_main
nm: lib.rmeta: file format not recognized
0000000000000000 T _ZN8y_lib_name9real_main17h8664760a5d2676beE
Думаю, мою проблему можно решить с помощью макроса в X, например:
// in X
#[macro_export]
macro_rules define_ep! {
($fn:expr) => {{ fn main() { $fn(); } }}
}
// in Y
fn f() {}
X::define_ep!(f);
, но я бы предпочел способ с поддержкой компоновщика, потому что:
- если вы забыли компоновщик, выдает ошибку;
- (не уверен) компоновщик выдает ошибку, если символы появляются более одного раза.