• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1[![crates.io](https://img.shields.io/crates/v/bindgen.svg)](https://crates.io/crates/bindgen)
2[![docs.rs](https://docs.rs/bindgen/badge.svg)](https://docs.rs/bindgen/)
3
4## 引入背景
5
6`bindgen` 自动生成Rust与C(和一些C++)库的FFI绑定。
7
8例如,给定C头文件`doggo.h`:
9
10```c
11typedef struct Doggo {
12    int many;
13    char wow;
14} Doggo;
15
16void eleven_out_of_ten_majestic_af(Doggo* pupper);
17```
18
19`bindgen`产生Rust FFI代码,允许调用`doggo`库的函数并使用其类型:
20
21```rust
22/* automatically generated by rust-bindgen 0.99.9 */
23
24#[repr(C)]
25pub struct Doggo {
26    pub many: ::std::os::raw::c_int,
27    pub wow: ::std::os::raw::c_char,
28}
29
30extern "C" {
31    pub fn eleven_out_of_ten_majestic_af(pupper: *mut Doggo);
32}
33```
34
35## 目录结构
36bindgen的目录树结构如下:
37```
38.
39├── appveyor.yml
40├── bindgen
41│   ├── BUILD.gn
42│   ├── build.rs
43│   ├── callbacks.rs
44│   ├── Cargo.toml
45│   ├── codegen
46│   ├── deps.rs
47│   ├── extra_assertions.rs
48│   ├── features.rs
49│   ├── ir
50│   ├── lib.rs
51│   ├── LICENSE -> ../LICENSE
52│   ├── log_stubs.rs
53│   ├── parse.rs
54│   ├── regex_set.rs
55│   └── time.rs
56├── bindgen-cli
57│   ├── BUILD.gn
58│   ├── Cargo.toml
59│   ├── LICENSE -> ../LICENSE
60│   ├── main.rs
61│   └── options.rs
62├── bindgen-integration
63│   ├── build.rs
64│   ├── Cargo.toml
65│   ├── cpp
66│   ├── include
67│   └── src
68├── bindgen-tests
69│   ├── build.rs
70│   ├── Cargo.toml
71│   ├── src
72│   └── tests
73├── book
74│   ├── book.toml
75│   └── src
76├── Cargo.lock
77├── Cargo.toml
78├── CHANGELOG.md
79├── ci
80│   ├── assert-no-diff.bat
81│   ├── no-includes.sh
82│   ├── test.bat
83│   └── test.sh
84├── CONTRIBUTING.md
85├── csmith-fuzzing
86│   ├── csmith.h
87│   ├── driver.py
88│   ├── predicate.py
89│   └── README.md
90├── example-graphviz-ir.png
91├── LICENSE
92├── OAT.xml
93├── README.md
94├── README.OpenSource
95├── README_zh.md
96├── releases
97│   ├── friends.sh
98│   └── release-announcement-template.md
99└── rustfmt.toml
100```
101
102## Bindgen工具在OH上的使用指导
103
104### 操作步骤
105下面是一个使用bindgen实现Rust调用C的示例。
106
1071. 在C代码侧,使用头文件lib.h定义两个接口,接口FuncAAddB用来实现两数求和,接口SayHello用来打印字符串。
108
109   ```c
110   #ifndef BUILD_RUST_TESTS_BINDGEN_TEST_LIB_H_
111   #define BUILD_RUST_TESTS_BINDGEN_TEST_LIB_H_
112   #include <stdint.h>
113   #include "build/rust/tests/test_bindgen_test/test_for_hello_world/lib2.h"
114
115   uint32_t FuncAAddB(uint32_t a, uint32_t b);
116   void SayHello(const char *message);
117
118   #endif  //  BUILD_RUST_TESTS_BINDGEN_TEST_LIB_H_
119   ```
120
121
1222. 在lib.c中添加对两个接口的对应实现。
123
124   ```c
125   #include "build/rust/tests/test_bindgen_test/test_for_hello_world/lib.h"
126   #include <stdint.h>
127   #include <stdio.h>
128
129   void SayHello(const char *message)
130   {
131       printf("This is a test for bindgen hello world:\n");
132       printf("%s\n", message);
133   }
134
135   uint32_t FuncAAddB(uint32_t a, uint32_t b)
136   {
137       printf("This is a test for bindgen of a + b:\n");
138       return a + b;
139   }
140   ```
141
1423. 添加文件main.rs,就可以在Rust侧通过c_ffi实现对C侧的接口调用。注意Rust侧调用的不安全接口需要使用unsafe封装。
143
144   ```rust
145   //!  bindgen test for hello world
146   #![allow(clippy::approx_constant)]
147   mod c_ffi {
148       #![allow(dead_code)]
149       #![allow(non_upper_case_globals)]
150       #![allow(non_camel_case_types)]
151       include!(env!("BINDGEN_RS_FILE"));
152   }
153   /// pub fn add_two_numbers_in_c
154   pub fn add_two_numbers_in_c(a: u32, b: u32) -> u32 {
155       unsafe { c_ffi::FuncAAddB(a, b) }
156   }
157
158   use std::ffi::c_char;
159   use std::ffi::CString;
160
161   /// fn main()
162   fn main() {
163       println!("{} + {} = {}", 3, 7, add_two_numbers_in_c(3, 7));
164       let c_str = CString::new("This is a message from C").unwrap();
165       let c_world: *const c_char = c_str.as_ptr() as *const c_char;
166       unsafe {
167           c_ffi::SayHello(c_world);
168       }
169   }
170
171   ```
172
1734. 添加构建文件BUILD.gn,建立Rust模块对C模块的依赖。
174
175   ```GN
176   import("//build/ohos.gni")
177
178   ohos_shared_library("c_lib") {
179     sources = [ "lib.c" ]
180     defines = [ "COMPONENT_IMPLEMENTATION" ]
181   }
182
183   rust_bindgen("c_lib_bindgen") {
184     header = "lib.h"
185   }
186
187   ohos_rust_executable("bindgen_test") {
188     deps = [ ":c_lib" ]
189     deps += [ ":c_lib_bindgen" ]
190     sources = [ "main.rs" ]
191     bindgen_output = get_target_outputs(":c_lib_bindgen")
192     inputs = bindgen_output
193     rustenv = [ "BINDGEN_RS_FILE=" + rebase_path(bindgen_output[0]) ]
194     crate_root = "main.rs"
195   }
196   ```
197
198**调测验证**
199
200![bindgen_test](./bindgen_test.png)
201
202## MSRV
203
204Minimum support Rust版本是**1.60.0**。
205
206目前还没有制定MSRV提升政策,所以MSRV可能会在任何版本中增加。
207
208MSRV是可用于编译`bindgen`的Minimum Rust版本。`bindgen`可以生成与低于当前MSRV的Rust版本兼容的绑定。
209
210## API参考
211
212[API参考文档在docs.rs上](https://docs.rs/bindgen)
213
214## 开发者贡献
215
216在使用该工具的过程中有任何问题欢迎开发者在社区issue中反馈。
217
218<br>
219
220
221