MDA之路

          MDA,UML,XML,Eclipse及Java相關的Blog
          posts - 53, comments - 494, trackbacks - 0, articles - 2
            BlogJava :: 首頁 :: 新隨筆 :: 聯系 :: 聚合  :: 管理

          DLL編寫教程

          Posted on 2007-09-11 22:13 wxb_nudt 閱讀(64591) 評論(113)  編輯  收藏 所屬分類: 實用編程技術

           

          DLL編寫教程

          半年不能上網,最近網絡終于通了,終于可以更新博客了,寫點什么呢?決定最近寫一個編程技術系列,其內容是一些通用的編程技術。例如DLLCOMSocket,多線程等等。這些技術的特點就是使用廣泛,但是誤解很多;網上教程很多,但是幾乎沒有什么優質良品。我以近幾個月來的編程經驗發現,很有必要好好的總結一下這些編程技術了。一來對自己是總結提高,二來可以方便光顧我博客的朋友。

          好了,廢話少說,言歸正傳。第一篇就是《DLL編寫教程》,為什么起這么土的名字呢?為什么不叫《輕輕松松寫DLL》或者《DLL一日通》呢?或者更nb的《深入簡出DLL》呢?呵呵,常常上網搜索資料的弟兄自然知道。

          本文對通用的DLL技術做了一個總結,并提供了源代碼打包下載,下載地址為:

          http://www.aygfsteel.com/Files/wxb_nudt/DLL_SRC.rar

          DLL的優點

          簡單的說,dll有以下幾個優點:

          1)      節省內存。同一個軟件模塊,若是以源代碼的形式重用,則會被編譯到不同的可執行程序中,同時運行這些exe時這些模塊的二進制碼會被重復加載到內存中。如果使用dll,則只在內存中加載一次,所有使用該dll的進程會共享此塊內存(當然,像dll中的全局變量這種東西是會被每個進程復制一份的)。

          2)      不需編譯的軟件系統升級,若一個軟件系統使用了dll,則該dll被改變(函數名不變)時,系統升級只需要更換此dll即可,不需要重新編譯整個系統。事實上,很多軟件都是以這種方式升級的。例如我們經常玩的星際、魔獸等游戲也是這樣進行版本升級的。

          3)      Dll庫可以供多種編程語言使用,例如用c編寫的dll可以在vb中調用。這一點上DLL還做得很不夠,因此在dll的基礎上發明了COM技術,更好的解決了一系列問題。

          最簡單的dll

          開始寫dll之前,你需要一個c/c++編譯器和鏈接器,并關閉你的IDE。是的,把你的VCC++ BUILDER之類的東東都關掉,并打開你以往只用來記電話的記事本程序。不這樣做的話,你可能一輩子也不明白dll的真諦。我使用了VC自帶的cl編譯器和link鏈接器,它們一般都在vcbin目錄下。(若你沒有在安裝vc的時候選擇注冊環境變量,那么就立刻將它們的路徑加入path吧)如果你還是因為離開了IDE而害怕到哭泣的話,你可以關閉這個頁面并繼續去看《VC++技術內幕》之類無聊的書了。

          最簡單的dll并不比chelloworld難,只要一個DllMain函數即可,包含objbase.h頭文件(支持COM技術的一個頭文件)。若你覺得這個頭文件名字難記,那么用windows.H也可以。源代碼如下:dll_nolib.cpp

          #include <objbase.h>

          #include <iostream.h>

          BOOL APIENTRY DllMain(HANDLE hModule, DWORD dwReason, void* lpReserved)

          {

              HANDLE g_hModule;

              switch(dwReason)

              {

              case DLL_PROCESS_ATTACH:

                 cout<<"Dll is attached!"<<endl;

                 g_hModule = (HINSTANCE)hModule;

                 break;

              case DLL_PROCESS_DETACH:

                 cout<<"Dll is detached!"<<endl;

                 g_hModule=NULL;

                 break;

              }

              return true;

          }

          其中DllMain是每個dll的入口函數,如同cmain函數一樣。DllMain帶有三個參數,hModule表示本dll的實例句柄(聽不懂就不理它,寫過windows程序的自然懂),dwReason表示dll當前所處的狀態,例如DLL_PROCESS_ATTACH表示dll剛剛被加載到一個進程中,DLL_PROCESS_DETACH表示dll剛剛從一個進程中卸載。當然還有表示加載到線程中和從線程中卸載的狀態,這里省略。最后一個參數是一個保留參數(目前和dll的一些狀態相關,但是很少使用)。

          從上面的程序可以看出,當dll被加載到一個進程中時,dll打印"Dll is attached!"語句;當dll從進程中卸載時,打印"Dll is detached!"語句。

          編譯dll需要以下兩條命令:

          cl /c dll_nolib.cpp

          這條命令會將cpp編譯為obj文件,若不使用/c參數則cl還會試圖繼續將obj鏈接為exe,但是這里是一個dll,沒有main函數,因此會報錯。不要緊,繼續使用鏈接命令。

          Link /dll dll_nolib.obj

          這條命令會生成dll_nolib.dll

          注意,因為編譯命令比較簡單,所以本文不討論nmake,有興趣的可以使用nmake,或者寫個bat批處理來編譯鏈接dll

          加載DLL(顯式調用)

          使用dll大體上有兩種方式,顯式調用和隱式調用。這里首先介紹顯式調用。編寫一個客戶端程序:dll_nolib_client.cpp

          #include <windows.h>

          #include <iostream.h>

          int main(void)

          {

              //加載我們的dll

              HINSTANCE hinst=::LoadLibrary("dll_nolib.dll"); 

              if (NULL != hinst)

              {

                 cout<<"dll loaded!"<<endl;

              }

              return 0;

          }

          注意,調用dll使用LoadLibrary函數,它的參數就是dll的路徑和名稱,返回值是dll的句柄。 使用如下命令編譯鏈接客戶端:

          Cl dll_nolib_client.cpp

          并執行dll_nolib_client.exe,得到如下結果:

          Dll is attached!

          dll loaded!

          Dll is detached!

          以上結果表明dll已經被客戶端加載過。但是這樣僅僅能夠將dll加載到內存,不能找到dll中的函數。

          使用dumpbin命令查看DLL中的函數

          Dumpbin命令可以查看一個dll中的輸出函數符號名,鍵入如下命令:

          Dumpbin –exports dll_nolib.dll

          通過查看,發現dll_nolib.dll并沒有輸出任何函數。

          如何在dll中定義輸出函數

          總體來說有兩種方法,一種是添加一個def定義文件,在此文件中定義dll中要輸出的函數;第二種是在源代碼中待輸出的函數前加上__declspec(dllexport)關鍵字。

          Def文件

          首先寫一個帶有輸出函數的dll,源代碼如下:dll_def.cpp

          #include <objbase.h>

          #include <iostream.h>

          void FuncInDll (void)

          {

              cout<<"FuncInDll is called!"<<endl;

          }

          BOOL APIENTRY DllMain(HANDLE hModule, DWORD dwReason, void* lpReserved)

          {

              HANDLE g_hModule;

              switch(dwReason)

              {

              case DLL_PROCESS_ATTACH:

                 g_hModule = (HINSTANCE)hModule;

                 break;

              case DLL_PROCESS_DETACH:

                  g_hModule=NULL;

                  break;

              }

              return TRUE;

          }

          這個dlldef文件如下:dll_def.def

          ;

          ; dll_def module-definition file

          ;

          LIBRARY         dll_def.dll

          DESCRIPTION     '(c)2007-2009 Wang Xuebin'

          EXPORTS

                          FuncInDll @1 PRIVATE

          你會發現def的語法很簡單,首先是LIBRARY關鍵字,指定dll的名字;然后一個可選的關鍵字DESCRIPTION,后面寫上版權等信息(不寫也可以);最后是EXPORTS關鍵字,后面寫上dll中所有要輸出的函數名或變量名,然后接上@以及依次編號的數字(從1N),最后接上修飾符。

          用如下命令編譯鏈接帶有def文件的dll

          Cl /c dll_def.cpp

          Link /dll dll_def.obj /def:dll_def.def

          再調用dumpbin查看生成的dll_def.dll

          Dumpbin –exports dll_def.dll

          得到如下結果:

          Dump of file dll_def.dll

          File Type: DLL

           Section contains the following exports for dll_def.dll

                     0 characteristics

              46E4EE98 time date stamp Mon Sep 10 15:13:28 2007

                  0.00 version

                     1 ordinal base

                     1 number of functions

                     1 number of names

              ordinal hint RVA      name

                    1    0 00001000 FuncInDll

           Summary

                  2000 .data

                  1000 .rdata

                  1000 .reloc

                  6000 .text

          觀察這一行

                    1    0 00001000 FuncInDll

          會發現該dll輸出了函數FuncInDll

          顯式調用DLL中的函數

          寫一個dll_def.dll的客戶端程序:dll_def_client.cpp

          #include <windows.h>

          #include <iostream.h>

          int main(void)

          {

              //定義一個函數指針

              typedef void (* DLLWITHLIB )(void); 

              //定義一個函數指針變量

              DLLWITHLIB pfFuncInDll = NULL; 

              //加載我們的dll

              HINSTANCE hinst=::LoadLibrary("dll_def.dll"); 

              if (NULL != hinst)

              {

                 cout<<"dll loaded!"<<endl;

              }

              //找到dllFuncInDll函數

              pfFuncInDll = (DLLWITHLIB)GetProcAddress(hinst, "FuncInDll"); 

              //調用dll里的函數

              if (NULL != pfFuncInDll)

              {

                 (*pfFuncInDll)();  

              }

              return 0;

          }

          有兩個地方值得注意,第一是函數指針的定義和使用,不懂的隨便找本c++書看看;第二是GetProcAddress的使用,這個API是用來查找dll中的函數地址的,第一個參數是DLL的句柄,即LoadLibrary返回的句柄,第二個參數是dll中的函數名稱,即dumpbin中輸出的函數名(注意,這里的函數名稱指的是編譯后的函數名,不一定等于dll源代碼中的函數名)。

          編譯鏈接這個客戶端程序,并執行會得到:

          dll loaded!

          FuncInDll is called!

          這表明客戶端成功調用了dll中的函數FuncInDll

          __declspec(dllexport)

          為每個dlldef顯得很繁雜,目前def使用已經比較少了,更多的是使用__declspec(dllexport)在源代碼中定義dll的輸出函數。

          Dll寫法同上,去掉def文件,并在每個要輸出的函數前面加上聲明__declspec(dllexport),例如:

          __declspec(dllexport) void FuncInDll (void)

          這里提供一個dll源程序dll_withlib.cpp,然后編譯鏈接。鏈接時不需要指定/DEF:參數,直接加/DLL參數即可,

          Cl /c dll_withlib.cpp

          Link /dll dll_withlib.obj

          然后使用dumpbin命令查看,得到:

          1    0 00001000 ?FuncInDll@@YAXXZ

          可知編譯后的函數名為?FuncInDll@@YAXXZ,而并不是FuncInDll,這是因為c++編譯器基于函數重載的考慮,會更改函數名,這樣使用顯式調用的時候,也必須使用這個更改后的函數名,這顯然給客戶帶來麻煩。為了避免這種現象,可以使用extern “C”指令來命令c++編譯器以c編譯器的方式來命名該函數。修改后的函數聲明為:

          extern "C" __declspec(dllexport) void FuncInDll (void)

          dumpbin命令結果:

          1    0 00001000 FuncInDll

          這樣,顯式調用時只需查找函數名為FuncInDll的函數即可成功。

          extern “C”

          使用extern “C”關鍵字實際上相當于一個編譯器的開關,它可以將c++語言的函數編譯為c語言的函數名稱。即保持編譯后的函數符號名等于源代碼中的函數名稱。

          隱式調用DLL

          顯式調用顯得非常復雜,每次都要LoadLibrary,并且每個函數都必須使用GetProcAddress來得到函數指針,這對于大量使用dll函數的客戶是一種困擾。而隱式調用能夠像使用c函數庫一樣使用dll中的函數,非常方便快捷。

          下面是一個隱式調用的例子:dll包含兩個文件dll_withlibAndH.cppdll_withlibAndH.h

          代碼如下:dll_withlibAndH.h

          extern "C" __declspec(dllexport) void FuncInDll (void);

          dll_withlibAndH.cpp

          #include <objbase.h>

          #include <iostream.h>

          #include "dll_withLibAndH.h"http://看到沒有,這就是我們增加的頭文件

          extern "C" __declspec(dllexport) void FuncInDll (void)

          {

              cout<<"FuncInDll is called!"<<endl;

          }

          BOOL APIENTRY DllMain(HANDLE hModule, DWORD dwReason, void* lpReserved)

          {

              HANDLE g_hModule;

              switch(dwReason)

              {

              case DLL_PROCESS_ATTACH:

                 g_hModule = (HINSTANCE)hModule;

                 break;

              case DLL_PROCESS_DETACH:

                  g_hModule=NULL;

                  break;

              }

              return TRUE;

          }

          編譯鏈接命令:

          Cl /c dll_withlibAndH.cpp

          Link /dll dll_withlibAndH.obj

          在進行隱式調用的時候需要在客戶端引入頭文件,并在鏈接時指明dll對應的lib文件(dll只要有函數輸出,則鏈接的時候會產生一個與dll同名的lib文件)位置和名稱。然后如同調用api函數庫中的函數一樣調用dll中的函數,不需要顯式的LoadLibraryGetProcAddress。使用最為方便。客戶端代碼如下:dll_withlibAndH_client.cpp

          #include "dll_withLibAndH.h"

          //注意路徑,加載 dll的另一種方法是 Project | setting | link 設置里

          #pragma comment(lib,"dll_withLibAndH.lib")

          int main(void)

          {

              FuncInDll();//只要這樣我們就可以調用dll里的函數了

              return 0;

          }

          __declspec(dllexport)__declspec(dllimport)配對使用

          上面一種隱式調用的方法很不錯,但是在調用DLL中的對象和重載函數時會出現問題。因為使用extern “C”修飾了輸出函數,因此重載函數肯定是會出問題的,因為它們都將被編譯為同一個輸出符號串(c語言是不支持重載的)。

          事實上不使用extern “C”是可行的,這時函數會被編譯為c++符號串,例如(?FuncInDll@@YAXH@Z ?FuncInDll@@YAXXZ),當客戶端也是c++時,也能正確的隱式調用。

          這時要考慮一個情況:若DLL1.CPP是源,DLL2.CPP使用了DLL1中的函數,但同時DLL2也是一個DLL,也要輸出一些函數供Client.CPP使用。那么在DLL2中如何聲明所有的函數,其中包含了從DLL1中引入的函數,還包括自己要輸出的函數。這個時候就需要同時使用__declspec(dllexport)__declspec(dllimport)了。前者用來修飾本dll中的輸出函數,后者用來修飾從其它dll中引入的函數。

          所有的源代碼包括DLL1.HDLL1.CPPDLL2.HDLL2.CPPClient.cpp。源代碼可以在下載的包中找到。你可以編譯鏈接并運行試試。

          值得關注的是DLL1DLL2中都使用的一個編碼方法,見DLL2.H

          #ifdef DLL_DLL2_EXPORTS

          #define DLL_DLL2_API __declspec(dllexport)

          #else

          #define DLL_DLL2_API __declspec(dllimport)

          #endif

          DLL_DLL2_API void FuncInDll2(void);

          DLL_DLL2_API void FuncInDll2(int);

          在頭文件中以這種方式定義宏DLL_DLL2_EXPORTSDLL_DLL2_API,可以確保DLL端的函數用__declspec(dllexport)修飾,而客戶端的函數用__declspec(dllimport)修飾。當然,記得在編譯dll時加上參數/D “DLL_DLL2_EXPORTS”,或者干脆就在dllcpp文件第一行加上#define DLL_DLL2_EXPORTS

          VC生成的代碼也是這樣的!事實證明,我是抄襲它的,hoho

          DLL中的全局變量和對象

          解決了重載函數的問題,那么dll中的全局變量和對象都不是問題了,只是有一點語法需要注意。如源代碼所示:dll_object.h

          #ifdef DLL_OBJECT_EXPORTS

          #define DLL_OBJECT_API __declspec(dllexport)

          #else

          #define DLL_OBJECT_API __declspec(dllimport)

          #endif

          DLL_OBJECT_API void FuncInDll(void);

          extern DLL_OBJECT_API int g_nDll;

          class DLL_OBJECT_API CDll_Object {

          public:

              CDll_Object(void);

              show(void);

              // TODO: add your methods here.

          };

          Cpp文件dll_object.cpp如下:

          #define DLL_OBJECT_EXPORTS

          #include <objbase.h>

          #include <iostream.h>

          #include "dll_object.h"

          DLL_OBJECT_API void FuncInDll(void)

          {

              cout<<"FuncInDll is called!"<<endl;

          }

          DLL_OBJECT_API int g_nDll = 9;

          CDll_Object::CDll_Object()

          {

              cout<<"ctor of CDll_Object"<<endl;

          }

          CDll_Object::show()

          {

              cout<<"function show in class CDll_Object"<<endl;

          }

          BOOL APIENTRY DllMain(HANDLE hModule, DWORD dwReason, void* lpReserved)

          {

              HANDLE g_hModule;

              switch(dwReason)

              {

              case DLL_PROCESS_ATTACH:

                 g_hModule = (HINSTANCE)hModule;

                 break;

              case DLL_PROCESS_DETACH:

                  g_hModule=NULL;

                  break;

              }

              return TRUE;

          }

          編譯鏈接完后Dumpbin一下,可以看到輸出了5個符號:

          1    0 00001040 ??0CDll_Object@@QAE@XZ

           2    1 00001000 ??4CDll_Object@@QAEAAV0@ABV0@@Z

           3    2 00001020 ?FuncInDll@@YAXXZ

           4    3 00008040 ?g_nDll@@3HA

           5    4 00001069 ?show@CDll_Object@@QAEHXZ

          它們分別代表類CDll_Object,類的構造函數,FuncInDll函數,全局變量g_nDll和類的成員函數show。下面是客戶端代碼:dll_object_client.cpp

          #include "dll_object.h"

          #include <iostream.h>

          //注意路徑,加載 dll的另一種方法是 Project | setting | link 設置里

          #pragma comment(lib,"dll_object.lib")

          int main(void)

          {

              cout<<"call dll"<<endl;

              cout<<"call function in dll"<<endl;

              FuncInDll();//只要這樣我們就可以調用dll里的函數了

              cout<<"global var in dll g_nDll ="<<g_nDll<<endl;

              cout<<"call member function of class CDll_Object in dll"<<endl;

              CDll_Object obj;

              obj.show();

              return 0;

          }

          運行這個客戶端可以看到:

          call dll

          call function in dll

          FuncInDll is called!

          global var in dll g_nDll =9

          call member function of class CDll_Object in dll

          ctor of CDll_Object

          function show in class CDll_Object

          可知,在客戶端成功的訪問了dll中的全局變量,并創建了dll中定義的C++對象,還調用了該對象的成員函數。

          中間的小結

          牢記一點,說到底,DLL是對應C語言的動態鏈接技術,在輸出C函數和變量時顯得方便快捷;而在輸出C++類、函數時需要通過各種手段,而且也并沒有完美的解決方案,除非客戶端也是c++

          記住,只有COM是對應C++語言的技術。

          下面開始對各各問題一一小結。

          顯式調用和隱式調用

          何時使用顯式調用?何時使用隱式調用?我認為,只有一個時候使用顯式調用是合理的,就是當客戶端不是C/C++的時候。這時是無法隱式調用的。例如用VB調用C++寫的dll。(VB我不會,所以沒有例子)

          Def__declspec(dllexport)

          其實def的功能相當于extern “C” __declspec(dllexport),所以它也僅能處理C函數,而不能處理重載函數。而__declspec(dllexport)__declspec(dllimport)配合使用能夠適應任何情況,因此__declspec(dllexport)是更為先進的方法。所以,目前普遍的看法是不使用def文件,我也同意這個看法。

          從其它語言調用DLL

          從其它編程語言中調用DLL,有兩個最大的問題,第一個就是函數符號的問題,前面已經多次提過了。這里有個兩難選擇,若使用extern “C”,則函數名稱保持不變,調用較方便,但是不支持函數重載等一系列c++功能;若不使用extern “C”,則調用前要查看編譯后的符號,非常不方便。

          第二個問題就是函數調用壓棧順序的問題,即__cdecl__stdcall的問題。__cdecl是常規的C/C++調用約定,這種調用約定下,函數調用后棧的清理工作是由調用者完成的。__stdcall是標準的調用約定,即這些函數將在返回到調用者之前將參數從棧中刪除。

          這兩個問題DLL都不能很好的解決,只能說湊合著用。但是在COM中,都得到了完美的解決。所以,要在Windows平臺實現語言無關性,還是只有使用COM中間件。

          總而言之,除非客戶端也使用C++,否則dll是不便于支持函數重載、類等c++特性的。DLLc函數的支持很好,我想這也是為什么windows的函數庫使用Cdll實現的理由之一。

          VC中編寫DLL

          VC中創建、編譯、鏈接dll是非常方便的,點擊fileàNewàProjectàWin32 Dynamic-Link Library,輸入dll名稱dll_InVC然后點擊確定。然后選擇A DLL that export some symbols,點擊Finish。即可得到一個完整的DLL

          仔細觀察其源代碼,是不是有很多地方似曾相識啊,哈哈!

          最后

          貼上女兒近照一張,小家伙長得太快了!

          評論共2頁: 1 2 下一頁 

          評論

          # re: DLL編寫教程[未登錄]  回復  更多評論   

          2007-12-10 14:09 by zz
          很好.拜一下
          已轉到我博客,已注明作者與原文鏈接

          # re: DLL編寫教程  回復  更多評論   

          2007-12-11 12:58 by wxb_nudt
          @zz
          好的,謝謝!

          # re: DLL編寫教程  回復  更多評論   

          2007-12-11 21:54 by 蘇三
          恩 ,寫的很好。期待。

          # re: DLL編寫教程  回復  更多評論   

          2007-12-14 12:30 by dAYu
          非常好,謝謝!

          # re: DLL編寫教程  回復  更多評論   

          2007-12-19 01:02 by xx
          很有啟發,拜讀了,謝謝

          # re: DLL編寫教程  回復  更多評論   

          2007-12-21 11:40 by jjlsky
          非常感謝
          讓我對dll的編制過程有所理解
          有待實踐
          呵呵

          # re: DLL編寫教程  回復  更多評論   

          2007-12-27 10:53 by 1211
          我靠,寫的太好了,比一些垃圾書上面寫得好多了

          # re: DLL編寫教程  回復  更多評論   

          2008-01-11 17:04 by hitma
          走來又飄走。

          # re: DLL編寫教程  回復  更多評論   

          2008-01-31 02:56 by samwon
          四個字:豁然開朗!

          # re: DLL編寫教程  回復  更多評論   

          2008-02-13 19:04 by
          內容很好 但是.....能否換個歌 第一次打開我還以為電腦又中毒了 嚇死我了

          # re: DLL編寫教程  回復  更多評論   

          2008-02-23 14:20 by wenjiahe
          從Google搜到你這片文章,寫的太好了。
          加入收藏夾了,希望盡快看到你關于com技術的高論。

          # re: DLL編寫教程  回復  更多評論   

          2008-03-10 20:43 by jef
          樓主在國防科大上學和工作的,博士學歷

          # re: DLL編寫教程[未登錄]  回復  更多評論   

          2008-03-13 11:16 by wangcheng
          雖然有這么多人說寫得好,但我還是得說:"真得寫的非常好!!"

          # re: DLL編寫教程  回復  更多評論   

          2008-03-19 10:30 by deadjn
          玩得夠透了,佩服!

          # re: DLL編寫教程  回復  更多評論   

          2008-03-20 14:39 by kris
          寫得太好了,我查了很多資料,這篇文章寫得既有條理,有清晰,果然是大作啊

          # re: DLL編寫教程  回復  更多評論   

          2008-04-02 08:28 by Ulti
          呵呵,文美,照片也美

          # re: DLL編寫教程  回復  更多評論   

          2008-04-08 13:11 by 王俊華
          寫的非常好!謝謝!

          # re: DLL編寫教程  回復  更多評論   

          2008-04-08 16:30 by 白狐
          Thanks !

          # re: DLL編寫教程  回復  更多評論   

          2008-04-13 22:27 by ziffwong
          清晰明了,非常不錯。3x!

          # re: DLL編寫教程  回復  更多評論   

          2008-04-14 00:16 by 陳帥
          十分感謝。。。

          # re: DLL編寫教程  回復  更多評論   

          2008-04-17 15:14 by Alexander
          博主寫得好!最后的方法是不是把所有DLL中的全局符號都輸出了?

          # 求教  回復  更多評論   

          2008-04-20 15:37 by 逍遙郁悶
          現在在網上查資料的時候很郁悶,最近想寫一個能傳入和傳入字符串的DLL,可是我發現網上那個有關DLL編程的帖子全用int來舉例,有沒有那位大哥來一個string,CString,String之類的,哪怕你傳入和傳出數組也行。。。。。郁悶。
          這位大哥你能不能在抽點時間寫一個能在電腦上注冊的DLL,用你說的這些方法寫的DLL都無法注冊,不能注冊使用的時候非常不方便。

          # re: DLL編寫教程  回復  更多評論   

          2008-05-04 18:02 by wycoo
          謝謝啊

          # re: DLL編寫教程  回復  更多評論   

          2008-05-28 21:54 by pzy123cn
          現在在網上查資料的時候很郁悶,最近想寫一個能傳入和傳入字符串的DLL,可是我發現網上那個有關DLL編程的帖子全用int來舉例,有沒有那位大哥來一個string,CString,String之類的,哪怕你傳入和傳出數組也行。。。。。郁悶。
          這位大哥你能不能在抽點時間寫一個能在電腦上注冊的DLL,用你說的這些方法寫的DLL都無法注冊,不能注冊使用的時候非常不方便。


          我前幾天也遇到了這個問題 , 我的解決方法是用指針

          在.h文件中定義

          extern "C" void __declspec(dllexport) SetTestS(char * s);
          extern "C" __declspec(dllexport) char * GetTestS();

          在cpp中:

          char * tests= 0; // 全局變量
          char * GetTestS()
          {
          //獲得tests的值
          return tests ;
          }
          void SetTestS(char * s)
          {
          //設置tests
          tests = s ;
          }

          # re: DLL編寫教程  回復  更多評論   

          2008-06-18 17:45 by zache
          不是所有的DLL都能注冊的,能注冊是DLL要實現DllRegisterServer函數
          RegSvr32只是調用該函數而已。你說的恐怕是COM了,那又是個大課題

          # re: DLL編寫教程[未登錄]  回復  更多評論   

          2008-07-16 17:34 by oo
          謝謝樓主啊

          # re: DLL編寫教程[未登錄]  回復  更多評論   

          2008-07-21 11:45 by oo
          受益匪淺啊!

          # re: DLL編寫教程  回復  更多評論   

          2008-07-25 13:54 by daodao
          不是很懂,但感覺寫的不錯!
          謝謝樓主!你的女兒看起來很聰明.

          # re: DLL編寫教程  回復  更多評論   

          2008-07-29 14:54 by mangshe0
          好!寫的太好了!謝謝樓主,我看了一下午,學到了很多東西。真的感謝您.

          # re: DLL編寫教程  回復  更多評論   

          2008-07-29 15:56 by jiejie
          十分感激

          # re: DLL編寫教程  回復  更多評論   

          2008-08-22 10:40 by YMM
          真是好文啊。這個才是偶需要的,好文!

          # re: DLL編寫教程  回復  更多評論   

          2008-09-02 16:45 by huhusu
          很好的文章 謝謝!

          # re: DLL編寫教程  回復  更多評論   

          2008-09-12 15:37 by piit
          再怎么感謝你也無法表達我對你的感激之情啊,祝你全家幸福!

          # re: DLL編寫教程  回復  更多評論   

          2008-09-20 22:33 by 小松
          寫的漂亮,小姑娘更漂亮

          # re: DLL編寫教程[未登錄]  回復  更多評論   

          2008-11-17 11:07 by joe
          很好的文章 謝謝!

          # re: DLL編寫教程  回復  更多評論   

          2008-12-15 13:20 by 編程愛好者
          感謝樓主的無私奉獻!

          # re: DLL編寫教程  回復  更多評論   

          2008-12-25 10:52 by lianyi
          盡管該說的別人都說了,可是我還是忍不住要說一句:寫得實在太好了!我太佩服你了!我將你的博客珍藏了,以后努力向你學習!

          # re: DLL編寫教程  回復  更多評論   

          2008-12-30 22:18 by lyl0719
          真的不錯,謝謝你。

          # re: DLL編寫教程[未登錄]  回復  更多評論   

          2009-01-06 12:26 by h
          怎一個強字了得………………

          # re: DLL編寫教程  回復  更多評論   

          2009-02-09 20:29 by 胡致璘
          寫得太好了。
          我曾花了近一個星期的時間去找有關DLL編程的資料。找到了一堆資料,亂七八糟的,今看了你的文章之后我對DLL編程豁然開朗

          # re: DLL編寫教程  回復  更多評論   

          2009-02-16 20:12 by 123
          這里好像是武漢的中山公園呀
          1

          # re: DLL編寫教程[未登錄]  回復  更多評論   

          2009-02-17 22:02 by wxb_nudt
          @123
          錯了,是北京動物園啊!

          # re: DLL編寫教程  回復  更多評論   

          2009-02-26 10:28 by kook@21cn.com
          樓上的文章寫的太好了,該贊的大家都已贊完。
          我給你發了封EMAIL,沒等到你的回復,大概意思在這里說一下,有一個DLL,沒有原文件,只有.h和.lib文件,實現功能有:socket通信,最重要是實現了一個通用的打包解包功能,其他功能還有指定線程數,短聯接長聯接,滑動窗口控制,UDP,回調函數等,其性能非常卓越,公司每日幾千萬的吞吐量。我學著重寫了一遍,源碼沒勇氣拿出手,只有樓主這水平的重寫一遍才行,在博客上發出來供大家學習,保證是一篇非常好的博文。
          頭文件怎么給你?
          歡迎有樓主這水平的人參與,kook@21cn.com 聯系。

          說不寫我家小子可以和樓主千金訂個娃娃親,haha。照片如下:
          http://photo.163.com/photo/youless1/#m=1&ai=27240730&p=1&n=60&cp=1

          # re: DLL編寫教程  回復  更多評論   

          2009-04-22 16:37 by 11
          非常感謝,比一些破書上的好多了!

          # re: DLL編寫教程  回復  更多評論   

          2009-04-22 16:37 by 11
          非常感謝,比一些破書上的好多了!

          # re: DLL編寫教程  回復  更多評論   

          2009-06-14 15:44 by 零魂
          寫的太好了,雖然看到該贊的大家都已經贊完了,不過我還是忍不住要頂一下。
          我心中的很多疑惑基本在你這一篇文章里面全給解答了....

          # re: DLL編寫教程  回復  更多評論   

          2009-06-27 20:14 by WwcMonkey
          呵呵,很樸實、實用的入門文章
          總算開了個頭, 謝了!

          期待更多大作

          # re: DLL編寫教程  回復  更多評論   

          2009-07-23 00:11 by Master Wei
          好不容易找到這篇文章的原始地址
          特趕來道謝
          教程寫得太好了

          # 怎么編譯?  回復  更多評論   

          2009-09-02 21:55 by dll
          怎么弄?是在命令行里面寫命令,還是什么?

          # re: DLL編寫教程  回復  更多評論   

          2010-02-21 14:48 by 慢步者
          支持好文!

          # re: DLL編寫教程[未登錄]  回復  更多評論   

          2010-02-23 22:20 by 蕭何
          我感動的淚流滿面,謝謝博主

          # re: DLL編寫教程  回復  更多評論   

          2010-02-26 13:33 by 水辰
          特來登門道謝!文章不是一般的好

          # re: DLL編寫教程[未登錄]  回復  更多評論   

          2010-02-26 14:08 by wxb_nudt
          @蕭何
          內牛滿面夸張了點吧,哈哈,大家新年好。

          # re: DLL編寫教程  回復  更多評論   

          2010-03-18 16:42 by lizhi
          寫了那么多年的程序,還搞不大清楚,真的汗顏,樓主寫的明了清晰

          # re: DLL編寫教程  回復  更多評論   

          2010-04-20 10:39 by epinszteinic
          兩個字:NB!!!!
          寫得真是太好了!!!!
          感激之情猶如滔滔江水!!!!
          趕緊存下來!!!!

          # re: DLL編寫教程  回復  更多評論   

          2010-07-26 14:16 by zz_yun
          博主事業有成,生活幸福啊!

          # re: DLL編寫教程  回復  更多評論   

          2010-08-26 15:56 by shirui
          太感謝樓主了,寫得太好了,可為什么我下載源代碼的時候沒速度呢,嗚嗚~~~~(>_<)~~~~ ,能不能把源代碼發到我郵箱一份,我的郵箱地址是shiruiyiruo@msn.cn
          非常感謝

          # re: DLL編寫教程  回復  更多評論   

          2010-09-20 14:48 by 柯南
          感謝樓主的教程

          # re: DLL編寫教程  回復  更多評論   

          2010-12-04 00:42 by 感謝祖國
          看完樓主的教程。。解開了我以前很多的疑惑。。樓主可否推薦幾本書,多想。

          # re: DLL編寫教程  回復  更多評論   

          2011-01-01 13:28 by kingbird
          好,比那些以上來就教我用IDE寫DLL的強多了,他們以為會用就好,可是我怎么也不能理解,我覺得編程人員向成為高手,就要從最樸實開始。。。。遠離IDE,成就高手。

          # re: DLL編寫教程[未登錄]  回復  更多評論   

          2011-01-04 16:37 by
          祝樓主新年快樂,呵呵,小女越來越漂亮

          # re: DLL編寫教程  回復  更多評論   

          2011-01-06 10:33 by turtle_2
          大牛啊,講的很清楚,謝謝。

          # re: DLL編寫教程  回復  更多評論   

          2011-01-17 08:21 by micRabbit
          寫的很霸氣

          # re: DLL編寫教程  回復  更多評論   

          2011-02-26 21:12 by 過路螞蟻
          寫的真好,兼備才氣和邏輯,難得

          # re: DLL編寫教程  回復  更多評論   

          2011-03-01 14:52 by Cathy
          謝謝博主,這篇文章對我幫助很大,所以很想把它分享給更多人。
          轉發后博客中已注明作者和出處。

          # re: DLL編寫教程  回復  更多評論   

          2011-04-02 18:02 by 王朋
          贊一個

          # re: DLL編寫教程[未登錄]  回復  更多評論   

          2011-04-03 20:08 by RYAN
          感謝博主!

          # re: DLL編寫教程  回復  更多評論   

          2011-05-20 12:56 by jj

          # re: DLL編寫教程  回復  更多評論   

          2011-05-20 12:57 by jj
          頂weqw

          # re: DLL編寫教程  回復  更多評論   

          2011-05-30 12:09 by 踏血無痕
          令人敬佩的文章,謝謝了

          # re: DLL編寫教程  回復  更多評論   

          2011-06-03 01:00 by 陳水文
          qq 1300510038 很想跟你學習

          # re: DLL編寫教程  回復  更多評論   

          2011-06-21 11:19 by 楊元
          我是想在VB中調用Dll,必須要用C寫才可以,看了您的文章,很好!
          而且感覺C語言比VB方便很多

          # re: DLL編寫教程  回復  更多評論   

          2011-07-20 11:00 by 無語紫玉
          看完了~~獲益匪淺啊~~

          # re: DLL編寫教程  回復  更多評論   

          2011-09-07 19:09 by fan
          小小的入門了

          # re: DLL編寫教程  回復  更多評論   

          2012-02-23 22:55 by DllMain
          寫的很詳細,支持一下

          # re: DLL編寫教程  回復  更多評論   

          2012-02-24 14:16 by 團團
          感謝樓主,寫的很詳細!
          總算是入門了,呵呵

          # 寫的很好  回復  更多評論   

          2012-02-26 19:08 by DLL大全
          寫的很好,支持一下

          # re: DLL編寫教程  回復  更多評論   

          2012-03-03 22:21 by Alex.Wu
          非常好的教程,起碼我是在這里搞懂如何編寫dll的。十分感謝

          # re: DLL編寫教程  回復  更多評論   

          2012-03-04 11:49 by c初級程序員
          謝謝樓主,讓我知識面有廣了

          # re: DLL編寫教程[未登錄]  回復  更多評論   

          2012-07-10 22:30 by 飛鳥
          很不錯,一個偶然的機會讓我學會了DLL,哈哈

          # re: DLL編寫教程  回復  更多評論   

          2012-08-14 15:36 by Logger
          獲益良多,可惜沒有介紹類的導出方法。期待樓主繼續完善。

          # re: DLL編寫教程[未登錄]  回復  更多評論   

          2012-10-02 22:01 by lobby
          找了好久,終于找到說的清晰明了的好文章,太好了;學到了很多,謝謝樓主。

          # re: DLL編寫教程[未登錄]  回復  更多評論   

          2012-12-04 12:26 by 123
          教程很清晰,收獲很大,非常感謝!!

          # re: DLL編寫教程[未登錄]  回復  更多評論   

          2013-03-20 16:47 by Andy
          程序媛辛苦了

          # re: DLL編寫教程  回復  更多評論   

          2013-03-27 20:59 by 麥穗兒
          寫得真是太好了!

          # re: DLL編寫教程  回復  更多評論   

          2013-04-13 16:03 by 王海輝
          不得不好,真的是很好。

          # re: DLL編寫教程[未登錄]  回復  更多評論   

          2013-07-23 23:47 by 小輝
          非常棒!!!很清楚~

          # re: DLL編寫教程  回復  更多評論   

          2013-08-15 17:59 by feitian
          剛拜讀完文章,寫得很不錯,受益匪淺,期待更多更好的文章!

          # re: DLL編寫教程  回復  更多評論   

          2013-08-16 13:09 by 沈軍濤
          不錯,學習了

          # re: DLL編寫教程  回復  更多評論   

          2013-09-06 01:46 by Frankie
          實在太感謝了,比書里講的好多了

          # re: DLL編寫教程  回復  更多評論   

          2013-09-14 14:12 by be.truth
          __declspec(dllexport) 導出不了函數,用dumpbin看不到導出函數 用的是vs2008 的CL

          # re: DLL編寫教程  回復  更多評論   

          2013-10-03 16:47 by caotengfei
          厲害,學習了

          # re: DLL編寫教程  回復  更多評論   

          2013-10-20 16:43 by thinkercui
          我忍不住,要感謝樓主,為傳播程序員文化所做出的努力!
          謝謝。

          # re: DLL編寫教程[未登錄]  回復  更多評論   

          2014-02-11 23:12 by
          雖然這么多贊的,但是我還要來贊一下!!

          # re: DLL編寫教程[未登錄]  回復  更多評論   

          2014-03-13 21:56 by 無名
          寫的十分清晰,十分感謝

          # re: DLL編寫教程[未登錄]  回復  更多評論   

          2014-04-10 16:53 by 1234
          膜拜樓主,非常清晰

          # re: DLL編寫教程  回復  更多評論   

          2014-04-16 03:00 by prx
          請教您了:照您的做法,我dll中的h是這樣:
          #define BASE_EXPORTS
          #ifdef BASE_EXPORTS
          #define  BASE_API __declspec(dllexport)
          #else
          #define  BASE_API __declspec(dllimport)
          #endif
          BASE_API BOOL BASIT;
          cpp如下:
          BASE_API BOOL BASIT=FALSE;
          編譯出現:
          D:\VC6\MyProjects\Base\Base.cpp(327) : error C2086: 'BASIT' : redefinition
          請你指點下!

          # re: DLL編寫教程  回復  更多評論   

          2014-08-21 16:52 by liuruoze
          謝謝 很不錯的文章

          # re: DLL編寫教程[未登錄]  回復  更多評論   

          2015-11-11 22:56 by HelloWorld
          樓主好文。我做學習筆記轉走了。么么噠

          # re: DLL編寫教程  回復  更多評論   

          2016-08-10 20:56 by liqiao
          這不就是一天學會,深入淺出……
          :p
          評論共2頁: 1 2 下一頁 
          主站蜘蛛池模板: 同心县| 永宁县| 泾源县| 崇仁县| 布尔津县| 天峻县| 囊谦县| 唐河县| 盘锦市| 潮安县| 宝山区| 延津县| 崇左市| 道孚县| 措勤县| 德江县| 夏河县| 腾冲县| 祥云县| 馆陶县| 高阳县| 寿阳县| 白银市| 澜沧| 县级市| 太康县| 开远市| 台州市| 中西区| 桑植县| 台中市| 习水县| 九台市| 神木县| 丹东市| 遂宁市| 崇信县| 长阳| 昆山市| 绍兴市| 尉氏县|