代码拉取完成,页面将自动刷新
同步操作将从 OpenHarmony/third_party_rust_bindgen 强制同步,此操作会覆盖自 Fork 仓库以来所做的任何修改,且无法恢复!!!
确定后同步将在后台操作,完成时将刷新页面,请耐心等待。
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实现Rust调用C的示例。
在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_
在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;
}
添加文件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);
}
}
添加构建文件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"
}
调测验证
Minimum support Rust版本是1.60.0。
目前还没有制定MSRV提升政策,所以MSRV可能会在任何版本中增加。
MSRV是可用于编译bindgen
的Minimum Rust版本。bindgen
可以生成与低于当前MSRV的Rust版本兼容的绑定。
在使用该工具的过程中有任何问题欢迎开发者在社区issue中反馈。
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。