Expand description
hicc
提供调用c++
接口的能力.
三个相关的库:
hicc
核心功能库.hicc-std
为c++
标准库中的容器提供rust api
.hicc-build
方便编译c++
适配代码.
约束: 依赖c++11
或更高版本的特性.
§类型映射通用规则
所有数据类型可以分为两大类: POD
和class
.
c++ 类型 | rust 参数(POD ) | rust 参数(class ) | rust 返回值(POD ) | rus 返回值(class ) | 说明 |
---|---|---|---|---|---|
T | T | T | T | T | |
ClassRef<'_, T> | 生命周期和输入关联 | ||||
ClassRefMut<'_, T> | 生命周期和输入关联 | ||||
ClassPtr<'_, T> | 生命周期和输入关联 | ||||
ClassMutPtr<'_, T> | 生命周期和输入关联 | ||||
T&& | T | T | T | T | |
ClassRef<'_, T> | 生命周期和输入关联 | ||||
ClassRefMut<'_, T> | 生命周期和输入关联 | ||||
ClassPtr<'_, T> | 生命周期和输入关联 | ||||
ClassMutPtr<'_, T> | 生命周期和输入关联 | ||||
std::unique_ptr<T> | unique_ptr<T> | T | unique_ptr<T> | T | |
ClassRef<'_, T> | 生命周期和输入关联 | ||||
ClassRefMut<'_, T> | 生命周期和输入关联 | ||||
ClassPtr<'_, T> | 生命周期和输入关联 | ||||
ClassMutPtr<'_, T> | 生命周期和输入关联 | ||||
std::unique_ptr<T, D> | unique_ptr<T> | unique_ptr<T> | unique_ptr<T> | unique_ptr<T> | D 非缺省模板参数 |
ClassRef<'_, unique_ptr<T>> | 生命周期和输入关联 | ||||
ClassRefMut<'_, unique_ptr<T>> | 生命周期和输入关联 | ||||
ClassPtr<'_, unique_ptr<T>> | 生命周期和输入关联 | ||||
ClassMutPtr<'_, unique_ptr<T>> | 生命周期和输入关联 | ||||
std::shared_ptr<T> | shared_ptr<T> | shared_ptr<T> | shared_ptr<T> | shared_ptr<T> | |
ClassRef<'_, shared_ptr<T>> | 生命周期和输入关联 | ||||
ClassRefMut<'_, shared_ptr<T>> | 生命周期和输入关联 | ||||
ClassPtr<'_, shared_ptr<T>> | 生命周期和输入关联 | ||||
ClassMutPtr<'_, shared_ptr<T>> | 生命周期和输入关联 | ||||
const T& | &T | &T | &T | ClassRef<'_, T> | |
T | |||||
ClassPtr<'_, T> | |||||
T& | &mut T | &mut T | &mut T | ClassRefMut<'_, T> | |
T | |||||
ClassMutPtr<'_, T> | |||||
const T* | *const T | &ClassPtr<'_, T> | *const T | ClassPtr<'_, T> | 多重指针对应ClassPtr<'_, T, N> |
&T | T | 非多重指针 | |||
&T | ClassRef<’_, T> | 非多重指针 | |||
T* | *mut T | &ClassMutPtr<'_, T> | *mut T | ClassMutPtr<'_, T> | 多重指针对应ClassMutPtr<'_, T, N> |
&mut T | T | 非多重指针 | |||
&mut T | ClassRefMut<’_, T> | 非多重指针 | |||
std::function<R(ArgTypes...)> | Function<fn(ArgTypes…)->R> | Function<fn(ArgTypes…)->R> | 其中R/ArgTypes 遵循上述映射规则 | ||
exception | - | - | Exception<T> | Exception<T> | 其中T 遵循上述映射规则 |
va_list | ... | - | - | - |
对于class
类型有几个特点:
- 无论
c++
返回值类型是什么,rust
可按需要选择值、引用或指针类型,作为返回值时他们的内存布局完全相同. - 输入参数类型需要准确匹配,代表不同的生命周期. 值传递等同于所有权转移,其他为资源借用.
T/ClassRef/ClassRefMut/ClassPtr/ClassMutPtr
总是可以通过AbiClass::is_null
判断返回是否为空指针.- 接口定义时可按
POD
定义为T/&T/&mut T/*const T/*mut T
,hicc
完成类型自动转换.参见import_lib/import_class
.
§模板(泛型)参数类型映射规则
hicc
支持映射c++
模板类,要利用AbiType
来屏蔽上述POD
和class
两类模板参数类型上映射规则的差异.
对于模板参数,类型映射规则如下:
c++模板参数类型 | rust 参数 | rust 返回值 |
---|---|---|
T | <T as AbiType>::InputType | <T as AbiType>::OutputType |
const T& | <T as AbiType>::InputRef<'_> | <T as AbiType>::OutputRef<'_> |
T& | <T as AbiType>::InputRefMut<'_> | <T as AbiType>::OutputRefMut<'_> |
const T* | <T as AbiType>::InputPtr<'_> | <T as AbiType>::OutputPtr<'_> |
T* | <T as AbiType>::InputMutPtr<'_> | <T as AbiType>::OutputMutPtr<'_> |
参考hicc-std::vector
的get
接口定义:
impl<T: AbiType + 'static> vector<T> {
pub fn get(&self) -> Option<T::OutputRef<'_>> {
//...
}
}
非class
类型用于rust
泛型,必须结合hicc::Pod<T>
使用.
参考hicc-std::basic_string<T>
的相关定义:
type string = basic_string<hicc::Pod<i8>>;
type u16string = basic_string<hicc::Pod<i16>>;
type u32string = basic_string<hicc::Pod<i32>>;
§二次开发
二次开发分为三个步骤
- 转换为
cabi
:c++
代码 - 映射为
rust api
:rust
代码 hicc-build
编译c++
代码
§hello world
函数和类.
为如下hello
和HelloWorld
实现提供rust api
.
#include <string>
std::string hello(const std::string& name) {
return std::string("hello ") + name;
}
class HelloWorld {
std::string hello;
public:
HelloWorld(const std::string& hello): hello(hello) {}
std::string hi(const std::string& name) { return hello + " " + name; }
};
§转换为cabi
// src/cabi.cpp
#include <hicc/std/memory.hpp>
#include <hicc/std/string.hpp>
EXPORT_CLASS_DECLARE(HelloWorld, HelloWorldMethods);
// 将成员方法映射为`cabi`接口.
struct HelloWorldMethods {
EXPORT_MEMBER_METHOD(&HelloWorld::hi);
};
// 将全局函数和构造函数映射为`cabi`接口.
EXPORT_METHODS_BEG(hello_1_0) {
EXPORT_METHOD(hello);
EXPORT_METHOD(hicc::make_unique<HelloWorld, const std::string&>);
}EXPORT_METHODS_END();
EXPORT_METHOD
宏完成c++
接口到cabi
的映射. 具体参见import_lib/import_class
.
§映射为rust api
// 映射HelloWorld
hicc::import_class! {
class HelloWorld {
fn hello(name: &hicc_std::string) -> hicc_std::string;
}
}
// 映射构造函数
hicc::import_lib! {
#![link_name = "hello_1_0"]
fn hello(name: &hicc_std::string) -> hicc_std::string;
// 推荐将全局构造函数设置为`crate::HelloWorld`的关联函数.
#[member(class = HelloWorld, method = new)]
fn helloworld_new(hello: &hicc_std::string) -> HelloWorld;
}
// 使用
fn main() {
let hello = hello(&hicc_std::string::from(c"world"));
println!("{:?}", hello.as_cstr());
let hello = HelloWorld::new(&hicc_std::string::from(c"Hello"));
let hi = hello.hi(&hicc_std::string::from(c"World"));
println!("{:?}", hi.as_cstr());
}
import_lib/import_class
中的函数声明将cabi
接口导入到rust
. 具体参见import_lib/import_class
.
§编译c++
代码
// build.rs
hicc_build::Build::new().file("src/cabi.cpp").compile("hello_1.0");
println!("cargo::rustc-link-lib=hello_1.0");
println!("cargo::rustc-link-lib=stdc++");
hicc_build
将c++
代码编译为静态库,将生成的库和stdc++
链接到rust
最终生成的二进制件.
§返回引用类型的处理
如果HelloWorld
增加如下接口:
class HelloWorld {
public:
// ...
const std::string& get_hello() const { return hello; }
};
c++
侧适配函数无特殊处理:
EXPORT_METHODS_BEG(hello_1_0) {
//...
EXPORT_MEMBER_METHOD(&HelloWorld::get_hello);
}EXPORT_METHODS_END();
根据类型映射规则,rust api
返回值类型应该是ClassRef<'_, T>
:
hicc::import_class! {
class HelloWorld {
//...
fn get_hello(&self) -> hicc::ClassRef<'_, hicc_std::string>;
}
}
推荐利用import_class
完成类型映射:
hicc::import_class! {
// 声明为`c++` class
class String = hicc_std::string;
class HelloWorld {
//...
// 根据映射规则,`&String`自动转换为`ClassRef<'_, String>`.
fn get_hello(&self) -> &String;
}
}
注: import_lib
有同样的功能.
hicc::import_class! {
// 重定义类型`hicc_std::string`为`String`
class String = hicc_std::string;
//...
}
hicc::import_lib! {
// `String`已经被定义,这里只需要声明即可.
class String;
//...
}
说明: 最终生成的代码中, class
关键字最终都对应到rust
的struct
关键字.
Macros§
- import_
class - 实现
c++ class
到rust struct
的映射. - import_
lib - 提供
rust
调用c++
函数,包括c++
类构造函数的能力.
Structs§
- Class
Array - 对应
c++
类对象只读数组 - Class
MutArray - 对应
c++
类对象可写数组 - Class
MutPtr - 对应
T*/T**/...
- Class
Ptr - 对应
const T*/const T**/...
- Class
Ref - 对应
&T
. - Class
RefMut - 对应
&mut T
. - Exception
- 对应
c++
接口抛出的异常 - Exception
Info - 保存
c++
异常信息 - Function
- 对应
c++
的std::function<R(...)>
类型. - Interface
- 类型标识,用于需要从
rust
的trait创建c++
类对象的场景. - Pod
c++
模板参数, 非c++类
必须包装在pod<T>
中使用.- shared_
ptr - 对应
std::shared_ptr<T>
- unique_
ptr - 对应
std::unique_ptr<T, D>
- weak_
ptr - 对应
std::weak_ptr<T>
.
Traits§
- AbiClass
- 遵循
RAII
原则管理c++
资源的生命周期. - AbiType
- 用于支持
c++
模板类. 对应rust
侧泛型参数必须支持AbiType
. - Function
Type - 辅助
Function
的实现. - Import
Lib - 辅助
import_lib
宏的实现.