動態鏈接庫

          動態連接庫(Dynamic link library),是一些編譯過的可以執行的代碼模塊,后綴為.dll
          1 DLL的基本理論
          ? 在使用普通函數庫時,可以在程序連接時將庫中的代碼拷貝到執行文件中,這時靜態鏈接,在多個同樣程序執行時,體統保留了許多
          代碼副本,造成了內存資源的浪費。在使用dll時,不必將dll鏈接到程序中,而是在應用程序運行時動態的裝載dll,裝載dll被映射
          到進程的地址空間中。同時,使用dll 并不時將庫代碼拷貝,只是在程序中記錄了函數的入口點和接口。
          2 DLL 的優點
          ?1) 節省系統資源
          ?2) 不僅可以包括可執行代碼,還可以包括數據和各種資源
          ?3)支持多語言
          ?4)升級可以僅僅覆蓋dll 文件
          ?5)dll 獨立編程語言,c++builder 中的dll vc 也可以使用
          3導入導出匹配
          ??? DLL函數一般有兩種函數,內部函數(internal)和導出函數(export).在實際情況下,許多DLL 調用了其他DLL里面的函數,因此
          DLL可以同時有導入和導出函數。
          ???? DLL 包含有一個導出函數表,可以通過函數的符號化的名字和稱為序號的正書來識別這些函數,函數表中包含了函數在dll內部的
          地址。在動態鏈接進程好建立一張表,把客戶的調用與dll里的函數的地址連接起來。
          ??? double dbValue(value);//內部函數
          ??? double dbValue(value);//內部函數
          ??? extern"c" _declspec(dllexpoert) double changeValue(double,bool);//外部函數
          ?? double dblValue(double value)
          ?? {
          ?????? return value*vlaue;
          ?? }
          ?? double changeValue(double value,bool whichOp)
          ? {
          ???? return whichOp?doublValue(value):halfValue(value);
          ?? }
          ? 如果我們希望dll可以用于其他語言或不同版本的c++ 需要在聲明導出函數的時候加上extern "C."
          ?4 隱式的鏈接和顯示的鏈接
          ?? 隱式鏈接(前面所講)在創建dll 的時候,鏈接器產生一個lib 文件把拿獲了dll中的導出符號和序號
          ?? 顯示鏈接調用Win32 的LoadLibrary 函數,使用完后,調用 FreeLibrary.
          ?5 查找dll
          ?? 依次順序為包含exe 的目錄,進程的當前目錄,Windows 目錄,path 環境變量里列出的目錄。
          ?6 創建動態鏈接庫
          ?? (如何查看dll 文件的定義)
          ?7 導出函數:extern "C" __declspec(dllexport) ExportType FunctionName(Parameter)
          ??? extern "C" __declspec(dllimport) __stdcall void CreateFromFunct();
          ??? extern "C" __declspec(dllexport) __stdcall void CreateFromFunct();//導出函數
          ??? 導出類:class __declspec(dllexport) ExportType ClassName{...}
          ??? class __declspec(dllexport) __stdcall MyDllClass { //導出類
          ???? public:
          ??? MyDllClass();
          ??? void CreateAForm();
          ??? TDllFrm* DllMyForm;
          ??? };

          ???? __declspec(dllimport) class __stdcall MyDllClass {
          ?????? public:
          ?????? MyDllClass();
          ?????? void CreateAForm();
          ?????? TDllFrm* DllMyForm;
          ??? };
          ??? 靜態調用,build 生成dll 文件和lib 文件,并把lib 文件導入到工程中
          ???? void __fastcall TForm1::Button1Click(TObject *Sender)
          ??? { // 導出類實現,導出類只能使用靜態方式調用
          ?????? DllClass = new MyDllClass();
          ?????? DllClass->CreateAForm();??
          ??? }
          ??? void __fastcall TForm1::Button2Click(TObject *Sender)
          ??? { // 導出函數實現
          ?????? CreateFromFunct();
          ???? }
          ???? void __fastcall TForm1::FormClose(TObject *Sender, TCloseAction &Action)
          ??? {
          ???????? delete DllClass;
          ???? }
          ?? 動態調用
          ?? class TForm1 : public TForm
          ? {
          ???????? ...
          ????? private: // User declarations
          ????? void (__stdcall *CreateFromFunct)();
          ?????????? ...
          ?? }
          ? HINSTANCE DLLInst = NULL;
          ? void __fastcall TForm1::Button2Click(TObject *Sender)
          ? {??
          ???? if( NULL == DLLInst ) DLLInst = LoadLibrary("DLL.dll"); //上面的 Dll
          ???? if (DLLInst) {
          ???????????? CreateFromFunct = (void (__stdcall*)()) GetProcAddress(DLLInst,
          ????????????????????????? "CreateFromFunct");
          ????? if (CreateFromFunct) CreateFromFunct();
          ????? else ShowMessage("Could not obtain function pointer");
          ?? }
          ????? else ShowMessage("Could not load DLL.dll");
          ? }
          ?? void __fastcall TForm1::FormClose(TObject *Sender, TCloseAction &Action)
          ? {
          ???? if ( DLLInst ) FreeLibrary (DLLInst);
          ? }
          8? bcb 調用vc 編寫的DLL
          ? 1) 名字分解
          ?? 1. 名字分解:
          ? 沒有名字分解的函數
          ??? TestFunction1 // __cdecl calling convention
          ??? @TestFunction2 // __fastcall calling convention
          ??? TESTFUNCTION3 // __pascal calling convention
          ??? TestFunction4 // __stdcall calling convention
          ? 有名字分解的函數
          ??? @TestFunction1$QV // __cdecl calling convention
          ??? @TestFunction2$qv // __fastcall calling convention
          ??? TESTFUNCTION3$qqrv // __apscal calling convention
          ??? @TestFunction4$qqrv // __stdcall calling convention
          ? 使用 extern "C" 不會分解函數名
          ?? 2)
          ????? __cdecl 缺省
          ?? 是 Borland C++ 的缺省的 C 格式命名約定,它在標識符前加一下劃線,以保留
          ? 它原來所有的全程標識符。參數按最右邊參數優先的原則傳遞給棧,然后清棧。
          ??? extaern "C" bool __cdecl TestFunction();
          ?? 在 def 文件中顯示為
          ??? TestFunction @1
          ?? 注釋: @1 表示函數的順序數,將在“使用別名”時使用。

          ? __pascal Pascal格式
          ?? 這時函數名全部變成大寫,第一個參數先壓棧,然后清棧。
          ??? TESTFUNCTION @1 //def file

          ? __stdcall 標準調用
          ?? 最后一個參數先壓棧,然后清棧。
          ??? TestFunction @1 //def file

          ? __fastcall 把參數傳遞給寄存器
          ?? 第一個參數先壓棧,然后清棧。
          ??? @TestFunction @1 //def file
          ? 3)
          ?? 3. 解決調用約定:
          ?? Microsoft 與 Borland 的 __stdcall 之間的區別是命名方式。 Borland 采用
          ? __stdcall 的方式去掉了名字起前的下劃線。 Microsoft 則是在前加上下劃線,在
          ? 后加上 @ ,再后跟為棧保留的字節數。字節數取決于參數在棧所占的空間。每一個
          ? 參數都舍入為 4 的倍數加起來。這種 Miocrosoft 的 DLL 與系統的 DLL 不一樣。
          ?4 查看dll 的調用接口tdump -ee MyDll.dll >1.txt (查看 1.txt 文件即可)
          5 編輯c++ builder build 為一個可以直接調用的 .exe 。 點擊project option? 中linker 標簽 去掉user dynamic RTL 選項 和package 中 去掉builder with runtime package 選項.
          6 調用代參數的vl 編寫的dll 調用的實例。
          int (__cdecl *fun)(char*,char*,char*);

          HINSTANCE DLLInst = NULL;
          void __fastcall TForm1::Button1Click(TObject *Sender)
          {
          if( NULL == DLLInst )
          {
          DLLInst = LoadLibrary("HollyIVRCard.dll");
          }
          if(DLLInst)
          {
          ? fun=(int (__cdecl*)(char*,char*,char*))GetProcAddress(DLLInst,"hTrade");
          ? if(fun)
          ? {
          ??? cardid=Edit1->Text.c_str();
          ??? num=Edit2->Text.c_str();
          ??? ShowMessage(fun(cardid,num,res));
          ??? //cout<<cardid<<endl;
          ??? //cout<<num<<endl;
          ? }
          } else{
          ?? ShowMessage("load dll fail");
          }
          ?? ShowMessage(AnsiString(res));
          }

          posted on 2006-09-06 18:13 康文 閱讀(386) 評論(0)  編輯  收藏 所屬分類: c\c++

          <2006年9月>
          272829303112
          3456789
          10111213141516
          17181920212223
          24252627282930
          1234567

          導航

          統計

          常用鏈接

          留言簿(1)

          隨筆分類

          隨筆檔案

          文章檔案

          搜索

          最新評論

          閱讀排行榜

          評論排行榜

          主站蜘蛛池模板: 益阳市| 射阳县| 合川市| 临高县| 玉林市| 林芝县| 时尚| 平遥县| 陕西省| 维西| 洪江市| 福清市| 太保市| 宁远县| 金寨县| 昌都县| 普兰店市| 乌兰县| 炎陵县| 东城区| 修水县| 宁武县| 集安市| 汨罗市| 施甸县| 彭阳县| 安吉县| 大田县| 新民市| 梁山县| 荣成市| 唐河县| 亳州市| 大安市| 木里| 罗江县| 连城县| 巩义市| 古田县| 德令哈市| 峨眉山市|