Вызов внешней функции в dylib

#rust #dylib

#Ржавчина #dylib

Вопрос:

У меня есть основное приложение с кодом, который выглядит следующим образом:

 pub fn load_lib() {
    let dylib = libloading::Library::new("example.dylib") ...
    unsafe { *dylib.get(b"fn_in_dylib") } ...
    // calling function from dylib.
}
pub extern "Rust" fn fn_in_main_app() { ... } // Function that I want to call from dylib
  

example.dylib dyliib успешно загружен, и функция из dylib вызывается без каких-либо проблем.

Но вот что я пытаюсь сделать внутри dylib:

 pub extern "Rust" fn fn_in_dylib() {
    fn_in_main_app(); // Here I'm trying to call function defined in main application.
}
extern "Rust" {
    fn fn_in_main_app();
}
  

Но это даже не компилируется:

 Undefined symbols for architecture x86_64:
    "_fn_in_main_app", referenced from:
  

Я не уверен, что использую правильный способ реализации этого, поэтому меня не удивило, когда он не скомпилировался. Но я надеюсь, что это показывает, что я на самом деле пытаюсь.

Ответ №1:

Dylibs не могут зависеть от приложения, которое их загружает. График зависимостей dylib должен быть полностью линейным, циклические зависимости не допускаются. В зависимости от того, что вы делаете, может быть возможно перейти fn_in_main_app к восходящей зависимости dylib. Вы также можете передать указатель на функцию в dylib:

 pub extern "Rust" fn fn_in_dylib(fn_in_main_app: fn()) {
    (fn_in_main_app)();
}
  

Комментарии:

1. Хорошо, это имеет смысл, теперь я пытаюсь передать указатель на функцию через статическую переменную. Хотя предложенный вами способ по-прежнему позволяет устанавливать статическую переменную через некоторую init() функцию, может быть, можно сделать статическую переменную «внешней»?

2. Хорошо, кажется, невозможно объявить extern static . Я использовал статическую переменную в качестве указателя fn функцию extern init, которая присваивает фактический указатель функции статической переменной. Это работает.

3. В macOS есть понятие «пакетов», то есть плагинов, которые вы можете создавать, передавая -bundle компоновщику, и которые могут связываться с символами из основного исполняемого файла — но тогда, конечно, основной исполняемый файл не может связываться с символами из плагина.