Используйте искаженные функции Rust из динамической библиотеки Rust

Редактировать заметку

Поскольку в 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.


person K. Mihaylov    schedule 19.03.2020    source источник


Ответы (1)


Ручное решение

Решение, которое я придумал, - это вручную разместить #[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();
    }
}
person K. Mihaylov    schedule 19.03.2020