6-2. CからRustを呼ぶ

ここでは、CのソースコードからRustのソースコードを呼び出す方法を説明します。やることは2つです。

  1. Cが扱えるAPIをRust側に作成する
  2. 外部ビルドシステムにRustプロジェクトを組み込む

上記の1.については、cbindgenで自動生成できます。2.は、Cのプロジェクトやビルドシステムに強く依存するため、一般的な方法はありません。ケーススタディ Zephyr bindingsでは、cmakeプロジェクトに組み込む一例を示します。

ライブラリプロジェクトの作成

通常のRustプロジェクトではなく、システムライブラリを出力します。

[lib] crate-type = ["cdylib"] # 動的ライブラリ # crate-type = ["staticlib"] # 静的ライブラリ

C APIの作成

C ABIで呼び出しできるRustのAPIを作成します。おおよそ、次のような関数になります。

#![allow(unused)] fn main() { #[no_mangle] pub extern "C" fn rust_function() { // ... } }

no_mangle

Rustコンパイラは、シンボル名をマングルします。そのため、Cから呼び出すRustの関数は、マングルしないように#[no_mangle]アトリビュートを付けます。

extern "C"

デフォルトでは、Rustの関数はRustのABIを使用します。そこで、CのABIを仕様するように、コンパイラに指示します。プラットフォーム固有のABI指定については、External Blocks ABIにドキュメントがあります。

Cヘッダファイル作成

Rustで作ったAPIをCから呼べるように、Cヘッダファイルを作成します。

#![allow(unused)] fn main() { #[no_mangle] pub extern "C" fn rust_function() { ... } }

上のRust APIはCヘッダファイルでは、次のようになります。

void rust_function();

Cヘッダファイルの自動生成

cbindgenにより、RustソースコードからCヘッダファイルを自動生成することができます。cbindgenをベアメタル環境で使うにあたり注意することは、いくつかの標準ライブラリヘッダをインクルードしたヘッダファイルが生成されることです。

#include <stdarg.h> #include <stdbool.h> #include <stdint.h> #include <stdlib.h> void rust_function(void);

ターゲットシステムによってはstdlib.hが与えられていない可能性があるので、注意して下さい。

外部ビルドシステムにRustプロジェクトを組み込む

Rust APIを作成し、ヘッダファイルを生成すれば、後はCファイルでヘッダをインクルードするだけです。

#include "rust_lib.h" void call_rust() { rust_fuction(); }

ビルドシステムへの組み込みについては、Cプロジェクトのビルドシステムが何か、に強く依存します。Makefileでビルドしている場合、ビルドステップの途中でMakefileからcargoを呼び出し、静的ライブラリとしてRustコードをビルドし、リンクします。

出典