かおるノート

cordx56のブログです

Rustで動的リンクライブラリを作る / 読み込む

こんにちは。 しばらくぶりの投稿になります。

シンプルにRustで動的リンクライブラリを作って読み込む記事が少ないように感じたので本記事を書くことにしました。 Rustで動的にリンクするライブラリを作りたい!、Rustで動的リンクライブラリを読み込みたい!という方は読んでいっていただければと思います。

Rustで動的リンクライブラリを作る

Rustで動的リンクライブラリを作ります。

Cargo.toml の編集

Cargo.toml を次のように編集します。

[package]
name = "dylib"
version = "0.1.0"
authors = ["cordx56"]
edition = "2018"

[lib]
crate-type = ["cdylib"]

[dependencies]

重要なのは [lib] 以下の2行です。 crate-type["cdylib"] を設定しています。

こうすることで、 $ cargo build がRust以外の言語からも利用できる動的リンクライブラリをビルドしてくれるようになります。 このオプションについて詳しくは Linkage - The Rust Reference を参照してください。

ライブラリ本体を書く

ライブラリ本体を書いていきます。

src/lib.rs に次のようなプログラムを書きました。

#[no_mangle]
pub extern "C" fn main() {
    println!("Hello, world!");
}

#[no_mangle] は名前マングリングをしないようにコンパイラに指示します。

extern "C" はCのABIを利用するようにRustコンパイラに指示します。

これでライブラリ本体が書けました。

ライブラリをビルドする

ビルドは簡単で、

$ cargo build

を実行するだけです。

Linux環境であれば、 target/debug/libdylib.so が生成されているはずです。 これが動的リンクライブラリです。

Rustで動的リンクライブラリを読み込む

前章で作成した動的リンクライブラリを読み込むプログラムを作ります。

Cargo.toml の編集

libloading クレートを利用します。

Cargo.toml を次のように編集します。

[package]
name = "testapp"
version = "0.1.0"
authors = ["cordx56"]
edition = "2018"

[dependencies]
libloading = "0.7.0"

読み込むプログラム本体を書く

動的リンクライブラリを読み込むプログラム本体を書いていきます。

src/main.rs に次のようなプログラムを書きました。

fn main() {
    unsafe {
        match libloading::Library::new("./libdylib.so") {
            Ok(lib) => {
                match lib.get::<libloading::Symbol<unsafe extern fn()>>(b"main") {
                    Ok(func) => {
                        func();
                    },
                    Err(_) => {
                        eprintln!("Function get error!");
                    }
                }
            },
            Err(_) => {
                eprintln!("Library link error!");
            }
        }
    }
}

詳しくはlibloadingのドキュメントを見てください。

動的リンクライブラリを配置する

前章で作成した libdylib.so をカレントディレクトリにコピーします。

実行する

$ cargo run

を実行して、 Hello, world! と表示されれば成功です。

おわり

以上でRustで動的リンクライブラリを作って読み込むことができました。

Rustで作った動的リンクライブラリをCで使ったり、Cで作った動的リンクライブラリをRustで使ったりもできるはずです(試してないので断言できませんが)。 それについてはまた後日記事を書こうかなと考えています。