繫結程式庫程式碼的教學課程

繫結程式庫可自動產生程式碼,協助驅動程式庫人參考 與驅動程式庫程式碼繫結程式庫目前建構會為 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_namefuchsia.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_namefuchsia.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 索引鍵為 barbaz 定義了兩個值,則 兩個 ID:FOO_BARFOO_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 中自動產生繫結程式庫構件 開發環境的詳細說明,請參閱 為驅動程式建立新的繫結程式庫