この記事でわかること
RustからC++を呼び出した後に、さらにC++からRustに何か通知したい場合があると思います。
本記事では、そのケースで、C++からRustのAPIを呼ぶ方法を説明します。
(下図のCallbackのところ)
RustからC++を呼び出す方法
こちらの方法は下記記事を参考にしてください。
-
【Rust】RustからC++ を呼び出す方法
2023/3/6 C++, programming, rust, プログラミング
この記事でわかること Rustに移行したいけど、全部を移行することはできない場合、一部のC++コードを呼び出したいと考える方も多いでしょう。 特に、外部のライブラリを使用する場合は、Rustのライブラ ...
C++からRustを呼び出す方法
上記記事の続きから説明します。
1. Rust側の実装
C++の呼び出しに関しては、こちらを参考にしてください。
Rust側の実装はこちらです。
// cxx_example/src/main.rs
#[cxx::bridge]
mod ffi {
extern "Rust" {
fn callback();
}
unsafe extern "C++" {
include!("cxx_example/src/hello.h");
fn hello();
}
}
fn callback() {
println!("Callback");
}
fn main() {
ffi::hello();
}
extern "Rust" {}
で括った関数をRustでは呼び出すことができます。
これを、呼び出したC++のhello()
の中で呼び出します。
2. C++側の実装
cxx_example/src/hello.h
とcxx_example/src/hello.cpp
を次のように記述します。
// cxx_example/src/hello.h
#pragma once
#include "rust/cxx.h"
void hello();
// cxx_example/src/hello.cpp
#include "hello.h"
#include "cxx_example/src/main.rs.h"
void hello() { callback(); }
#include "cxx_example/src/main.rs.h"
をインクルードすることで、Rustで定義した
callback()
を呼び出すことができます。
main.rs.h
自体は実装していませんが、コンパイルする過程で生成されるので、それをインクルードしています。
3. ビルド設定
Cargo.toml
とbuild.rs
を次のように記述します。
[package]
name = "cxx_example"
version = "0.1.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
cxx = "1.0"
[build-dependencies]
cxx-build = "1.0"
fn main() {
cxx_build::bridge("src/main.rs")
.file("src/hello.cpp")
.flag_if_supported("-std=c++20")
.compile("cxx-example");
println!("cargo:rerun-if-changed=/src/*");
println!("cargo:rerun-if-changed=/build.rs");
}
4. 実行
cargo run
// output: Callback
実行して「Callback」と出たら成功です。
終わりに
今回は、Rust→C++→Rustと呼び出す方法を説明しました。
全コードはこちらを参照してください。