third_party_rust_bindgen/README_zh.md
fangting 71a0ae1f77 add oh user guide
Signed-off-by: fangting <fangting12@huawei.com>
2023-05-04 11:58:04 +08:00

5.4 KiB
Raw Permalink Blame History

crates.io docs.rs

引入背景

bindgen 自动生成Rust与C和一些C++库的FFI绑定。

例如给定C头文件doggo.h

typedef struct Doggo {
    int many;
    char wow;
} Doggo;

void eleven_out_of_ten_majestic_af(Doggo* pupper);

bindgen产生Rust FFI代码允许调用doggo库的函数并使用其类型:

/* automatically generated by rust-bindgen 0.99.9 */

#[repr(C)]
pub struct Doggo {
    pub many: ::std::os::raw::c_int,
    pub wow: ::std::os::raw::c_char,
}

extern "C" {
    pub fn eleven_out_of_ten_majestic_af(pupper: *mut Doggo);
}

目录结构

bindgen的目录树结构如下

.
├── appveyor.yml
├── bindgen
│   ├── BUILD.gn
│   ├── build.rs
│   ├── callbacks.rs
│   ├── Cargo.toml
│   ├── codegen
│   ├── deps.rs
│   ├── extra_assertions.rs
│   ├── features.rs
│   ├── ir
│   ├── lib.rs
│   ├── LICENSE -> ../LICENSE
│   ├── log_stubs.rs
│   ├── parse.rs
│   ├── regex_set.rs
│   └── time.rs
├── bindgen-cli
│   ├── BUILD.gn
│   ├── Cargo.toml
│   ├── LICENSE -> ../LICENSE
│   ├── main.rs
│   └── options.rs
├── bindgen-integration
│   ├── build.rs
│   ├── Cargo.toml
│   ├── cpp
│   ├── include
│   └── src
├── bindgen-tests
│   ├── build.rs
│   ├── Cargo.toml
│   ├── src
│   └── tests
├── book
│   ├── book.toml
│   └── src
├── Cargo.lock
├── Cargo.toml
├── CHANGELOG.md
├── ci
│   ├── assert-no-diff.bat
│   ├── no-includes.sh
│   ├── test.bat
│   └── test.sh
├── CONTRIBUTING.md
├── csmith-fuzzing
│   ├── csmith.h
│   ├── driver.py
│   ├── predicate.py
│   └── README.md
├── example-graphviz-ir.png
├── LICENSE
├── OAT.xml
├── README.md
├── README.OpenSource
├── README_zh.md
├── releases
│   ├── friends.sh
│   └── release-announcement-template.md
└── rustfmt.toml

Bindgen工具在OH上的使用指导

操作步骤

下面是一个使用bindgen实现Rust调用C的示例。

  1. 在C代码侧使用头文件lib.h定义两个接口接口FuncAAddB用来实现两数求和接口SayHello用来打印字符串。

    #ifndef BUILD_RUST_TESTS_BINDGEN_TEST_LIB_H_
    #define BUILD_RUST_TESTS_BINDGEN_TEST_LIB_H_
    #include <stdint.h>
    #include "build/rust/tests/test_bindgen_test/test_for_hello_world/lib2.h"
    
    uint32_t FuncAAddB(uint32_t a, uint32_t b);
    void SayHello(const char *message);
    
    #endif  //  BUILD_RUST_TESTS_BINDGEN_TEST_LIB_H_
    
  2. 在lib.c中添加对两个接口的对应实现。

    #include "build/rust/tests/test_bindgen_test/test_for_hello_world/lib.h"
    #include <stdint.h>
    #include <stdio.h>
    
    void SayHello(const char *message)
    {
        printf("This is a test for bindgen hello world:\n");
        printf("%s\n", message);
    }
    
    uint32_t FuncAAddB(uint32_t a, uint32_t b)
    {
        printf("This is a test for bindgen of a + b:\n");
        return a + b;
    }
    
  3. 添加文件main.rs就可以在Rust侧通过c_ffi实现对C侧的接口调用。注意Rust侧调用的不安全接口需要使用unsafe封装。

    //!  bindgen test for hello world
    #![allow(clippy::approx_constant)]
    mod c_ffi {
        #![allow(dead_code)]
        #![allow(non_upper_case_globals)]
        #![allow(non_camel_case_types)]
        include!(env!("BINDGEN_RS_FILE"));
    }
    /// pub fn add_two_numbers_in_c
    pub fn add_two_numbers_in_c(a: u32, b: u32) -> u32 {
        unsafe { c_ffi::FuncAAddB(a, b) }
    }
    
    use std::ffi::c_char;
    use std::ffi::CString;
    
    /// fn main()
    fn main() {
        println!("{} + {} = {}", 3, 7, add_two_numbers_in_c(3, 7));
        let c_str = CString::new("This is a message from C").unwrap();
        let c_world: *const c_char = c_str.as_ptr() as *const c_char;
        unsafe {
            c_ffi::SayHello(c_world);
        }
    }
    
    
  4. 添加构建文件BUILD.gn建立Rust模块对C模块的依赖。

    import("//build/ohos.gni")
    
    ohos_shared_library("c_lib") {
      sources = [ "lib.c" ]
      defines = [ "COMPONENT_IMPLEMENTATION" ]
    }
    
    rust_bindgen("c_lib_bindgen") {
      header = "lib.h"
    }
    
    ohos_rust_executable("bindgen_test") {
      deps = [ ":c_lib" ]
      deps += [ ":c_lib_bindgen" ]
      sources = [ "main.rs" ]
      bindgen_output = get_target_outputs(":c_lib_bindgen")
      inputs = bindgen_output
      rustenv = [ "BINDGEN_RS_FILE=" + rebase_path(bindgen_output[0]) ]
      crate_root = "main.rs"
    }
    

调测验证

bindgen_test

MSRV

Minimum support Rust版本是1.60.0

目前还没有制定MSRV提升政策所以MSRV可能会在任何版本中增加。

MSRV是可用于编译bindgen的Minimum Rust版本。bindgen可以生成与低于当前MSRV的Rust版本兼容的绑定。

API参考

API参考文档在docs.rs上

开发者贡献

在使用该工具的过程中有任何问题欢迎开发者在社区issue中反馈。