C++ – Rust の関数を静的リンクで呼び出す

C++ から Rust の関数を呼び出す方法のメモです。
gcc を利用して、静的リンクで呼び出すケースについてまとめます。

目次

rustc でライブラリを生成する

cargo ではなく rustc でライブラリを生成する方法です。

Rust – 静的リンクライブラリの生成

Rust にて、2つの整数を足し算する add 関数を定義します。
これを C++ から呼び出します。

Filename: libadd.rs

#[no_mangle]
pub extern "C" fn add(a: i32, b: i32) -> i32 {
    a + b
}

コード作成後は、次のコマンドで静的リンクライブラリを生成します。
libadd.a ファイルが生成されます。

$ rustc --crate-type=staticlib libadd.rs -o libadd.a
$ ls libadd.a
libadd.a

ポイントは2つです。

  • no_mangle の属性を付与する
  • extern “C” を記述する

no_mangle は、関数名に特殊な装飾を指せないための指定です。
通常、言語の独自ルールで関数名がカスタマイズされてしまいますが、これを抑止させます。

extern “C” はバイナリインタフェースを Cルールにするという指定です。
今回の例ではこれがなくてもうまくいくかもしれませんが、関数呼び出し時の引数や戻り値の扱い方に影響します。

C++ – ライブラリの関数を呼び出し

C++ から静的リンクライブラリの add 関数を呼び出します。

こちらでも extern “C” を付与させて、C++ のマングリングを抑止させます。

#include <iostream>

extern "C" int add(int, int);

int main()
{
    int n = add(1, 2);
    std::cout << n << std::endl;
    return 0;
}

g++ でコンパイルすることで実行ファイルを生成します。
また、関数の呼び出しができていることを確認します。

$ g++ main.cc libadd.a -o main && ./main
3

Cargo でライブラリを生成する

Cargo を利用してライブラリを生成する方法です。

プロジェクトの作成

まずは cargo new でプロジェクトを作成します。
このときオプションに --lib を付与して、ライブラリ用のプロジェクトを生成させます。

$ cargo new add --lib
     Created library `add` package

ソースコードの編集

lib.rs ファイルを編集します。
rustc の例同様に、2つの整数を足し算する add 関数を定義します。

Filename: add/src/lib.rs

#[no_mangle]
pub extern "C" fn add(a: i32, b: i32) -> i32 {
    a + b
}

Cargo.toml の編集

Cargo.toml を開き、lib.crate-type の定義を追加します。
これで、静的リンクライブラリを生成することを Cargo に指示します。

Filename: add/Cargo.toml

[package]
name = "add"
version = "0.1.0"
edition = "2021"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[lib]
crate-type = ["staticlib"]

[dependencies]

ビルド

最後にビルドを実行します。
特にオプションを付与しない場合は、target/debug 配下にライブラリが出力されます。

$ cd add
$ cargo build
   Compiling add v0.1.0 (/home/gari/sandbox/cpp-ffi/add)
    Finished dev [unoptimized + debuginfo] target(s) in 0.18s
$ ls target/debug/libadd.a
target/debug/libadd.a

C++ にリンクさせる

ここまでできたら、あとは rustc のケースと同様です。
libadd.a をコピーして g++ でコンパイルさせると、Rust で定義したメソッドを C++ から呼ぶことができます。

$ g++ main.cc libadd.a -o main && ./main
3
  • URLをコピーしました!
  • URLをコピーしました!

コメント

コメントする

目次