hicc

Crates.iohicc
lib.rshicc
version0.2.0
created_at2025-05-06 00:48:43.379769+00
updated_at2025-09-04 02:19:46.487673+00
descriptionSafe, efficient, full-featured FFI between Rust and C++
homepage
repositoryhttps://gitcode.com/xuanwu/hicc
max_upload_size
id1661744
size173,564
hunting (h1467792822)

documentation

README

hicc

支持的功能介绍

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

说明:

  1. 字节对齐要求: 要求所有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函数类型:

  1. rust函数参数可以不包括c++函数的缺省参数
  2. rust函数可以忽略c++函数的返回值.
  3. 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中的关键字classc++的类映射为ruststruct. 无函数体的方法利用#[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]声明这是一个纯抽象类,最终会映射为rusttrait.

利用内置函数@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生成的文档.

Commit count: 0

cargo fmt