タイトルそのままの記事。
結論
link-cplusplusを使え。
動機
C++コードを経由してロボット用ミドルウェアやロボット用じゃないミドルウェアと連携したかったから。
この記事を書く動機
libcを使ってリンクする記事が多かったんだけど、それだと
= note: Undefined symbols for architecture arm64:
"std::__1::locale::use_facet(std::__1::locale::id&) const", referenced from:
std::__1::ctype<char> const& std::__1::use_facet[abi:v15006]<std::__1::ctype<char>>(std::__1::locale const&) in libnerikiri2_value.a(value.o)
以下略
みたいなエラーが出てくるので。
やることの流れ
- c++のコード (.hと.cpp) を用意する
- build.rsでコンパイル方法を記述する
- Cargo.tomlを編集する
- build.rsを設定する。
- link-cplusplusをdependenciesに加える。
- ccをbuild-dependenciesに加える。
- main.rsから使う。
空のプロジェクトを作る
$ cargo new hello_cpp_rs
C++のコードを用意
src/hello_cpp/include/hello_cpp/hello.h
#pragma once
#ifdef __cplusplus
extern "C" {
#endif
void hello();
#ifdef __cplusplus
}
#endif
src/hello_cpp/src/hello.cpp
#include <iostream>
#include <string>
#include "hello_cpp/hello.h"
void hello(){
std::cout << "Hello, C++!" << std::endl;
}
build.rsを用意
extern crate cc;
fn main(){
println!("cargo:rustc-link-search=native=/usr/local/lib");
cc::Build::new()
.cpp(true)
.warnings(true)
.flag("-std=c++17")
.flag("-Wall")
.flag("-Wextra")
.flag("-v")
.flag("-g")
.file("src/hello_cpp/src/hello.cpp")
.include("src/hello_cpp/include")
.compile("libhello_cpp.a");
}
.cppをtrueにしておけば-lc++などはいらない
Cargo.tomlを編集
[package]
name = "hello_cpp_rs"
version = "0.1.0"
edition = "2021"
build = "build.rs"
[dependencies]
link-cplusplus = "1.0"
[build-dependencies]
cc = { version = "1.0", features = ["parallel"] }
src/main.rsから使う
extern crate link_cplusplus;
#[link(name = "hello_cpp", kind = "static")]
extern "C" {
fn hello();
}
fn main() {
unsafe{
hello();
}
}
まとめ
これだけです。cargo runでHello, C++!とでれば成功。
参考