C++ Builder 創(chuàng)建和使用動(dòng)態(tài)加載的包 (.bpl)

C++ Builder 參考手冊(cè) ? 創(chuàng)建和使用動(dòng)態(tài)加載的包 (.bpl)


  1. 動(dòng)態(tài)加載的包 (.bpl) 簡(jiǎn)介
  2. 創(chuàng)建一個(gè)動(dòng)態(tài)加載的包 (.bpl)
  3. 使用動(dòng)態(tài)加載的包 (.bpl)

1. 動(dòng)態(tài)加載的包 (.bpl) 簡(jiǎn)介

組件包文件 .bpl 不安裝在控件面板上,不通過(guò)拖拽放置在 Form 上仗嗦,也沒(méi)有頭文件的情況下阱飘,只有一個(gè) .bpl 文件长搀,通過(guò) LoadPackage 加載靖避,然后使用里面的函數(shù)和類。C++ 沒(méi)有原生支持的反射屯断,不像 Delphi 直接通過(guò)類名反射出對(duì)象昨稼,但是仍然有辦法創(chuàng)建和使用動(dòng)態(tài)加載的包:

  • 動(dòng)態(tài)加載的 bpl 文件里面要有創(chuàng)建類的函數(shù),并且按照 dll 函數(shù)導(dǎo)出论皆;
    ? Delphi 只需要知道類名就可以使用了益楼;
    ? C++ 類名沒(méi)有用,需要知道創(chuàng)建類的對(duì)象的函數(shù)名点晴;
  • 只要?jiǎng)?chuàng)建了對(duì)象感凤,通過(guò)對(duì)象指針可以枚舉屬性、事件和方法粒督;
  • 通過(guò)成員函數(shù)名 (字符串) 可以調(diào)用成員函數(shù)陪竿。

2. 創(chuàng)建一個(gè)動(dòng)態(tài)加載的包 (.bpl)

2.1. 創(chuàng)建組件包項(xiàng)目

和普通的組件包一樣:
選擇菜單 File -> New -> Package - C++ Builder
或者菜單 File -> New - Other... 在打開(kāi)的對(duì)話框里面,左面的樹形結(jié)構(gòu)選擇 C++ Builder屠橄,右面選擇 Package
創(chuàng)建一個(gè) .bpl 組件包項(xiàng)目

2.2. 添加組件

和普通的組件包一樣:
選擇菜單 Component -> New Component
選擇 VCL for C++ Win32 添加一個(gè) VCL 組件族跛,然后選擇從哪個(gè)類繼承,運(yùn)行時(shí)不可見(jiàn)的組件仇矾,可以選擇 TComponent 作為父類庸蔼,也可以根據(jù)需要選擇其他的類作為父類。

然后:
選擇安裝在組件面板上的哪個(gè)頁(yè)面贮匕,也可以自己起個(gè)名字姐仅;
生成的源程序存放位置和文件名;

類的 __published 訪問(wèn)權(quán)限的屬性刻盐、事件和方法支持通過(guò)對(duì)象指針枚舉和通過(guò)名稱 (字符串) 訪問(wèn)掏膏。

2.3. 添加其他類

所有從 TObject 繼承的類的 __published 訪問(wèn)權(quán)限的成員都支持枚舉屬性、事件和方法敦锌,也支持通過(guò)成員函數(shù)名調(diào)用成員函數(shù)馒疹,只要給類加上 PACKAGE 屬性就可以從組件包里面導(dǎo)出,在組件包外面調(diào)用乙墙,例如:class PACKAGE THsuanluTest : public TObject { ...

2.4. 添加創(chuàng)建類的函數(shù)

創(chuàng)建類的函數(shù)必須定義為 C 語(yǔ)言格式 (extern "C") 和 __stdcall 調(diào)用約定颖变,并且也需要指定 PACKAGE 屬性從包里面導(dǎo)出這個(gè)函數(shù)。

例:通過(guò)菜單 Component -> New Component 創(chuàng)建的繼承 TComponent 的類 THsuanluComponent1听想,寫個(gè)函數(shù) CreateComponent1 創(chuàng)建 THsuanluComponent1 類:

extern "C" TObject *PACKAGE __stdcall CreateComponent1(void)
{
    return new THsuanluComponent1(NULL);
}

3. 使用動(dòng)態(tài)加載的包 (.bpl)

  • 使用 LoadPackage 加載 .bpl
  • 使用 GetProcAddress 通過(guò)函數(shù)名字符串獲取創(chuàng)建類的函數(shù)腥刹,例如前面說(shuō)的 CreateComponent1 函數(shù),然后調(diào)用這個(gè)函數(shù)創(chuàng)建類汉买,得到 TObject 對(duì)象指針衔峰;
  • 通過(guò) TObject 指針可以枚舉所有的屬性、事件和方法
  • 通過(guò) TObject 指針調(diào)用 MethodAddress 方法垫卤,可以通過(guò)成員函數(shù)名字符串獲取成員函數(shù)的地址威彰,然后通過(guò) TObject 指針和成員函數(shù)地址合成 __closure 指針,調(diào)用這個(gè) __closure 指針即調(diào)用了這個(gè)對(duì)象的成員函數(shù)穴肘。

例子:

創(chuàng)建 HsuanluTestPackage.bpl 包:

  1. 選擇菜單 File -> New -> Package - C++ Builder 創(chuàng)建一個(gè) .bpl 組件包項(xiàng)目
  2. 選擇菜單 Component -> New Component歇盼,然后選擇 VCL for C++ Win32 添加一個(gè) VCL 組件,選擇 TComponent 作為父類评抚,類名為 THsuanluComponent1
  3. 在生成的類里面添加 __published: 成員 void TestFunc(void);

以下為類的定義和實(shí)現(xiàn)部分旺遮、以及創(chuàng)建這個(gè)類的對(duì)象的函數(shù) CreateComponent1,其他部分省略

class PACKAGE THsuanluComponent1 : public TComponent
{
private:
protected:
public:
    __fastcall THsuanluComponent1(TComponent* Owner);
__published:
    void TestFunc(void);
};
__fastcall THsuanluComponent1::THsuanluComponent1(TComponent* Owner)
    : TComponent(Owner)
{
}
//---------------------------------------------------------------------------
void THsuanluComponent1::TestFunc(void)
{
    ::MessageBox(NULL, L"測(cè)試組件包:THsuanluComponent1::TestFunc", L"TestFunc - 玄坴", MB_OK|MB_ICONINFORMATION);
}
//---------------------------------------------------------------------------
extern "C" TObject *PACKAGE __stdcall CreateComponent1(void)
{
    return new THsuanluComponent1(NULL);
}

調(diào)用 HsuanluTestPackage.bpl 包:
這個(gè)例子的目標(biāo)是調(diào)用 THsuanluComponent1::TestFunc 成員函數(shù)盈咳,沒(méi)有頭文件耿眉,不知道類的具體定義和實(shí)現(xiàn)。

由于動(dòng)態(tài)加載組件包不需要頭文件和鏈接庫(kù)文件鱼响,這個(gè)例子直接在按鈕點(diǎn)擊事件里面:通過(guò) Sysutils::LoadPackage 加載 bpl 包鸣剪,通過(guò)函數(shù)名創(chuàng)建對(duì)象,通過(guò)成員函數(shù)名調(diào)用成員函數(shù)丈积,然后通過(guò) Sysutils::FreeAndNil 釋放對(duì)象占用資源筐骇,然后通過(guò) Sysutils::UnloadPackage 釋放 bpl 包占用的資源。

TMethod 有兩個(gè)成員:Code 和 Data江滨,是 __closure 的組成铛纬,調(diào)用這個(gè) __closure 指針相當(dāng)于調(diào)用 Data->Code(); 其中 Data 直接指向?qū)ο螅珻ode 指向 MethodAddress 方法獲取的成員函數(shù)的地址唬滑。

void __fastcall TForm1::Button1Click(TObject *Sender)
{
    try
    {
        NativeUInt hPackage = Sysutils::LoadPackage(L"HsuanluTestPackage.bpl");
        TObject *__stdcall (*pfCreate)(void) = (TObject *__stdcall(*)(void))::GetProcAddress((HINSTANCE)hPackage, "CreateComponent1");
        if(pfCreate)
        {
            TObject *pComponent = pfCreate();

            TMethod Method;
            Method.Code = pComponent->MethodAddress(L"TestFunc");
            Method.Data = pComponent;

            typedef void (__closure *pFunc)(void);
            (*(pFunc*)&Method)();

            Sysutils::FreeAndNil(&pComponent);
        }
        Sysutils::UnloadPackage(hPackage);
    }
    catch(Exception &e)
    {
        ShowMessage(e.Message);
    }
}

運(yùn)行結(jié)果:

運(yùn)行結(jié)果

相關(guān):


C++ Builder 參考手冊(cè) ? 創(chuàng)建和使用動(dòng)態(tài)加載的包 (.bpl)

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末稻艰,一起剝皮案震驚了整個(gè)濱河市懂牧,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌尊勿,老刑警劉巖僧凤,帶你破解...
    沈念sama閱讀 211,948評(píng)論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異元扔,居然都是意外死亡躯保,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,371評(píng)論 3 385
  • 文/潘曉璐 我一進(jìn)店門摇展,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)吻氧,“玉大人,你說(shuō)我怎么就攤上這事咏连《⑺铮” “怎么了?”我有些...
    開(kāi)封第一講書人閱讀 157,490評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵祟滴,是天一觀的道長(zhǎng)振惰。 經(jīng)常有香客問(wèn)我,道長(zhǎng)垄懂,這世上最難降的妖魔是什么骑晶? 我笑而不...
    開(kāi)封第一講書人閱讀 56,521評(píng)論 1 284
  • 正文 為了忘掉前任,我火速辦了婚禮草慧,結(jié)果婚禮上桶蛔,老公的妹妹穿的比我還像新娘。我一直安慰自己漫谷,他們只是感情好仔雷,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,627評(píng)論 6 386
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著舔示,像睡著了一般碟婆。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上惕稻,一...
    開(kāi)封第一講書人閱讀 49,842評(píng)論 1 290
  • 那天竖共,我揣著相機(jī)與錄音,去河邊找鬼俺祠。 笑死公给,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的蜘渣。 我是一名探鬼主播妓布,決...
    沈念sama閱讀 38,997評(píng)論 3 408
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼宋梧!你這毒婦竟也來(lái)了匣沼?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書人閱讀 37,741評(píng)論 0 268
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤捂龄,失蹤者是張志新(化名)和其女友劉穎释涛,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體倦沧,經(jīng)...
    沈念sama閱讀 44,203評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡唇撬,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,534評(píng)論 2 327
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了展融。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片窖认。...
    茶點(diǎn)故事閱讀 38,673評(píng)論 1 341
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出扑浸,到底是詐尸還是另有隱情烧给,我是刑警寧澤,帶...
    沈念sama閱讀 34,339評(píng)論 4 330
  • 正文 年R本政府宣布喝噪,位于F島的核電站础嫡,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏酝惧。R本人自食惡果不足惜榴鼎,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,955評(píng)論 3 313
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望晚唇。 院中可真熱鬧巫财,春花似錦、人聲如沸哩陕。這莊子的主人今日做“春日...
    開(kāi)封第一講書人閱讀 30,770評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)萌踱。三九已至葵礼,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間并鸵,已是汗流浹背鸳粉。 一陣腳步聲響...
    開(kāi)封第一講書人閱讀 32,000評(píng)論 1 266
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留园担,地道東北人届谈。 一個(gè)月前我還...
    沈念sama閱讀 46,394評(píng)論 2 360
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像弯汰,于是被迫代替她去往敵國(guó)和親艰山。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,562評(píng)論 2 349

推薦閱讀更多精彩內(nèi)容