| 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_worldhicc::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 examplehicc::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生成的文档.