亚洲欧美第一页_禁久久精品乱码_粉嫩av一区二区三区免费野_久草精品视频

蟲蟲首頁| 資源下載| 資源專輯| 精品軟件
登錄| 注冊

您現在的位置是:首頁 > 技術閱讀 >  Rust學習資料

Rust學習資料

時間:2024-02-15

最近在研究Rust,目前大多數項目都可以使用Rust開發,但是涉及到和其他語言交互,比如用Rust開發一個SDK,一般還是需要導出C接口。


那如何將Rust導出C接口?

Rust的FFI就是專門做這件事的。一個正常的Rust public接口長這樣:

pub fn hello_world() -> i32 {    20}

如果要把一個Rust函數導出為C接口,需要對它進行改造:

#[no_mangle]pub extern "C" fn hello_world() -> i32 {    20}

它相比于純Rust函數有兩點不同:

一個是extern "C":表示導出C接口

一個是#[no_mangle]:正常一個C++或者Rust函數相關的符號都特別長且難以理解,使用它表示導出的符號是C符號,即沒有任何多余的修飾,函數名是啥樣,相關的符號大概就是啥樣,如圖:

如何導出C的動態庫或者靜態庫?

如果想要編譯出動態庫或者靜態庫,可以在Cargo.toml中配置crate-type:

[lib]crate-type = ["cdylib"] # Creates dynamic lib# crate-type = ["staticlib"] # Creates static lib

cylib表示導出動態庫,staticlib表示導出靜態庫。


如何生成對應的C頭文件?

一個C庫一般都有個頭文件,那Rust怎么生成一個C的頭文件呢?可以使用cbindgen:

cbindgen --config cbindgen.toml --crate hello_world --output hello_world.h

其中cbindgen.toml是一個template文件,我后面鏈接中列了具體地址。


上面的hello_world函數,我使用cbindgen就可以自動生成一個頭文件:

#pragma once
#include <stdarg.h>#include <stdbool.h>#include <stddef.h>#include <stdint.h>#include <stdlib.h>
#ifdef __cplusplusextern "C" {#endif // __cplusplus
int32_t hello_world(void);
#ifdef __cplusplus} // extern "C"#endif // __cplusplus

至于如何使用更復雜的類型和C交互,比如我想導出和傳入一個結構體的指針,比如我想設置const char*,以及怎么管理對應的內存?


可以直接看這段代碼:

use std::boxed::Box;use std::ffi::CStr;use std::ffi::CString;use std::os::raw::c_char;
pub struct Manager { path: CString,}
fn get_default_cstring() -> CString { CString::new("").expect("new string failed")}
#[no_mangle]pub extern "C" fn manager_create() -> *mut Manager { println!("{}", "create_manager().".to_string()); Box::into_raw(Box::new(Manager { path: get_default_cstring(), }))}
#[no_mangle]pub extern "C" fn manager_destroy(ptr: *mut Manager) { if ptr.is_null() { return; }
// safe unsafe { let _b = Box::from_raw(ptr); }}
impl Manager { #[no_mangle] pub extern "C" fn manager_set_path(&mut self, p: *const c_char) { unsafe { self.path = CString::from(CStr::from_ptr(p)); } }
#[no_mangle] pub extern "C" fn manager_get_function(&self) -> *const c_char { self.path.as_ptr() }}
#[no_mangle]pub extern "C" fn hello_world() -> i32 { 20}

也許有人不太理解Rust代碼的含義,那可以直接看它對應的C Header:

#pragma once
#include <stdarg.h>#include <stdbool.h>#include <stddef.h>#include <stdint.h>#include <stdlib.h>
typedef struct Manager Manager;
#ifdef __cplusplusextern "C" {#endif // __cplusplus
int32_t hello_world(void);
struct Manager *manager_create(void);
void manager_destroy(struct Manager *ptr);
const char *manager_get_function(const struct Manager *self);
void manager_set_path(struct Manager *self, const char *p);
#ifdef __cplusplus} // extern "C"#endif // __cplusplus

通過manager_create創建的內存,需要通過manager_destroy銷毀。


但是在對應的Rust代碼沒有用到申請或者銷毀內存相關的代碼,而是使用Box來管理內存,它可以理解為C++中的unique_ptr。


內存都通過對象來管理,避免Rust申請的內存,讓C這邊來釋放,違反代碼的開發準則。


當然,如果你非要在Rust層想malloc和free內存,可以使用libc的crate。


如果想在Rust中調用C或者C++代碼,可以使用cxx crate,也很方便,比如Rust中的String、Vec都在cxx中有對應的類型。


但是我的目的是使用Rust開發一個C的動態庫的SDK,兩種方法都嘗試了下,感覺還是直接使用FFI更方便些。


我這里特意整理了一些Rust FFI相關資料,感興趣的可以看看

  • Rust如何調用C接口、Rust如何導出C接口、C的callback如何傳給Rust:https://doc.rust-lang.org/nomicon/ffi.html

  • The Embedded Rust Book FFI:https://docs.rust-embedded.org/book/interoperability/rust-with-c.html

  • 使用cbindgen可以自動分析,將Rust接口導出為C接口:https://github.com/eqrion/cbindgen

  • cbindgen的default template:https://github.com/eqrion/cbindgen/blob/master/template.toml

  • cbindgen的doc:https://github.com/eqrion/cbindgen/blob/master/docs.md

  • Rust FFI的 example blog,主要是string如何傳出去并銷毀相關內存:https://snacky.blog/en/string-ffi-rust.html

  • cxx專用于Rust和C++之間的橋梁:https://github.com/dtolnay/cxx

  • cxx:https://cxx.rs/

  • Complex data types and Rust FFI blog:http://kmdouglass.github.io/posts/complex-data-types-and-the-rust-ffi/

  • Rust std ffi:https://doc.rust-lang.org/std/ffi/index.html

  • 與C交互時,可以使用libc在Rust層做C的malloc和free

  • 涉及ptr的地方需要了解:https://doc.rust-lang.org/std/ptr/index.html


還有些Rust入門資料

  • https://www.zhihu.com/question/31038569 

  • https://doc.rust-lang.org/rust-by-example/ 

  • https://doc.rust-lang.org/cargo/getting-started/installation.html 

  • https://github.com/rustlang-cn/Rustt 

  • https://github.com/sunface/rust-course 


更多內容在 一個優質的C++學習圈 里,來一起鉆研C++和Rust吧。

主站蜘蛛池模板: 邹城市| 昔阳县| 秭归县| 乾安县| 台中县| 巩留县| 周宁县| 贵德县| 兴仁县| 普格县| 东乡县| 卓资县| 阳西县| 新闻| 资源县| 轮台县| 弋阳县| 株洲市| 龙江县| 兰考县| 陇南市| 迭部县| 灌阳县| 松溪县| 沈阳市| 桃园县| 德保县| 新安县| 麻江县| 天门市| 浮山县| 木里| 东丰县| 阿克苏市| 潍坊市| 普宁市| 且末县| 平武县| 饶河县| 双鸭山市| 麻栗坡县|