本文版权归作者所有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
转载自夜明的孤行灯
本文链接地址: https://www.huangyunkun.com/2023/05/07/rust-call-cplusplus/
Rust基于FFI可以调用其他语言,这个支持对于C是很完备的,对于C++有一些限制。常用的工具有cxx和autocxx,前者可控简单,后者强大易用。我一般喜欢使用autocxx,可以少写一些代码。
我们这里用Rust调用V8为例子。
打印固定字符串
首先引入autocxx
[dependencies]
autocxx = "0.25.0"
cxx = "1.0"
[build-dependencies]
autocxx-build = "0.25.0"
我们先尝试查询一下V8的版本号。
新建input文件,定义一个方法version,先返回一个固定字符串。
inline std::string version() {
return "0.0.1";
}
main.rs方法添加代码
use autocxx::prelude::*;
include_cpp! {
#include "../include/input.h"
safety!(unsafe_ffi)
generate!("version")
}
fn main() {
let rv8 = ffi::version();
println!("Hello, world! - from RV8, version= {:?}", rv8);
}
最后是build.rs文件,当前没有外部依赖,直接编译
fn main() -> miette::Result<()> {
let path = std::path::PathBuf::from("src");
let mut b = autocxx_build::Builder::new("src/main.rs", [&path]).build()?;
b.flag_if_supported("-std=c++14").compile("rv8");
println!("cargo:rerun-if-changed=src/main.rs");
println!("cargo:rerun-if-changed=include/input.h");
Ok(())
}
运行效果如下

引入V8
我这里使用V8 10版本,下载头文件和预构建包,

然后修改input.h。
#include "v8-headers/v8.h"
using namespace v8;
inline std::string version()
{
return v8::V8::GetVersion();
}
然后build文件中添加相关信息
fn main() -> miette::Result<()> {
let path = std::path::PathBuf::from("src");
let header_path = std::path::PathBuf::from("include/v8-headers");
let header_platform_path = std::path::PathBuf::from("include/v8-headers/libplatform");
let link_path = std::path::PathBuf::from("v8/linux_x86-64/obj");
let b =
autocxx_build::Builder::new("src/main.rs", [&path, &header_path, &header_platform_path])
.extra_clang_args(&["-std=c++17", "-Wc++17-extensions", "-Wunused-parameter"])
.build()?;
b.compile("rv8");
println!("cargo:rustc-link-lib=v8_monolith");
println!("cargo:rustc-link-search={}", link_path.display());
println!("cargo:rerun-if-changed=src/main.rs");
println!("cargo:rerun-if-changed=include/input.h");
Ok(())
}
主要改动有几点
- 路径中添加V8头文件路径
- 开启C++ 17支持
- link到预构建包
运行效果

其他使用方法类似,继续在input.h中添加就行了,比如需要执行脚本
inline std::string execute(std::string input)
{
Isolate *isolate = Isolate::GetCurrent();
HandleScope handle_scope(isolate);
Local<Context> context = Context::New(isolate);
Context::Scope context_scope(context);
Local<v8::String> source = v8::String::NewFromUtf8(isolate, input.c_str()).ToLocalChecked();
Local<Script> script = Script::Compile(context, source).ToLocalChecked();
Local<Value> result = script->Run(context).ToLocalChecked();
v8::String::Utf8Value utf8(isolate, result);
return std::string(*utf8);
}
要最大发挥autocxx的功能,还可以直接将所有C++方法和类型都生成rust代码,然后手动封装一层。
参考
https://github.com/google/autocxx
本文版权归作者所有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
转载自夜明的孤行灯
本文链接地址: https://www.huangyunkun.com/2023/05/07/rust-call-cplusplus/