繫結程式庫可自動產生程式碼,協助驅動程式庫人參考 與驅動程式庫程式碼繫結程式庫目前建構會為 C++ 和 Rust 產生程式碼。 本教學課程將詳細說明如何使用這些自動產生的程式碼目標。
本指南假設您已熟悉下列概念:
繫結程式庫範例
首先,我們先定義一個範例繫結程式庫,其中包含一些不同的定義。我們也會使用 依附另一個現有的繫結程式庫這是選填欄位,但為了方便起見,我們會提供這項資訊。
BUILD.gn
bind_library("my_bindlib_target") { # target_name
source = "mybindlib.bind"
name = "fuchsia.example.library" # library_name (optional, defaults to
# target_name)
public_deps = [ "//src/devices/bind/fuchsia.pci" ]
}
在多數情況下,建構目標名稱和程式庫名稱相同 (
不需要提供 name
屬性,只要將程式庫名稱設為建構目標名稱即可)。
但這裡我們會分別定義這些函式,以便日後區分各個用途。
mybindlib.bind
library fuchsia.example.library;
using fuchsia.pci;
string Name;
string DeviceCategory {
KB = "keyboard",
Mouse = "mouse",
};
uint I2C_ADDRESS;
enum I2C_PROTOCOL {
Device,
Impl,
};
bool Flag {
ENABLE = true,
DISABLE = false,
};
extend uint fuchsia.BIND_PCI_VID {
GIZMOTRONICS = 0x314159,
};
自動產生的程式庫
產生的建構目標
C++
建構會根據繫結程式庫的 target_name
自動提供新的目標,
:{target_name}_cpp
在上述範例中,這是 my_bindlib_target
。所以目標就是
:my_bindlib_target_cpp
。
Rust
建構會根據繫結程式庫的 target_name
自動提供新的目標,
:{target_name}_rust
在上述範例中,這是 my_bindlib_target
。所以目標就是
:my_bindlib_target_rust
。
使用產生的程式庫
C++
這是 source_set
目標,其中包含的標頭檔案,以及從
繫結程式庫。驅動程式作者可在建立節點屬性時使用這個屬性。他們只是需要
從執行檔或其他以 C++ 為基礎的目標中建立依附元件。
include 路徑和命名空間將以繫結程式庫的 library_name
為基礎 (
程式庫名稱中 .
的某些替換項目),
#include <bind/{library_name with slashes}/cpp/bind.h>
和
namespace bind_{library_name with underscores}
。
在上述的範例中,library_name
為 fuchsia.example.library
。所以我們應該
《#include <bind/fuchsia/example/library/cpp/bind.h>
》和《namespace bind_fuchsia_example_library
》。
Rust
這是 rustc_library
目標,這是具有常數的根模組的 Rust Crate
從繫結程式庫產生的 ID驅動程式作者可在建立節點時使用
資源。他們只需要從 Rust 目標中建立依附元件即可。
用於陳述式的 Crate 名稱取決於 library_name
繫結程式庫 (加上程式庫名稱的 .
部分替換)
use bind_{library_name with underscores};
。
在上述的範例中,library_name
為 fuchsia.example.library
,因此我們會
use bind_fuchsia_example_library;
。
系統產生的標頭檔案
C++
// WARNING: This file is machine generated by bindc.
#ifndef BIND_FUCHSIA_EXAMPLE_LIBRARY_BINDLIB_
#define BIND_FUCHSIA_EXAMPLE_LIBRARY_BINDLIB_
#include <string>
#include <bind/fuchsia/pci/cpp/bind.h>
namespace bind_fuchsia_example_library {
static const std::string NAME = "fuchsia.example.library.Name";
static const std::string DEVICECATEGORY = "fuchsia.example.library.DeviceCategory";
static const std::string DEVICECATEGORY_KB = "keyboard";
static const std::string DEVICECATEGORY_MOUSE = "mouse";
static const std::string I2C_ADDRESS = "fuchsia.example.library.I2C_ADDRESS";
static const std::string I2C_PROTOCOL = "fuchsia.example.library.I2C_PROTOCOL";
static const std::string I2C_PROTOCOL_DEVICE = "fuchsia.example.library.I2C_PROTOCOL.Device";
static const std::string I2C_PROTOCOL_IMPL = "fuchsia.example.library.I2C_PROTOCOL.Impl";
static const std::string FLAG = "fuchsia.example.library.Flag";
static constexpr bool FLAG_ENABLE = true;
static constexpr bool FLAG_DISABLE = false;
static constexpr uint32_t BIND_PCI_VID_GIZMOTRONICS = 3227993;
} // namespace bind_fuchsia_example_library
#endif // BIND_FUCHSIA_EXAMPLE_LIBRARY_BINDLIB_
Rust
// WARNING: This file is machine generated by bindc.
pub use bind_fuchsia_pci;
pub const NAME: &str = "fuchsia.example.library.Name";
pub const DEVICECATEGORY: &str = "fuchsia.example.library.DeviceCategory";
pub const DEVICECATEGORY_KB: &str = "keyboard";
pub const DEVICECATEGORY_MOUSE: &str = "mouse";
pub const I2C_ADDRESS: &str = "fuchsia.example.library.I2C_ADDRESS";
pub const I2C_PROTOCOL: &str = "fuchsia.example.library.I2C_PROTOCOL";
pub const I2C_PROTOCOL_DEVICE: &str = "fuchsia.example.library.I2C_PROTOCOL.Device";
pub const I2C_PROTOCOL_IMPL: &str = "fuchsia.example.library.I2C_PROTOCOL.Impl";
pub const FLAG: &str = "fuchsia.example.library.Flag";
pub const FLAG_ENABLE: bool = true;
pub const FLAG_DISABLE: bool = false;
pub const BIND_PCI_VID_GIZMOTRONICS: u32 = 3227993;
產生的常數
鍵
繫結程式庫中的每個鍵都有同名的字串常數 ID。
但以大寫字母表示字串值將是該鍵的完整名稱。
完整名稱包含繫結程式庫的 library_name
和金鑰名稱,沒有
大小寫調整項,以 .
分隔。
C++
如果在名為 fuchsia.example.library
的程式庫中已有名為 keyName
的索引鍵,這會是
產生的常數:std::string KEYNAME = "fuchsia.example.library.keyName";
。
Rust
如果在名為 fuchsia.example.library
的程式庫中已有名為 keyName
的索引鍵,這會是
產生的常數:pub const KEYNAME: &str = "fuchsia.example.library.keyName";
。
值
針對繫結程式庫中,為某個鍵定義的每個值,系統就會根據類型 的金鑰 (請見下表)。常數的 ID 就是 索引鍵和值名稱,以底線分隔
舉例來說,如果 foo
索引鍵為 bar
和 baz
定義了兩個值,則
兩個 ID:FOO_BAR
和 FOO_BAZ
。
C++
金鑰類型 | C++ 常數類型 | C++ 常數值 |
---|---|---|
Uint | uint32_t | 項目中的整數值 |
string | std::字串 | 項目的字串值 |
布林值 | 布林值 | 項目中的布林值 |
列舉 | std::字串 | 列舉的全名 (詳情請見下方) |
Rust
金鑰類型 | Rust 常數類型 | Rust 常數值 |
---|---|---|
Uint | u32 | 項目中的整數值 |
string | str | 項目的字串值 |
布林值 | 布林值 | 項目中的布林值 |
列舉 | str | 列舉的全名 (詳情請見下方) |
列舉的完整名稱包含 library_name
、鍵名稱和值名稱。
並以 .
分隔
C++
如果在程式庫的列舉鍵 enumeratedKey
下有名為 someValue
的值
稱為 fuchsia.example.library
,那麼產生的常數會是
std::string ENUMERATEDKEY_SOMEVALUE = "fuchsia.example.library.enumeratedKey.someValue";
。
Rust
如果在程式庫的列舉鍵 enumeratedKey
下有名為 someValue
的值
稱為 fuchsia.example.library
,那麼產生的常數會是
pub const ENUMERATEDKEY_SOMEVALUE: &str = "fuchsia.example.library.enumeratedKey.someValue";
。
依附元件
C++
我們的繫結程式庫範例依附於 //src/devices/bind/fuchsia.pci
,因此另一個繫結
程式庫,產生的程式碼也已自動加入從中產生的標頭。
因此,加入這個標頭後,程式碼也可以參照基本繫結程式庫中的值。
Rust
我們的繫結程式庫依附於 //src/devices/bind/fuchsia.pci
,因此另一個繫結
所產生的程式碼,也會自動從該程式庫匯入已產生的 Crate。
與 C++ 標頭的不同之處在於,在 Rust 中,使用者必須為 Crate 名稱建立巢狀結構
所參照的依附元件請參閱下方範例,瞭解運作方式。
使用範例
BUILD.gn
C++
source_set("parent_cpp_code") {
sources = [ "parent-driver.cc" ]
deps = [ ":my_bindlib_target_cpp" ]
}
Rust
rustc_binary("parent_rust_code") {
edition = "2021"
source_root = "parent-driver.rs"
sources = [ "parent-driver.rs" ]
deps = [ ":my_bindlib_target_rust" ]
}
複合節點規格建立者
C++
#include <bind/fuchsia/example/library/cpp/bind.h>
std::string a = bind_fuchsia_example_library::NAME;
uint32_t b = bind_fuchsia_example_library::BIND_PCI_VID_GIZMOTRONICS;
uint32_t c = bind_fuchsia_pci::BIND_PROTOCOL_DEVICE;
Rust
use bind_fuchsia_example_library::bind_fuchsia_pci;
fn main() {
let _a: &str = bind_fuchsia_example_library::NAME;
let _b: u32 = bind_fuchsia_example_library::BIND_PCI_VID_GIZMOTRONICS;
let _c: u32 = bind_fuchsia_pci::BIND_PROTOCOL_DEVICE;
}
SDK 中自動產生的程式庫
瞭解如何在 Fuchsia SDK 中自動產生繫結程式庫構件 開發環境的詳細說明,請參閱 為驅動程式建立新的繫結程式庫。