Crates.io | hicc |
lib.rs | hicc |
version | 0.2.0 |
created_at | 2025-05-06 00:48:43.379769+00 |
updated_at | 2025-09-04 02:19:46.487673+00 |
description | Safe, efficient, full-featured FFI between Rust and C++ |
homepage | |
repository | https://gitcode.com/xuanwu/hicc |
max_upload_size | |
id | 1661744 |
size | 173,564 |
v0.20
版本支持自动生成c++
适配代码,开发人员只需要提供rs
文件, 进一步方便使用.
约束: 依赖c++11
及更高版本的特性.
数据类型 | 是否支持 | 备注 |
---|---|---|
T |
support | |
const T& |
support | |
T& |
support | |
T&& |
support | rust 侧同T |
const T* |
support | 程序员管理资源生命周期 |
T* |
support | 程序员管理资源生命周期 |
const T** 多重指针 |
support | 程序员管理资源生命周期 |
T** 多重指针 |
support | 程序员管理资源生命周期 |
std::function<R(ArgTypes...)> |
support |
说明:
c++
对象都至少按照size_t
字节数进行对齐, 未对齐地址被视为非法指针.函数分类 | 是否支持 |
---|---|
funtion(external linkage/internal linkage/no linkage) |
support |
function overloading | support |
default parameters | support |
template function | support |
class member function | support |
noexcept(false) |
support |
template class | support |
dynamic_cast |
support |
realizing virtual function with rust | support |
va_list |
support |
variadic(... ) |
partial support(仅全局函数,参数和返回值无类类型) |
hello_world
hicc::cpp
可嵌入c++
代码, hicc::import_lib
定义需要调用的c++
api.
hicc::cpp! {
#include <iostream>
static void hello_world() {
std::cout << "hello world!" << std::endl;
}
}
hicc::import_lib! {
#![link_name = "example"]
#[cpp(func = "void hello_world()")]
fn hello_world();
}
fn main() {
hello_world();
}
最终还需要利用build.rs
编译此文件:
hicc_build::Build::new().rust_file("src/main.rs").compile("example");
println!("cargo::rustc-link-lib=example");
println!("cargo::rustc-link-lib=stdc++");
println!("cargo::return-if-changed=src/main.rs");
如下场景,对于非变长参数的c++
函数,允许映射不同的rust
函数类型:
rust
函数参数可以不包括c++
函数的缺省参数rust
函数可以忽略c++
函数的返回值.rust
函数可以将返回值包装在hicc::Exception
中捕获c++
异常.hicc::cpp! {
#include <iostream>
static int foo(int v1, int v2 = 0) {
std::cout << "foo(v1 = " << v1 << ", v2 = " << v2 << ")" << std::endl;
throw 3;
return v1 + v2;
}
}
hicc::import_lib! {
#![link_name = "example"]
#[cpp(func = "int foo(int, int)")]
fn foo(v: i32) -> hicc::Exception<()>;
}
fn main() {
println!("{:?}", foo(1).ok());
}
stl example
hicc::import_class
中的关键字class
将c++
的类映射为rust
的struct
. 无函数体的方法利用#[cpp(method = ...)]
映射为对应的c++
类的成员函数.
use std::ffi::CStr;
hicc::cpp! {
#include <string>
static std::string hello_world() {
return "hello_world";
}
}
hicc::import_class! {
#[cpp(class = "std::string")]
class string {
#[cpp(method = "const char* c_str() const")]
fn c_str(&self) -> *const i8;
fn as_cstr(&self) -> &CStr {
unsafe { CStr::from_ptr(self.c_str()) }
}
}
}
hicc::import_lib! {
#![link_name = "example"]
class string;
#[cpp(func = "std::string hello_world()")]
fn hello_world() -> string;
}
fn main() {
let hello = hello_world();
println!("{:?}", hello.as_cstr());
}
hicc-std
使用样例.注: hicc-std
提供了对stl
容器的完整支持.
业务依赖std::map<int, std::string>
, 需要提供实例化类的构建函数即可.
use hicc::AbiClass;
hicc::cpp! {
// c++侧需要引用hicc提供的头文件.
#include <hicc/std/map.hpp>
#include <hicc/std/string.hpp>
// 按需定义容器类型. 可以包含非缺省的Allocator等模版参数类型.
typedef std::map<int, std::string> CppMap;
}
hicc::import_lib! {
#![link_name = "example"]
// 对应`c++`的`CppMap`
class RustMap = hicc_std::map<hicc::Pod<i32>, hicc_std::string>;
// 创建容器接口.
#[cpp(func = "std::unique_ptr<CppMap> hicc::make_unique<CppMap>()")]
fn rustmap_new() -> RustMap;
}
fn main() {
let mut map = rustmap_new();
let name = hicc_std::string::from(c"hello");
map.insert(&0, &name);
assert_eq!(map.get(&1), None);
assert_eq!(map.get(&0), Some(name.as_ref()));
}
c++
抽象类同样利用hicc::import_class
实现c++
抽象类的映射(当前不支持多继承).
#[interface]
声明这是一个纯抽象类,最终会映射为rust
的trait
.
利用内置函数@make_proxy
和宏#[interface(name = ...)]
, 基于组合模式,提供Rust
继承c++
抽象类的相似效果.
对于需要利用@make_proxy
创建的类,必须在定义时提供c++
构造函数的定义,下面例子中的:
#[cpp(class = "Baz", ctor = "Baz()")]
class Baz: Bar {
#[cpp(method = "void baz() const")]
fn baz(&self);
}
hicc::cpp! {
#include <hicc/std/memory.hpp>
#include <iostream>
struct Foo {
virtual ~Foo() {};
virtual void foo() const = 0;
};
struct Bar: public Foo {
virtual void bar() const = 0;
};
struct Baz: public Bar {
virtual void foo() const override {
std::cout << "C++ Baz::foo" << std::endl;
}
virtual void bar() const override {
std::cout << "C++ Baz::bar" << std::endl;
}
void baz() const {
std::cout << "C++ Baz::baz" << std::endl;
}
~Baz() {
std::cout << "C++ Baz::~Baz" << std::endl;
}
};
}
hicc::import_class! {
#[interface]
class Foo {
#[cpp(method = "void foo() const")]
fn foo(&self);
}
#[interface]
class Bar: Foo {
#[cpp(method = "void bar() const")]
fn bar(&self);
}
#[cpp(class = "Baz", ctor = "Baz()")]
class Baz: Bar {
#[cpp(method = "void baz() const")]
fn baz(&self);
}
}
hicc::import_lib! {
#![link_name = "example"]
class Baz;
#[cpp(func = "Baz @make_proxy<Baz>()")]
#[interface(name = "Bar")]
fn new_rust_baz(intf: hicc::Interface<Baz>) -> Baz;
#[cpp(func = "std::unique_ptr<Baz> std::make_unique<Baz>()")]
fn new_cpp_baz() -> Baz;
}
struct RustBaz;
impl Bar for RustBaz {
fn bar(&self) {
println!("Rust Baz::bar");
}
}
impl Foo for RustBaz {
fn foo(&self) {
println!("Rust Baz::foo");
}
}
impl Drop for RustBaz {
fn drop(&mut self) {
println!("Rust Baz::~Baz");
}
}
fn main() {
let cpp_baz = new_cpp_baz();
cpp_baz.foo();
cpp_baz.bar();
cpp_baz.baz();
let rust_baz = new_rust_baz(RustBaz);
rust_baz.foo();
rust_baz.bar();
rust_baz.baz();
}
详细内容参见cargo doc
生成的文档.