線上訂房服務-台灣趴趴狗聯合訂房中心
發文 回覆 瀏覽次數:2984
推到 Plurk!
推到 Facebook!

c++ builder 免用midas.dll 的方式

 
aftcast
站務副站長


發表:81
回覆:1485
積分:1763
註冊:2002-11-21

發送簡訊給我
#1 引用回覆 回覆 發表時間:2014-06-30 20:41:57 IP:114.32.xxx.xxx 訂閱
大家好,

c builder的資源很少,又算是delphi的房客。經常的,delphi簡單的一個做法就搞定一些作法,但cb就是要自己來。學cb的人算很強,也很可憐。強的是也要會delphi才能精通呀!

我們知道delphi若要不使用midas.dll只要use MidasLib 就可以。那c 呢? … 沒辦法囉… 為了爭一口氣,我決定就寫一個MidasLib.hpp,那麼事情就會如delphier一樣的爽了。

你只要
#include "MidasLib.hpp"

加這行到你的專案就可以搞定一切。 程式碼雖極小,但隱含一些深入的觀念,有時間可以看一下,1分鐘內就看完的… 對不熟cb的人來說,但可能受益無菲淺呢!

蕭沖

另附上hami雲的連結供備用
http://cht.tw/h/2zuyg
------


蕭沖
--All ideas are worthless unless implemented--

C++ Builder Delphi Taiwan G+ 社群
http://bit.ly/cbtaiwan
GrandRURU
站務副站長


發表:240
回覆:1680
積分:1874
註冊:2005-06-21

發送簡訊給我
#2 引用回覆 回覆 發表時間:2014-07-01 09:03:00 IP:59.120.xxx.xxx 訂閱
補充一點

在 XE6 中,Midas.lib 是放在:
C:\Program Files\Embarcadero\Studio\14.0\lib\win32\release

記得要把這個 LIB 加入專案中。
taishyang
站務副站長


發表:377
回覆:5490
積分:4563
註冊:2002-10-08

發送簡訊給我
#3 引用回覆 回覆 發表時間:2014-07-01 10:32:47 IP:60.251.xxx.xxx 訂閱
感謝分享,能否請前輩解釋一下原理呢^^?
aftcast
站務副站長


發表:81
回覆:1485
積分:1763
註冊:2002-11-21

發送簡訊給我
#4 引用回覆 回覆 發表時間:2014-07-05 16:51:57 IP:114.32.xxx.xxx 訂閱

[code delphi]
//in DSIntf.pas
var
Loading: TObject;
DbClientHandle: THandle = THandle(0);
DllGetClassObject: function(const CLSID, IID: TGUID; var Obj): HResult; stdcall;


if DbClientHandle = 0 then
.....
DbClientHandle := LoadLibrary(PChar(FileName)); // Midas.dll
DllGetClassObject := GetProcAddress(DbClientHandle, 'DllGetClassObject');
........
end;
procedure RegisterMidasLib(GetClassProc: Pointer);
begin
DllGetClassObject := GetClassProc;
DbClientHandle := THandle(1);
end;
//------------------------------------------
//in alchemy.cpp
extern "C" HRESULT _export DBIFN DllGetDataSnapClassObject(REFCLSID rclsid, REFIID riid, pVOID *ppv)
{
return DllGetClassObject(rclsid, riid, ppv);
}
STDAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, pVOID *ppv)
{
HRESULT rslt = 0;
DS_Factory *ppvObj = NULL;
if (ppv == NULL)
return E_INVALIDARG;
#ifdef MIDAS_DLL
if (IsEqualCLSID(rclsid, CLSID_MDSBASE_1))
{
ppvObj = (DS_Factory*)new DSBASE_Factory();
}
.................
[/code]


DSIntf.pas 是初始化midas 元件的單元。看我貼的部份,DbClientHandle 預設值是0,接著透過if =0 開始去做二件重要的事,1/ 把midas dll 載入 2/ 找出dll裡DllGetClassObject這個function出來備用…

我們的問題是,我沒dll,但我有一份和dll幾乎一樣的「二進位碼」(obj/lib檔)在我的exe檔裡,可不可以 1/ 不要去載入 dll 2/ 用exe裡的DllGetClassObject function來處理取得objects? 有了這樣的了解後,我們的解法就會有 (delphi本身有預留啦,不能也無解)。
1/ 讓 if 不成立,就不會load dll
2/ 讓DllGetClassObject 指向我們的exe檔裡的地方
為了要達成上述二點,就呼叫DSIntf.pas裡的RegisterMidasLib()。 懂了吧!

另一個問題是,exe檔裡的DllGetClassObject 位址在哪裡呢? 在 alchemy.cpp 這裡有(系統c 實作midas的一部份)。但因為它沒有被曝露出來,不能直接叫它,所以就叫他有露的DllGetDataSnapClassObject 這個 c function。但又因為它沒有露出header檔,所以你無法用include xxxx 來讓compiler了解它的存在,於是你就要用extern 的外在宣告方式告訴compiler說,你別煩,它就是有在某個二進位(obj)裡。又為何用 "c" 這個關鍵字? 因為它是 純 c 的function (不懂的話去google一下我的blog)。

最後一個重點: 極重要,我們發現 DbClientHandle: THandle = THandle(0); 這句話是全域變數,可以單元被戴入後就會馬上執行的耶… 我怎麼在 if 前就先下重手讓它不是 0 ? 網路上你可能會看到一些部落客說在form create時叫 RegisterMidasLib,為的就是要搶得先機。但夠不夠先呢? 嘿嘿…我個人覺得難說,比如說你是放在datamodule裡,而它又是比form被先初始化,你就掛了啦… 那要如何搶第一名? 就是用極少極少cb人知道的 #pragma startup (cb擴展) 它會在main() 就是程式進入點前就先偷跑,這樣他不是第一名,誰是第一名,是不?! ^ ^

本不想在忙的時候寫很多啦,看在taishyang的請求上,假日就補一下囉! 希望對 c builder的用戶有一些技術上的幫助,這也是讓我開心的地方! :)


===================引 用 taishyang 文 章===================
感謝分享,能否請前輩解釋一下原理呢^^?
------


蕭沖
--All ideas are worthless unless implemented--

C++ Builder Delphi Taiwan G+ 社群
http://bit.ly/cbtaiwan
編輯記錄
aftcast 重新編輯於 2014-07-05 16:53:13, 註解 無‧
taishyang
站務副站長


發表:377
回覆:5490
積分:4563
註冊:2002-10-08

發送簡訊給我
#5 引用回覆 回覆 發表時間:2014-07-07 10:06:43 IP:60.251.xxx.xxx 訂閱
感謝高手高手高高手~~~
系統時間:2024-04-26 5:52:38
聯絡我們 | Delphi K.Top討論版
本站聲明
1. 本論壇為無營利行為之開放平台,所有文章都是由網友自行張貼,如牽涉到法律糾紛一切與本站無關。
2. 假如網友發表之內容涉及侵權,而損及您的利益,請立即通知版主刪除。
3. 請勿批評中華民國元首及政府或批評各政黨,是藍是綠本站無權干涉,但這裡不是政治性論壇!