c++ builder 免用midas.dll 的方式 |
|
aftcast
站務副站長 發表:81 回覆:1485 積分:1763 註冊:2002-11-21 發送簡訊給我 |
大家好,
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 發送簡訊給我 |
|
taishyang
站務副站長 發表:377 回覆:5490 積分:4563 註冊:2002-10-08 發送簡訊給我 |
|
aftcast
站務副站長 發表:81 回覆:1485 積分:1763 註冊:2002-11-21 發送簡訊給我 |
[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 發送簡訊給我 |
本站聲明 |
1. 本論壇為無營利行為之開放平台,所有文章都是由網友自行張貼,如牽涉到法律糾紛一切與本站無關。 2. 假如網友發表之內容涉及侵權,而損及您的利益,請立即通知版主刪除。 3. 請勿批評中華民國元首及政府或批評各政黨,是藍是綠本站無權干涉,但這裡不是政治性論壇! |