CppCon 2014 學習:Cross platform GUID association with types

類型的 GUID(全局唯一標識符) 是在 COM 編程(Component Object Model) 和某些大型 C++ 架構(如 Office、DirectX、跨 DLL 接口)中關聯類型信息實現運行時類型識別與動態接口查詢的重要機制。
下面我們分層解釋——

類型的 GUID 是什么?

GUID(Globally Unique Identifier):128 位的唯一標識,用來唯一標識某種類型(接口/類)
比如:

__declspec(uuid("4D675322-F6F5-4E85-94EF-2927DFAA1409"))
struct IWorkerCallback : IUnknown { ... };

這個 GUID 表示:IWorkerCallback 類型的唯一身份標識是這個字符串值

GUID 的用途:為什么類型需要它?

1. COM 接口查詢(核心用途)

COM 是基于接口的架構,組件之間只能通過接口通信。你不能像 C++ 的 dynamic_cast 那樣直接轉換接口指針,所以需要:

HRESULT QueryInterface(const IID& iid, void** out);

你必須提供要“轉換到的接口”的 IID(也就是接口的 GUID),比如:

pUnknown->QueryInterface(__uuidof(IMyInterface), (void**)&pMyInterface);

這背后的意思是:我想知道你是否實現了 IMyInterface,請給我這個接口指針,如果有的話。

2. 替代 RTTI:無需開啟 -frtti

  • 有些大型項目(如 Office)**禁用了 RTTI(運行時類型信息)**以節省空間。
  • 通過 GUID,我們就能在運行時識別類型、接口并動態轉換,而不用啟用 C++ 的原生 typeiddynamic_cast

3. 跨 DLL 類型識別

在 Windows DLL 邊界上,類型信息是不能直接共享的,但 GUID 可以。于是:

  • DLL A 定義了 IFoo
  • DLL B 想和它通信,只要知道 IFoo 的 GUID 就行了,無需包含 IFoo 的完整實現。

4. 插件機制和反射支持

如果你要構建:

  • 跨平臺插件框架
  • 腳本調用(如 Lua → C++)
  • 元數據反射(識別支持的功能)
    你也可以使用類型 GUID 來:
  • 注冊所有類型
  • 用 GUID 映射構造函數、工廠函數、接口表
  • 甚至用于序列化/反序列化(type-safe)

不是 C++ 標準的機制

GUID 和 __uuidof() 不是 C++ 標準提供的功能,而是:

  • Microsoft Visual C++ 提供的擴展(__declspec(uuid)
  • Clang/GCC 等可以通過宏和模板模擬(如你前面看到的 STRUCT_GUID

舉個實際例子

IUnknown* p = ...;
IFoo* foo = nullptr;
if (SUCCEEDED(p->QueryInterface(__uuidof(IFoo), (void**)&foo))) {foo->DoSomething();
}

沒有 GUID,你就無法調用 QueryInterface();類型系統沒法知道“你到底想要哪個接口”。

總結一句話:

類型的 GUID 是類型在運行時的身份證,它是 COM 等架構中實現接口查詢(QueryInterface)、替代 RTTI、支持插件與 DLL 通信的核心機制。

總結一下為什么需要類型的 GUID:

  • GUID(全局唯一標識符)用于標識接口類型,特別是在 COM(組件對象模型)編程中,比如 Microsoft Office 里的代碼。
  • 通過 IUnknown::QueryInterface 方法,可以根據 GUID 實現接口的動態查詢和類型轉換(類似于動態類型轉換,但不依賴于 C++ 的 RTTI)。
  • Office 里不使用 C++ 標準的 RTTI,而是用 GUID 來保證跨模塊、跨語言的一致性和安全性。
  • Visual C++ 提供了對 GUID 的內置支持,通過 __declspec(uuid("...")) 來聲明 GUID,通過 __uuidof(Type) 獲取類型對應的 GUID。
  • C++ 標準并沒有內建對 GUID 的支持,所以這是 Microsoft 平臺特有的擴展。

這段代碼展示了一個跨平臺(特別是支持 MSVC 和 Clang 編譯器)對 GUID 與接口類型關聯的典型寫法,核心點如下:

  • __declspec(uuid("...")) 是 MSVC 特有的語法,用于給接口(如 IWorkerCallback)附加 GUID。
  • 在 MSVC 下,__uuidof(type) 可以直接獲取這個 GUID。
  • Clang 編譯器不支持 __declspec(uuid) 的模板特化,所以采用模板特化結構體 guid_of<type> 來手動綁定 GUID。
  • 通過宏 #define __uuidof(type) guid_of<type>::value,無論在哪個編譯器環境,都能統一用 __uuidof(type) 方式獲取 GUID。
  • 這樣寫能實現跨編譯器一致訪問 GUID,同時保證代碼跨平臺兼容。

總結一下這個理想方案的問題點:

  • [uuid(“…”)] 標注雖然寫起來直觀簡潔,
  • 但它是 微軟專有擴展,不屬于標準 C++,只能在 Visual C++ 使用
  • 其實現會在對象實例中增加額外指針,導致對象體積變大
  • 這對性能敏感或跨平臺項目是不友好的。
    所以,雖然它“看上去理想”,但實際用時要慎重,最好還是用兼容性更好、對實例大小無影響的傳統 __declspec(uuid(...)) + 模板特化方案。

總結一下這個用宏簡化 GUID 綁定的關鍵點:

  • 宏寫成 STRUCT_GUID(IWorkerCallback, "4D675322-F6F5-4E85-94EF-2927DFAA1409") 形式,
    宏只負責綁定 GUID,不包含 structclass 關鍵字,
    這樣更利于 IDE 和工具解析代碼(語法高亮、跳轉等)。
  • structclass 關鍵字放在宏外寫,方便代碼風格統一和工具支持。
  • 注意宏綁定的 GUID 必須和類型的聲明匹配,比如不能宏里用 class,類型定義里用 struct,否則會產生 Visual C++ 的 Level 1 警告。
  • 保證這點對 Visual C++ 的 ABI 穩定性很重要,避免潛在兼容性問題。

How can we implement the STRUCT_GUID macro?

這段代碼意思是:

#define STRUCT_GUID(type, guidString) \struct __declspec(uuid(guidString)) type;
  • 這個宏利用 Visual C++ 的 __declspec(uuid(...)) 特性直接把 GUID 綁定到 struct 上。
  • 宏只負責給類型添加 GUID 屬性,不管是定義、前置聲明還是重新聲明,都可以使用這個宏。
  • 實現非常簡單明了,使用方便。
    比如:
STRUCT_GUID(IWorkerCallback, "4D675322-F6F5-4E85-94EF-2927DFAA1409")
struct IWorkerCallback : IUnknown {virtual void Invoke(IWorkerObject* pObj) = 0;
};

這樣,IWorkerCallback 類型就綁定了對應的 GUID,VC++ 編譯器會自動生成相關信息。

這段描述是 Clang 下跨平臺實現 GUID 關聯的思路,主要點如下:

核心思想

  • 不像 VC++ 直接用 __declspec(uuid(...)),Clang 沒有類似的內建支持,需要用模板和函數來“模擬” GUID 關聯。
  • 定義一個模板結構體 guid_of<T>,它有一個 static constexpr GUID value,存儲對應類型的 GUID。
  • __uuidof(type) 宏映射到 guid_of<type>::value,這樣用起來語義一致。

關鍵實現細節

// 默認模板,調用 get_guid 函數
template<typename T>
struct guid_of {static constexpr GUID value = get_guid(static_cast<T*>(nullptr));
};
// 默認 get_guid 函數實現,static_assert 防止未特化情況導致使用錯誤
template<typename T>
constexpr GUID get_guid(T*) {static_assert(sizeof(T) == 0, "GUID not defined for this type!");
}
// 用宏定義類型的 GUID,宏展開成 get_guid 函數的特化版本
#define STRUCT_GUID(type, guidString)             \struct type;                                 \extern "C++" constexpr GUID get_guid(type*) noexcept { \return str_to_guid(guidString);          \}
  • STRUCT_GUID(type, guidString) 會先聲明一個 struct type,再定義一個針對該類型指針的 get_guid 函數特化,返回對應的 GUID。
  • 通過 str_to_guid 將字符串形式的 GUID 轉換為 GUID 結構。
  • 當你調用 __uuidof(type) 時,實際是訪問 guid_of<type>::value,編譯器會調用對應的 get_guid(type*),返回正確的 GUID。
  • 如果沒有使用 STRUCT_GUID 定義的類型,調用 __uuidof 會觸發 static_assert,提示沒有定義 GUID。

優點

  • 支持 Clang 以及非 VC++ 編譯器。
  • 類型安全,調用時若未定義 GUID 會報錯。
  • 不改變結構體大小或內存布局。

你提供的這段代碼是對 Clang 下如何在 C++ 中實現編譯期 GUID(全局唯一標識符)解析 的繼續部分。下面是對這段實現的完整講解:

/// 表示一個不帶花括號的 GUID 字符串,格式為 "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX"
typedef char GuidString[37];
/// 把十六進制的 ASCII 字符轉換為無符號整數值(0–15)
/// H2U['0'] = 0, H2U['9'] = 9, H2U['A'] = 10, H2U['F'] = 15, H2U['a'] = 10, H2U['f'] = 15
const unsigned char H2U[256] = {0, 0, 0, 0, 0, 0, 0, 0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,0, 0, 0, 0, 0, 0, 0, 0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,0, 0, 0, 0, 0, 0, 0, 10, 11, 12, 13, 14, 15, 0,  0,  0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,0, 0, 0, 0, 0, 0, 0, 0,  0,  0,  10, 11, 12, 13, 14, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,0, 0, 0, 0, 0, 0, 0, 0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,0, 0, 0, 0, 0, 0, 0, 0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,0, 0, 0, 0, 0, 0, 0, 0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,0, 0, 0, 0, 0, 0, 0, 0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,0, 0, 0, 0, 0, 0, 0, 0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 0, 0, 0, 0, 0, 0, 0,
};
/// 將格式為 "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX" 的字符串在編譯期轉換為 GUID 結構
constexpr GUID str_to_guid(const GuidString& g) noexcept {return {// 第1段(8位十六進制)→ unsigned longstatic_cast<unsigned long>((H2U[g[0]] << 28) | (H2U[g[1]] << 24) | (H2U[g[2]] << 20) |(H2U[g[3]] << 16) | (H2U[g[4]] << 12) | (H2U[g[5]] << 8) |(H2U[g[6]] << 4)  | H2U[g[7]]),// 第2段(4位十六進制)→ unsigned shortstatic_cast<unsigned short>((H2U[g[9]] << 12) | (H2U[g[10]] << 8) |(H2U[g[11]] << 4) | H2U[g[12]]),// 第3段(4位十六進制)→ unsigned shortstatic_cast<unsigned short>((H2U[g[14]] << 12) | (H2U[g[15]] << 8) |(H2U[g[16]] << 4) | H2U[g[17]]),// 第4和第5段(4位 + 12位十六進制)→ 8字節 unsigned char[8]{static_cast<unsigned char>((H2U[g[19]] << 4) | H2U[g[20]]),static_cast<unsigned char>((H2U[g[21]] << 4) | H2U[g[22]]),static_cast<unsigned char>((H2U[g[24]] << 4) | H2U[g[25]]),static_cast<unsigned char>((H2U[g[26]] << 4) | H2U[g[27]]),static_cast<unsigned char>((H2U[g[28]] << 4) | H2U[g[29]]),static_cast<unsigned char>((H2U[g[30]] << 4) | H2U[g[31]]),static_cast<unsigned char>((H2U[g[32]] << 4) | H2U[g[33]]),static_cast<unsigned char>((H2U[g[34]] << 4) | H2U[g[35]])}};
}

目的

Clang 不支持 __declspec(uuid(...)),所以我們自己構建一種方式,在 編譯期將字符串形式的 GUID 解析為結構體形式(即 GUID{...}),以便類型綁定使用。

關鍵元素解釋

1. GuidString 類型定義

typedef char GuidString[37];
  • 用于表示標準 GUID 格式的字符串 "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX"(共 36 個字符 + 終止符)。
  • 格式示例:"4D675322-F6F5-4E85-94EF-2927DFAA1409"

2. H2U 十六進制字符轉換表

const unsigned char H2U[256] = { ... };
  • '0''9''A''F''a''f' 轉換為 015
  • 例如:H2U['A'] == 10H2U['f'] == 15
  • 其它值都默認為 0,避免非 hex 字符崩潰。

3. str_to_guid:將字符串轉為 GUID

constexpr GUID str_to_guid(const GuidString& g) noexcept
工作流程(按 GUID 各字段分段解釋):
// DWORD Data1 = 8 hex digits: g[0] - g[7]
(H2U[g[0]] << 28) | (H2U[g[1]] << 24) | ... | H2U[g[7]]
// WORD Data2 = 4 hex digits: g[9] - g[12]
(H2U[g[9]] << 12) | ... | H2U[g[12]]
// WORD Data3 = 4 hex digits: g[14] - g[17]
(H2U[g[14]] << 12) | ... | H2U[g[17]]
// BYTE Data4[8] = 16 hex digits: g[19]–g[36]
(g[19], g[20]), (g[21], g[22]), ... (g[34], g[35])
  • 每一對十六進制字符被解析為一個字節。
  • 中間的 - 符號被跳過(g[8], g[13], g[18], g[23] 是 -)。
  • 因此,整段是一個無分支、常量求值的 GUID 解析器!

總結理解

  • 這段代碼的目的是為了讓你能用字符串定義 GUID,但 在編譯期就能將字符串轉化為真實的 GUID 對象
  • 配合前面提到的 STRUCT_GUIDget_guid() 機制,就可以對任意類型 T 實現 __uuidof(T) 的能力,跨平臺兼容。
  • 這種實現方式 既不依賴 RTTI,也不增加對象大小,且可靜態驗證和優化

這段內容是 Clang 下使用 __uuidof()GUID編譯期模擬實現方案的延續,解釋了 str_to_guid() 機制的工作方式、潛在限制和一些高級用法。下面是逐條解釋:

理解要點

str_to_guid()constexpr

constexpr GUID str_to_guid(const GuidString& g) noexcept;
  • 這是一個編譯期函數,所以只要傳入的是字符串常量,就能在編譯時生成 GUID 實例
  • 可用于 constexpr GUID value = str_to_guid("..."),不會有運行時代價。

get_guid() 依賴于 ADL(Argument-Dependent Lookup)

template<typename T>
constexpr GUID get_guid(T*);
  • 它通過 實參依賴查找 來解析 get_guid()
  • 所以這個函數必須定義在和類型 T 同一個命名空間下。
  • 否則 get_guid(T*) 找不到合適的定義,觸發 static_assert() 編譯錯誤(這個是特意設計的安全機制)。

若類型未定義 GUID,會報錯

template<typename T>
constexpr GUID get_guid(T*) {static_assert(false, "Type has no GUID.");
}
  • 這是故意設計的“fail early”機制。
  • 目的是讓開發者在使用 __uuidof(T)必須先注冊 GUID,否則就失敗。

限制和已知問題

僅適用于 C++11

  • 這套方案依賴 C++11 的 constexpr 和模板機制。
  • 不兼容更早的標準(如 C++03)。

NDK 鏈接器問題(在 Android 開發中)

NDK linker error when __uuidof() is used as a template parameter

具體問題:

template<typename C, const IID* piid = &__uuidof(C)> class QIPtr;
  • 在某些平臺(如 Android NDK),__uuidof() 的地址值不能用于模板非類型參數
  • 原因:鏈接器無法靜態推導 &__uuidof(C) 的地址。

替代方案:使用 resolve_guid_ptr<C, piid>::guid

解決方法:

template<typename C, const IID* piid = nullptr>
class QIPtr {static constexpr const GUID* guid = resolve_guid_ptr<C, piid>::guid;
};
  • 提供一個 resolve_guid_ptr 模板:
    • 如果顯式提供 piid,就用它。
    • 如果為 nullptr,就自動使用 __uuidof(C)
      這個模式使用了 偏特化/特化技巧 來繞開鏈接器問題。

總結

這套 Clang 下的 GUID 實現機制的關鍵點是:

特性說明
str_to_guid()編譯期解析 GUID 字符串為結構體。
get_guid() + ADL自動查找對應類型的 GUID。如果沒有定義,則編譯失敗。
Clang 支持跨平臺 __uuidof通過 #define __uuidof(type) guid_of<type>::value 實現替代。
NDK 問題的解決使用 resolve_guid_ptr 延遲和間接獲取 GUID 地址,繞過鏈接器限制。

對整套跨平臺 GUID 關聯機制的總結性說明,下面是它的要點解析和中文理解:

總結理解

STRUCT_GUID 的作用

STRUCT_GUID 允許在多個平臺(如 VC++ 和 Clang)上將字符串形式的 GUID 與類型關聯。

  • 在 Visual C++ 下,使用 __declspec(uuid("..."))
  • 在 Clang 下,通過 get_guid()str_to_guid() 編譯期計算 GUID。
  • 它本質上是一個跨平臺的類型→GUID映射工具

保持與舊代碼兼容

可以繼續使用 __uuidof()

  • __uuidof(T) 在 Visual C++ 是內建的。
  • 在 Clang 中通過 #define __uuidof(type) guid_of<type>::value 來兼容。
  • 所以老代碼無需修改,新的平臺仍然能運行。

這個技巧還能用于其他自定義類型屬性

不局限于 GUID,你還可以用類似方式為類型添加其他屬性,如:

  • 類型標簽(tag)
  • 分類信息(traits)
  • 序列化 ID 等等

如何實現一個通用機制

  1. 定義一個宏(比如 STRUCT_GUID)來注入屬性信息。
  2. 宏會展開成一個 constexpr 函數,返回這個屬性值。
  3. 提供一個訪問接口類或模板(如 guid_of<T>::value)。
  4. 提供一個默認模板函數(當類型未定義該屬性時觸發 static_assert,或返回默認值)。

中文總結一句話:

使用 STRUCT_GUID 技術,我們可以為類型編譯期地綁定 GUID 或其他自定義屬性,支持多平臺編譯器(如 VC++、Clang),且對舊代碼兼容良好。這個機制也能擴展到任意類型屬性的靜態綁定,是一種強大且通用的元編程手法。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/907980.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/907980.shtml
英文地址,請注明出處:http://en.pswp.cn/news/907980.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Android 11以上App主動連接WIFI的完整方案

早期Android版本App內連接指定的WIFI還是比較簡單的&#xff0c;但是隨著Android版本的提升&#xff0c;限制也越來越多。以下是一套完整的Android 11以上的WIFI應用內主動連接方案。 第一步&#xff1a;添加到建議連接&#xff1a; val wifiManager getSystemService(WIFI_…

讓AI彈琴作曲不再是夢:Python+深度學習玩轉自動化音樂創作

讓AI彈琴作曲不再是夢:Python+深度學習玩轉自動化音樂創作 一、AI也能譜出動人的旋律?真不是科幻! 還記得小時候學鋼琴時老師的那句經典:“感覺不到情緒的樂句,是沒靈魂的。” 當時我一邊練琴一邊想:要是有個機器能幫我寫譜、調性又不跑調就好了! 結果幾年后,真被我碰…

機器學習:集成學習概念、分類、隨機森林

本文目錄&#xff1a; 一、集成學習概念**核心思想&#xff1a;** 二、集成學習分類&#xff08;一&#xff09;Bagging集成&#xff08;二&#xff09;Boosting集成(三&#xff09;兩種集成方法對比 三、隨機森林 一、集成學習概念 集成學習是一種通過結合多個基學習器&#…

YOLO機械臂丨使用unity搭建仿真環境,YOLO算法識別,Moveit2控制

文章目錄 前言搭建開發環境在window中安裝Unity創建Docker容器&#xff0c;并安裝相關軟件運行測試改進添加刪除節點前的函數調用 報錯?框選節點的時候報錯?如果無法控制機械臂&#xff0c;查看rviz2的終端&#xff0c;應該會有?規劃路徑超出范圍 參考 前言 本項目介紹通過…

Docker 插件生態:從網絡插件到存儲插件的擴展能力解析

Docker 容器技術以其輕量、快速、可移植的特性,迅速成為構建和部署現代應用的核心工具。然而,盡管 Docker Engine 自身功能強大,但在面對多樣化的生產環境和復雜業務需求時,僅靠核心功能往往無法滿足所有場景。 例如,跨主機的容器網絡通信、異構存儲系統的持久化數據管理…

飛牛fnNAS使用群輝DSM系統

目錄 一、Virtual DSM簡介 二、在飛牛NAS中安裝 1、激活Docker 2、建立路徑 3、創建Compose項目 4、容器啟動 (1)構建容器 (2)容器啟動 5、查看日志 6、登錄DSM地址 7、安裝完成 8、安裝套件示例 9、遠程訪問 10、測試 (1)PC瀏覽器創建筆記 (2)手機創建…

關于FPGA軟核的仿真(一)

MicroBlaze是Xilinx專為FPGA設計的軟核處理器&#xff0c;其本質是通過FPGA的可編程邏輯資源&#xff08;如查找表LUT、觸發器Flip-Flop&#xff09;動態構建的處理器架構&#xff0c;其本質為搭建處理器電路。MicroBlaze上運行嵌入式C代碼程序&#xff0c;通過CoreConnect總線…

戶外攝像頭監控如何兼顧安全實時監控

一、技術手段提升隱私安全性 硬件與功能設計 采用支持隱私保護技術的設備&#xff0c;例如帶電子開關的攝像頭&#xff08;可遠程控制攝像頭啟閉&#xff09;3&#xff0c;或搭載本地AI算法的設備&#xff0c;僅識別人形、車輛等目標&#xff0c;減少無關信息采集。 使用安全…

【C#朗讀文本DLL動態按鈕控件組及按鈕事件文本框拖放數據】2022-1-21

緣由https://bbs.csdn.net/topics/604357098 DotNetSpeech.dll下載_DotNetSpeech.dll免費版下載 - 系統之家 dotnetspeech.dll 64下載-dotnetspeech.dll下載 v10.2 官方版-IT貓撲網 下載了一個DotNetSpeech.dll&#xff0c;放到 \bin\Debug里&#xff0c;添加引用&#xff0c;…

<5>, Qt系統相關

目錄 一、Qt 事件 1&#xff0c;事件的定義 2&#xff0c;事件的處理 3&#xff0c;鼠標事件 4&#xff0c;按鍵事件 5&#xff0c;定時器 6&#xff0c;事件分發器 7&#xff0c;事件過濾器 二、Qt 文件 1&#xff0c;輸入輸出類 2&#xff0c;文件讀寫類 3&#x…

WordPress主題代碼優化深度指南

引言&#xff1a;為何主題優化至關重要 WordPress作為全球最流行的內容管理系統&#xff0c;其性能表現直接關系到用戶體驗和網站成功。主題代碼優化不僅能夠&#xff1a; 提升頁面加載速度&#xff08;Google研究表明&#xff0c;頁面加載時間每增加1秒&#xff0c;跳出率增加…

數據結構第6章 圖(竟成)

第 6 章 圖 【考綱內容】 1.圖的基本概念 2.圖的存儲及基本操作&#xff1a;(1) 鄰接矩陣法&#xff1b;(2) 鄰接表法&#xff1b;(3) 鄰接多重表、十字鏈表 3.圖的遍歷&#xff1a;(1) 深度優先搜索&#xff1b;(2) 廣度優先搜索 4.圖的基本應用&#xff1a;(1) 最小 (代價) 生…

【ROS2實體機械臂驅動】rokae xCoreSDK Python測試使用

【ROS2實體機械臂驅動】rokae xCoreSDK Python測試使用 文章目錄 前言正文配置環境下載源碼配置環境變量測試運行修改點說明實際運行情況 參考 前言 本文用來記錄 xCoreSDK-Python的調用使用1。 正文 配置環境 配置開發環境&#xff0c;這里使用conda做python環境管理&…

黑馬Java面試筆記之MySQL篇(優化)

一. 慢查詢 在MySQL中&#xff0c;如何定位慢查詢&#xff1f; 出現慢查詢的情況有以下幾種&#xff1a; 聚合查詢多表查詢表數據量過大查詢深度分頁查詢 表象&#xff1a;頁面加載過慢&#xff0c;接口壓測響應時間過長&#xff08;超過1s&#xff09; 1.2 如何定位慢查詢&…

歷史數據分析——廣州港

個股簡介 公司簡介: 華南地區最大的綜合性主樞紐港。 本公司是由廣州港集團、國投交通、廣州發展作為發起人,共同出資以發起方式設立的股份有限公司。 經營分析: 一般經營項目:企業管理服務(涉及許可經營項目的除外);港務船舶調度服務;船舶通信服務;企業自有資金…

圖解gpt之Transformer架構與設計原理

Transformer架構。它不僅僅是一個模型&#xff0c;更是一種范式&#xff0c;徹底改變了我們理解和處理自然語言的方式。 2017年&#xff0c;谷歌大腦團隊發表了一篇劃時代的論文&#xff0c;題目就叫《Attention is All You Need》。這標題本身就充滿了力量&#xff0c;宣告了…

HCIP:MPLS靜態LSP的配置及抓包

目錄 一、MPLS的簡單的一些知識點 1.MPLS的概述&#xff1a; 2.MPLS工作原理&#xff1a; 3.MPLS的核心組件&#xff1a; 4. MPLS標簽 5.MPLS標簽的處理 6.MPLS轉發的概述&#xff1a; 7.MPLS的靜態LSP建立方式 二、MPLS的靜態LSP的實驗配置 1.配置接口的地址和配置OS…

Azure DevOps 管道部署系列之一本地服務器

Azure DevOps 是一個幫助改進 SDLC(軟件開發生命周期)的平臺。 在本文中,我們將使用 Azure Pipelines 創建自動化部署。 Azure DevOps 團隊將 Azure Pipelines 定義為“使用 CI/CD 構建、測試和部署,適用于任何語言、平臺和云平臺”。 在這里,我將解釋如何在 Azure Dev…

深入剖析網絡協議:七層協議與四層協議詳解

在計算機網絡的世界中&#xff0c;數據的傳輸與交互離不開協議的規范。其中&#xff0c;七層協議和四層協議是網絡通信架構的核心概念&#xff0c;它們如同網絡世界的 “交通規則”&#xff0c;保障著數據準確、高效地在不同設備間流轉。本文將深入解讀七層協議與四層協議&…

回頭看,FPGA+RK3576方案的功耗性能優勢

作者&#xff1a;Hello,Panda 各位朋友&#xff0c;大家好&#xff0c;熊貓君這次開個倒車&#xff0c;在這個廣泛使用Xilinx&#xff08;Altera&#xff09;高端SoC的時代&#xff0c;分享一個“FPGAARM”實現的低功耗高性能傳統方案。 圖1 瑞芯微RK3576電路 當前&#xff0c…