Используйте искаженные функции Rust из библиотеки Rust Dynami c - PullRequest
2 голосов
/ 19 марта 2020

Редактировать примечание

Поскольку у Rust (вер. 1.42) все еще нет стабильного ABI , рекомендуется использовать extern (что в настоящее время эквивалентно extern "C" (может измениться в будущем)) В противном случае может потребоваться перекомпиляция библиотек. В этой статье объясняется, как изменить соглашение о вызовах .


Цель состоит в том, чтобы иметь возможность работать с искаженными именами (что позволило бы сосуществование функций из разных модулей / пространств имен, имеющих одинаковые идентификаторы) внутри ящика, который использует библиотеку. Я заметил, что Rust (вер. 1.42) автоматически предполагает, что идентификаторы функций экспортируемых функций не искажены. На данный момент я могу успешно связать его и использовать при использовании #[no_mangle] и #[export_name="..."] в функциях. Я использую набор инструментов stable-x86_64-windows-pc-msvc.


Рабочий пример

rslib / lib.rs:

#[no_mangle] /* Exports it as "func" */
pub extern fn func() { ... }

app / main.rs:

#[link(name="rslib.dll", kind="dylib")]
extern { fn func(); }

fn main() {
    unsafe { func(); }
}

Компилируется и запускается без проблем.


Пример не работает

rslib / lib .rs:

pub extern fn func() { ... }

Использование того же "app / main.rs" приводит к сбою связи с: error LNK2019: unresolved external symbol __imp_func referenced in function _ZN8rust_app4main17h52189e261ef80b93E.

1 Ответ

2 голосов
/ 19 марта 2020

Решение вручную

Решение, которое я нашел, заключается в том, чтобы вручную поместить #[link_name="..."] в функции в блоке extern. Таким образом, можно также иметь модули, которые используют импортированные функции. Примечание: возможно с макросами! rslib / lib.rs:

pub mod foo {
    #[export_name="foo_func"] /* Also possible to append some identification for different parameters if desired */
    pub extern fn func() { ... }
}

#[export_name="func"]
pub extern fn func() { ... }

app / main.rs:

mod foo {
    #[link(name="rslib.dll", kind="dylib")]
    extern {
        #[link_name="foo_func"]
        pub fn func();
    }
}

#[link(name="rslib.dll", kind="dylib")]
extern {
    #[link_name="_func"]
    pub fn func();
}

fn main() {
    unsafe {
        func();
        foo::func();
    }
}
...