吴忠躺衫网络科技有限公司

0
  • 聊天消息
  • 系統(tǒng)消息
  • 評論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

一個用C++ 開發(fā)的可用于管理插件的開源架構(gòu) Pluma

工程師鄧生 ? 來源:OSCHINA 社區(qū) ? 作者:悠然紅茶 ? 2022-09-16 11:18 ? 次閱讀

1. 概述

Pluma 是一個用 C++ 開發(fā)的可用于管理插件的開源架構(gòu)。該架構(gòu)是個輕量級架構(gòu),非常易于理解。

Pluma 架構(gòu)有以下基本概念:

1)插件的外在行為體現(xiàn)為一個純虛類,可以叫作插件接口;

2)繼承于同一個插件接口的若干派生類,被認(rèn)為屬于同一種插件,可以叫作插件類;

3)每一個插件接口或插件類都有個一一對應(yīng)的 Provider 類,其中,插件接口對應(yīng)的 Provider 類里會定義一個特殊字符串常量:PLUMA_PROVIDER_TYPE,表示這一類 “插件 Provider” 共同的類型名稱,而這個類型名稱其實就是插件接口的類名字符串。

4)多個插件類可以被放入一個插件動態(tài)庫中,而這個動態(tài)庫文件名(不包括后綴部分)可以叫作 “插件名”。

5)插件機(jī)制使用者可以在自己的架構(gòu)中包含一個 Pluma 管理類,該類支持從所指定的位置加載一個或多個插件動態(tài)庫,并將每個插件類對應(yīng)的 Provider,記錄進(jìn)內(nèi)部的表中。

6)插件機(jī)制使用者可以在合適時機(jī),利用 Pluma 獲取內(nèi)含的插件 Provider,并調(diào)用某個插件 Provider 的 create () 函數(shù),創(chuàng)建出對應(yīng)的插件對象。

7)使用完插件對象后,不要忘了 delete 它。

現(xiàn)在我們畫一張示意圖:


d2a127d2-3432-11ed-ba43-dac502259ad0.png

2. Pluma 管理類

我們剛剛也說了,插件機(jī)制使用者可以包含一個 Pluma 管理類。

該類繼承于 PluginManager 類。

【pluma-1.1/include/pluma/PluginManager.hpp】


poYBAGMj66-AKxy3AAGt4DC0U_8150.jpg 從上面的 load () 函數(shù)和 loadFromFolder () 函數(shù)可以看出,插件管理器既允許用戶單獨加載某個插件動態(tài)庫,也允許批量性加載某個目錄下所有的插件動態(tài)庫。另外,值得注意的是,getProviders () 函數(shù)是 protected 的成員,也就是說,這套架構(gòu)是不希望用戶直接使用這個 PluginManager 類的,即便用了,你也拿不到 Provider。正確的做法是,使用 PluginManager 的子類:Pluma 管理類。 ?? 另外,上面的成員變量 libraries,就是記錄所有已加載的插件動態(tài)庫的映射表。而成員變量 host 則負(fù)責(zé)記錄每個插件類對應(yīng)的 Provider 信息。之所以被稱為 host(宿主),是針對插件而言的。也就是說插件本身實際上是沒資格知道其真實宿主的全貌的,它只能訪問和它相關(guān)的很小一部分?jǐn)?shù)據(jù)而已,因此 Pluma 將這一小部分?jǐn)?shù)據(jù)整理成一個 host 代理,供插件使用。?? ? Pluma 管理類的代碼截選如下: 【pluma-1.1/include/pluma/Pluma.hpp】

pYYBAGMj69KAN3DEAABukF5mWyc123.jpg

請大家注意上面代碼中最后一行,這個 Pluma.hpp 還真是有點手黑,偷偷摸摸 #include 了個 Pluma.inl 文件,其實展開來就是 acceptProviderType () 和 getProviders () 這兩個模板函數(shù)的實現(xiàn)。Pluma.inl 文件的內(nèi)容如下: 【pluma-1.1/include/pluma/Pluma.inl】

poYBAGMj6--AMVfqAAEv_7Rt3N4028.jpg

看到了吧,重新定義了個 getProviders (),還搞成一個模板函數(shù),在函數(shù)體內(nèi)會反過來通過模板參數(shù),進(jìn)一步得到所涉及的插件 Provider 的 PLUMA_PROVIDER_TYPE 信息,這個技巧挺重要。也就是說,外界傳來的是 vector,而函數(shù)內(nèi)部可以推斷出 ProviderType::PLUMA_PROVIDER_TYPE。將 PLUMA_PROVIDER_TYPE 傳入父類的 PluginManager::getProviders () 函數(shù),就可以拿到符合所指類型的所有 Provider。 我們畫一張 Pluma 簡圖,后面再細(xì)說相關(guān)細(xì)節(jié): d2bc2a14-3432-11ed-ba43-dac502259ad0.png 同一類插件類,會對應(yīng)一個 ProviderInfo 節(jié)點,該節(jié)點內(nèi)部的 providers 列表,記錄著同屬一類的若干 Provider。

2.1 Host 代理 【pluma-1.1/include/pluma/Host.hpp】

pYYBAGMj7B2AScFnAAFEhApOE-c560.jpgpYYBAGMj7CSAASNtAABxdymdDgU500.jpg

正如前文所說,Host 代理是針對插件而言的。而 Host 只有一個 public 成員函數(shù) add (),說明其主要對外行為就是讓插件將對應(yīng)的 provider 注冊進(jìn) Host。

3. 插件類和其對應(yīng)的 Provider 類

在說了一大堆插件管理類代碼后,現(xiàn)在終于要開始說插件部分了。前文已經(jīng)說過,插件的外在行為體現(xiàn)為一個純虛類,可以叫作插件接口。我們現(xiàn)在就以 Pluma 源碼中給出的例子為準(zhǔn),來說明一些細(xì)節(jié)。

3.1 Warrior 接口和 WarriorProvider 類

Pluma 中的插件接口例子是 Warrior,其源碼截選如下: 【pluma-1.1/example/src/interface/Warrior.hpp】


pYYBAGMj7D-AJVCHAABCyGY1gt4715.jpg 這個接口里只象征性的寫了一個成員函數(shù) getDescription (),大家明白意思即可。 ?? ? 需要注意的是類定義之后的那句 PLUMA_PROVIDER_HEADER,這個宏負(fù)責(zé)定義和插件接口對應(yīng)的 Provider 類。相關(guān)的宏定義如下: 【pluma-1.1/include/pluma/Pluma.hpp】

pYYBAGMj7FWAEQF4AAEHMJvauLA297.jpg

基于這些宏定義,我們可以將 PLUMA_PROVIDER_HEADER (Warrior) 展開為:

poYBAGMj7HOAK2VDAAC7dO0qpzE457.jpg

代碼很清晰,為 Warrior 接口聲明一個配套的 WarriorProvider 類。這個類里包含著重要的 PLUMA_PROVIDER_TYPE 常量,以及最關(guān)鍵的 create () 函數(shù)。 Warrior 的實現(xiàn)文件更加簡單: 【pluma-1.1/example/src/interface/Warrior.cpp】

poYBAGMj7IiATyndAAAdbDAFUyo300.jpg

也在使用宏,展開宏后可見:

poYBAGMj7JuAfQEfAABlUGbcW7E941.jpg

因為 Warrior 本身是個純虛類,所以 WarriorProvider 里也不用實現(xiàn) create () 函數(shù)。

3.2 Warrior 派生類和派生 Provider

在 pluma 源碼的例子中,提供了三個 Warrior 派生類,SimpleWarrior、Eagle 和 Jaguar。默認(rèn)的是 SimpleWarrior,它被集成進(jìn) example/src/host 目錄。也就是說,即便我們一個額外的插件庫都不提供,示例至少還可以使用 SimpleWarrior。而 Eagle 和 Jaguar 則位于 example/src/plugin 目錄,可以打包進(jìn)一個插件動態(tài)庫。 【pluma-1.1/example/src/host/SimpleWarrior.hpp】

poYBAGMj7LSARMTfAABc8jwniCk595.jpg

前文我們已經(jīng)看到,對于插件接口(Warrior)來說,用到的宏是PLUMA_PROVIDER_HEADER(Warrior),現(xiàn)在針對實際插件類(SimpleWarrior),會用到另一個宏P(guān)LUMA_INHERIT_PROVIDER(SimpleWarrior, Warrior)。這個宏的定義如下: 【pluma-1.1/include/pluma/Pluma.hpp】

pYYBAGMj7MyAbcGLAABcjVqQTZo262.jpg

展開后可見:

poYBAGMj7N-Aa6YVAAA8D8bxK8o324.jpg

很簡單,就是在完成 Provider 的核心使命,提供一個創(chuàng)建插件類對象的 create () 函數(shù)。與 SimpleWarriorProvider 類似,另外兩個 Warrior 派生類 Eagle 和 Jaguar 大體也是這么寫的。示意圖如下: d2e2adc4-3432-11ed-ba43-dac502259ad0.png 在研究 Pluma 所給示例時,我已事先將 Pluma 封裝成靜態(tài)庫了,現(xiàn)在要把 Eagle 和 Jaguar 編譯并封裝成一個動態(tài)庫,就需要鏈接 Pluma 靜態(tài)庫,除此之外,還需要編譯其他一些輔助文件,列舉如下: 1)Connector.cpp 2)dllmain.cpp 3)Eagle.hpp 4)Jaguar.hpp 5)Warrior.cpp 其中 Connector.cpp 文件,是插件動態(tài)庫向外界 Host 注冊自己所有 Provider 的地方。它必須實現(xiàn)一個 connect () 函數(shù),代碼截選如下:

poYBAGMj7P6AI6h3AABiredLvDQ088.jpg

我們先不要著急分析上面的 connect () 動作,可以先跟著我看看插件的加載流程,后文我們就會知道,connect () 只是加載流程的一環(huán)而已。

4. 插件加載流程

我們看一下 Pluma 架構(gòu)所給例子的 main () 函數(shù),就可以了解插件的加載流程了:

pYYBAGMj7RiABMrSAAELwFnSM8M836.jpg

其中和加載插件相關(guān)的句子主要就是 pluma.acceptProviderType 和 pluma.load 兩句了。前者主要負(fù)責(zé)在 Host 的knownTypes映射表中添加一個 ProviderInfo 節(jié)點,后者負(fù)責(zé)加載插件動態(tài)庫,并將動態(tài)庫里匹配的 Provider 指針記入 ProviderInfo 節(jié)點。

4.1 pluma.acceptProviderType<>()

我們先說 pluma.acceptProviderType 一句。在前文介紹 Pluma.inl 文件的內(nèi)容時,我們已經(jīng)看到一個叫作 acceptProviderType 的模板函數(shù)了,當(dāng)時沒有細(xì)說,現(xiàn)在我把它的代碼再貼一下: 【pluma-1.1/include/pluma/Pluma.inl】

poYBAGMj7TiAck7tAABsH0sPDoI046.jpg

里面調(diào)用的是 PluginManager 基類的 registerType () 函數(shù)。 我們前文主要關(guān)心的是 PLUMA_PROVIDER_TYPE,現(xiàn)在再說一下后兩個參數(shù)。PLUMA_INTERFACE_VERSION 表示管理器當(dāng)前應(yīng)該使用的插件接口的版本,因為我們不能確定更高版本的插件接口會不會增加或刪除成員函數(shù),所以這個值其實是個限定值,如果后續(xù)用戶嘗試加載更高版本的插件,那么是無法通過校驗的。 第三個參數(shù) PLUMA_INTERFACE_LOWEST_VERSION 則是限定最低值,如果嘗試加載比這個值更低版本的插件,肯定也是不會通過的。 在剛剛看到的 main () 函數(shù)里,是這樣寫的:

pluma.acceptProviderType();

也就是說,Pluma 插件管理器對 Warrior 接口對應(yīng)的 WarriorProvider 類感興趣。而當(dāng)初定義 Warrior 時,在 Warrior.cpp 文件里的確指明了 WarriorProvider 能限定的當(dāng)前版本號和最低版本號:

PLUMA_PROVIDER_SOURCE(Warrior, 1, 1);

這些類型信息、版本號限定信息都會被注冊在 Host 的 knownTypes 映射表中,每種接口類型對應(yīng)一個 ProviderInfo 節(jié)點。注冊動作的代碼如下:

【pluma-1.1/src/pluma/PluginManager.cpp】

pYYBAGMj7WyAEUAbAABNgvDLs0g044.jpg

【pluma-1.1/src/pluma/Host.cpp】

pYYBAGMj7YKAdyMMAABiYEWlb3o152.jpg

當(dāng)然,新加的 ProviderInfo 節(jié)點的 providers 列表是個空列表,待后續(xù)再添加 Provider * 內(nèi)容。

4.2 pluma.load()

接著,我們繼續(xù)看 main () 函數(shù)里調(diào)用的 pluma.load (),其實調(diào)用的是其父類 PluginManager 的 load ()。相關(guān)代碼截選如下:

【pluma-1.1/src/pluma/PluginManager.cpp】

poYBAGMj7ZiANhKSAADTuumCVjE057.jpg

可以看到,一開始就在著手加載動態(tài)庫,并調(diào)用動態(tài)庫里的 connect () 函數(shù)。前文我們實際上已經(jīng)列舉過示例代碼里的 connect () 函數(shù)了,現(xiàn)在再貼一次:

poYBAGMj7a-ALQ-rAABA98TDc7Y693.jpg

前文在闡述到 connect () 時,暫時沒有細(xì)說 add () 動作,現(xiàn)在我們來看看它的代碼:

【pluma-1.1/src/pluma/Host.cpp】

poYBAGMj7cSAWJqUAACPOR6pUWQ601.jpg

上面代碼中那個 plumaGetType () 函數(shù)其實是 Provider 的私有成員,一般人訪問不了,但 Host 是它的友元類,所以可以訪問。代碼中會先校驗待添加的 Provider 是否合格,如果合格則以 plumaGetType () 返回值為 key 值,并向臨時映射表 addRequests 中添加該 Provider 指針。所謂合格是指,這個 Provider 的類型是 Host 感興趣的,并且其版本號也是合適的。

值得注意的是,待添加的 Provider*,只是臨時先放進(jìn)一個 addRequests 映射表中。addRequests 映射表的定義如下:

【pluma-1.1/include/pluma/Host.hpp】

poYBAGMj7d6AEQzAAAAviHyQa3M128.jpg

那么這個臨時性的 addRequests 映射表的內(nèi)容會怎樣處理呢?說起來也簡單,會被 “搬移” 進(jìn) Host 的 knownTypes 映射表中某個 ProviderInfo 的內(nèi)部列表去。main () 在調(diào)用完 connect () 函數(shù)后,調(diào)用的 confirmAddictions () 就是做這個事情的:

【pluma-1.1/src/pluma/Host.cpp】

poYBAGMj7fiAGhc6AAC7cpn6_Q8730.jpg

我們畫一張調(diào)用關(guān)系圖看看:


d302c168-3432-11ed-ba43-dac502259ad0.png ??

我們可以通過這張調(diào)用關(guān)系圖回顧一下,主要流程就是在加載插件動態(tài)庫,并執(zhí)行動態(tài)庫里的 connect () 函數(shù)。該函數(shù)會將動態(tài)庫里可用的所有 Provider * 記入 Host 的 knownTypes 映射表中。

同時,動態(tài)庫對應(yīng)的 DLibrary 對象,也會插入 Pluma 管理類內(nèi)部的 libraries 映射表中。

為了鞏固知識,我們把前文的兩張圖再整合一下。


d348a0ca-3432-11ed-ba43-dac502259ad0.png

5. 使用插件 Provider

5.1 pluma.getProviders()

在 Providers 都添加進(jìn) Pluma 管理類后,我們就可以在需要時獲取 provider 了,為此 Pluma 類提供了 getProviders () 函數(shù):

【pluma-1.1/src/pluma/PluginManager.cpp】

poYBAGMj7iOAJtYcAAA8tMoiTbU450.jpg

【pluma-1.1/src/pluma/Host.cpp】

pYYBAGMj7jaAPO0HAABhoNso11Q109.jpg

代碼很簡單,就是幫使用者把感興趣的某類插件 Provider 全部找出來。如果當(dāng)初我們已經(jīng)通過 acceptProviderType () 注冊了對應(yīng)的類型(PLUMA_PROVIDER_TYPE),那么至少可以拿到一個 list,否則就只能拿到 NULL 了。如果我們可以拿到若干 Provider,就可以調(diào)用其 create () 函數(shù)創(chuàng)建對應(yīng)的插件對象了。

當(dāng)工作做完后,用戶應(yīng)該及時 delete 掉之前創(chuàng)建出的插件對象。在程序退出之前,用戶應(yīng)該調(diào)用 pluma.unloadAll () 刪除所有插件 Provider 及 DLibrary 對象。DLibrary 對象析構(gòu)時,會自動關(guān)閉已經(jīng)打開的動態(tài)鏈接庫。

【pluma-1.1/src/pluma/PluginManager.cpp】

pYYBAGMj7lGALRXEAAEA--e0ITw849.jpg

6. 結(jié)束

至此,Pluma 架構(gòu)的主體代碼就分析完畢了,希望對大家有所幫助。

?


審核編輯:劉清

聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問題,請聯(lián)系本站處理。 舉報投訴
  • 管理器
    +關(guān)注

    關(guān)注

    0

    文章

    248

    瀏覽量

    18618
  • 字符串
    +關(guān)注

    關(guān)注

    1

    文章

    585

    瀏覽量

    20604
  • 開源架構(gòu)
    +關(guān)注

    關(guān)注

    0

    文章

    8

    瀏覽量

    6972

原文標(biāo)題:聊聊Pluma插件管理框架

文章出處:【微信號:OSC開源社區(qū),微信公眾號:OSC開源社區(qū)】歡迎添加關(guān)注!文章轉(zhuǎn)載請注明出處。

收藏 人收藏

    評論

    相關(guān)推薦

    JetBrains IDE上架開發(fā)微信小程序的官方插件

    快速發(fā)展的特色開發(fā)需求,最近 JetBrains 官方開發(fā)并上線了款專用于微信小程序開發(fā)插件
    的頭像 發(fā)表于 01-16 17:15 ?139次閱讀
    JetBrains IDE上架<b class='flag-5'>開發(fā)</b>微信小程序的官方<b class='flag-5'>插件</b>

    Spire.XLS for C++組件說明

    Spire.XLS for C++款專業(yè)的 C++ Excel 組件,可以用在各種 C++ 框架和應(yīng)用程序中。Spire.XLS for C+
    的頭像 發(fā)表于 01-14 09:40 ?150次閱讀
    Spire.XLS for <b class='flag-5'>C++</b>組件說明

    AKI跨語言調(diào)用庫神助攻C/C++代碼遷移至HarmonyOS NEXT

    跨語言調(diào)用,成為開發(fā)者和廠商面臨的重要挑戰(zhàn)。為解決這痛點,款名為AKI (Alpha Kernel Interacting)的開源三方庫應(yīng)運而生,它通過高效封裝跨語言調(diào)用接口,幫助
    發(fā)表于 01-02 17:08

    HighTec C/C++編譯器套件全面支持芯來RISC-V IP

    是基于LLVM開源汽車級C/C++編譯器工具,已通過ISO 26262 ASIL D的安全認(rèn)證。從事RISC-V架構(gòu)開發(fā)的汽車軟件
    的頭像 發(fā)表于 12-23 09:04 ?341次閱讀
    HighTec <b class='flag-5'>C</b>/<b class='flag-5'>C++</b>編譯器套件全面支持芯來RISC-V IP

    同樣是函數(shù),在CC++中有什么區(qū)別

    同樣是函數(shù),在 CC++ 中有什么區(qū)別? 第一個返回值。 C語言的函數(shù)可以不寫返回值類型,編譯器會默認(rèn)為返回 int。 但是 C++
    的頭像 發(fā)表于 11-29 10:25 ?434次閱讀

    Chrome瀏覽器插件

    、什么是瀏覽器插件 瀏覽器插件是依附于瀏覽器,用來拓展網(wǎng)頁能力的程序。插件具有監(jiān)聽瀏覽器事件、獲取和修改網(wǎng)頁元素、攔截網(wǎng)絡(luò)請求、添加快捷菜單等功能。使用瀏覽器
    的頭像 發(fā)表于 11-18 17:12 ?506次閱讀
    寫<b class='flag-5'>一</b><b class='flag-5'>個</b>Chrome瀏覽器<b class='flag-5'>插件</b>

    使用OpenVINO GenAI API在C++中構(gòu)建AI應(yīng)用程序

    許多桌面應(yīng)用程序是使用 C++ 開發(fā)的,而將生成式AI(GenAI)功能集成到這些應(yīng)用程序中可能會很具有挑戰(zhàn)性,尤其是因為使用像 Hugging Face 這樣的 Python 庫的復(fù)雜性。C++
    的頭像 發(fā)表于 10-12 09:36 ?470次閱讀
    使用OpenVINO GenAI API在<b class='flag-5'>C++</b>中構(gòu)建AI應(yīng)用程序

    【飛凌嵌入式OK3576-C開發(fā)板體驗】RKNN神經(jīng)網(wǎng)絡(luò)算法開發(fā)環(huán)境搭建

    的軟件包管理系統(tǒng)和環(huán)境管理系統(tǒng),主要用于安裝、更新、刪除軟件包及其依賴關(guān)系,并允許用戶在不同環(huán)境之間輕松切換。用于后續(xù)安裝Python等插件
    發(fā)表于 10-10 09:28

    ostream在c++中的用法

    )是 C++ 標(biāo)準(zhǔn)輸出流體系的核心部分,用于向各種輸出設(shè)備(如控制臺、文件等)發(fā)送數(shù)據(jù)。 1. 基本概念 ostream 是抽象基類,它定義了向輸出流寫入數(shù)據(jù)的基本接口。 ost
    的頭像 發(fā)表于 09-20 15:11 ?952次閱讀

    OpenVINO2024 C++推理使用技巧

    很多人都使用OpenVINO新版的C++ 或者Python的SDK,都覺得非常好用,OpenVINO2022之后的版本C++ SDK做了大量的優(yōu)化與整理,已經(jīng)是非常貼近開發(fā)的使用習(xí)慣與推理方式。與OpenCV的Mat對象對接方式
    的頭像 發(fā)表于 07-26 09:20 ?1057次閱讀

    C++中實現(xiàn)類似instanceof的方法

    C++有多態(tài)與繼承,但是很多人開始學(xué)習(xí)C++,有時候會面臨常見問題,就是如何向下轉(zhuǎn)型,特別是不知道具體類型的時候,這個時候就希望C++
    的頭像 發(fā)表于 07-18 10:16 ?673次閱讀
    <b class='flag-5'>C++</b>中實現(xiàn)類似instanceof的方法

    keilc++編譯含有rtos模塊時的錯誤問題怎么解決?

    近期看到哥們c++寫嵌入式,感覺蠻有趣,如果當(dāng)初我的程序要是能用類就輕松多了,所以也想嘗試下。雖然不會
    發(fā)表于 05-09 08:29

    鴻蒙OS開發(fā)實例:【Native C++

    使用DevEco Studio創(chuàng)建Native C++應(yīng)用。應(yīng)用采用Native C++模板,實現(xiàn)使用NAPI調(diào)用C標(biāo)準(zhǔn)庫的功能。使用
    的頭像 發(fā)表于 04-14 11:43 ?2767次閱讀
    鴻蒙OS<b class='flag-5'>開發(fā)</b>實例:【Native <b class='flag-5'>C++</b>】

    請問CubeIDE如何支持C++開發(fā)?

    CubeIDE如何支持C++開發(fā)。有沒有些例程。
    發(fā)表于 03-25 06:22

    鴻蒙實戰(zhàn)開發(fā)學(xué)習(xí):【HiView插件開發(fā)

    Hiview是跨平臺的終端設(shè)備維測服務(wù)集,其中是由插件管理平臺和插件實現(xiàn)的各自功能構(gòu)成整套系統(tǒng)。 本文描述了hiview
    的頭像 發(fā)表于 03-12 11:52 ?1433次閱讀
    鴻蒙實戰(zhàn)<b class='flag-5'>開發(fā)</b>學(xué)習(xí):【HiView<b class='flag-5'>插件</b><b class='flag-5'>開發(fā)</b>】
    沈阳市| 百家乐官网策略| 百家乐的代理办法| 百家乐官网看不到视频| 天博百家乐的玩法技巧和规则| 大发888体育和娱乐| 百家乐之对子的技巧| 金山区| 娱乐城送钱| 百家乐黏土筹码| 运城百家乐官网蓝盾| 百家乐官网游戏的玩法| 盛世国际娱乐场| 大发888最新信息| 百家乐凯时赌场娱乐网规则| 百家乐官网用品| 真人百家乐官网做假| 百家乐官网机器昀程序| 大富豪百家乐| 娱网棋牌| 老虎机控制器| 新锦江百家乐娱乐场开户注册| 致胜百家乐官网下载| 澳门百家乐官网有哪些| 百家乐官网另类投注法| 视频百家乐是真是假| 澳门百家乐秘积| 百家乐视频免费下载| 做生意店铺风水好吗| 百家乐官网庄牌| 博雅德州扑克下载| 威尼斯人娱乐备用6222| LV百家乐娱乐城| 威尼斯人娱乐城注册| 威尼斯人娱乐城会员注册| 百家乐最安全打法| 百家乐是如何出千的| 百家乐视频游戏冲值| 博之道百家乐技巧| 狮威百家乐的玩法技巧和规则 | 百家乐官网的破解方法|