2009-08-14 99 views
8

使用Visual Studio 2008及其C/C++編譯器,如何創建僅依賴於其他Windows DLL的Win32 DLL,並且不依賴於微軟C運行時?如何在不依賴C運行庫的情況下創建Win32 DLL

我有一些C代碼,我想放在一個完全計算的DLL中,並且幾乎不使用C庫函數。

對於那些使用(例如memcpy)的用戶,我很高興重寫代碼以使用Win32 API等價物(例如CopyMemory)。

+0

CopyMemory不是一個winapi函數,你將不得不自己編寫 – Anders 2009-08-16 01:04:20

+6

不好意思碰到一箇舊的線程,但'CopyMemory'是一個API函數:http://msdn.microsoft.com/en-us/library/ aa366535%28VS.85%29.aspx 除了'#define'd代替調用'memcpy'外。 – Thomas 2009-10-02 17:24:55

回答

10

使用/ NODEFAULTLIB鏈接器選項和(當然)確保您在運行時沒有實際的依賴關係。您還需要指定&使用/ ENTRY鏈接器選項爲DLL定義自己的入口點,或者使用自己的入口點函數來匹配編譯器/鏈接程序所需的名稱(對於dll,即_DllMainCRTStartup)。

從方式馬特·皮特里克的文章後面,當上LIBCTINY可能將所有您需要的信息:

+0

引用那篇文章「幸運的是,我們已經過去了那些日子,在大多數情況下,您可以依靠目標機器上的MSVCRT.DLL。」 Pietrek建議你應該如此依賴。 – 2009-08-14 19:29:39

+0

這是*仍然是真的*?自Windows 2000以來,許多方面都發生了變化。現在我認爲我們不應該依賴MSVCRT。至少它比馬特的聲明表明更復雜。 – Cheeso 2009-08-24 03:27:15

+2

我們可以依賴MSVCRT.dll在機器上,但Visual C++鏈接針對MSVCRver.dll,其中ver是80,90,100,110等。 – BCran 2012-09-11 16:28:07

0

某些Windows庫依賴於C運行庫(例如ODBC32.DLL) 所以我認爲你在這裏隱藏到什麼都沒有。無論如何,你爲什麼要這麼做?

+3

我認爲它公平地假設windows dll的任何依賴關係都會隨窗口一起提供。我沒有看到你的觀點。 – 2009-08-14 18:33:39

+0

如果你的代碼依賴於ODBC32這樣的DLL,那麼它間接依賴於Windows自帶的CRT--你錯誤的印象是它必須分開發布嗎?如果你低估了這個答案,我必須問 - 爲什麼? – 2009-08-14 18:38:03

+0

如果我用微軟C編譯器構建我的代碼,我必須使用它隨附的C運行時,如果我想要他們記錄/支持的行爲。這需要用我的代碼分發所述運行時。 我想我可以'發現'另一個C運行庫在Windows中敲入並以某種方式動態鏈接到它,但是這比我想象的要更加努力,尤其是當我實際上不需要它的任何功能時... – 2009-08-14 19:01:05

0

使用靜態微軟庫進行編譯。

+2

正如此處所述:http://msdn.microsoft.com/en-us/library/abx4dbyh(VS.80).aspx 現代微軟C運行時最好不是靜態鏈接到系統中的其他庫的dll可能正在使用C運行時。 – 2009-08-14 18:36:32

0

你必須確保沒有使用需要使用Win32的DLL C運行時也是如此,否則你回到原點。如果其中一個Win32 DLL依賴於C運行時,靜態編譯您的DLL並不重要。

我可以看到這個工作的唯一方法是靜態鏈接所有您的依賴DLL(如果這是可行的)到您的DLL。這當然意味着您必須重新編譯才能利用任何DLL更新。

5

您可能比您想象的更依賴於CRT。它將線程本地存儲等資源壓縮,全局類初始化程序由main()之前的CRT運行。

正如有人所說,考慮使用靜態CRT進行鏈接,如果您真的不想要,可以像其他人說的那樣使用/ NODEFAULTLIB和/ ENTRY。

哦,而不是重寫memcpy,考慮使用它的超快速compiler intrinsic。您可以使用/ Oi打開內部函數。

+0

我只使用memcpy作爲示例。 – 2009-08-14 18:37:36

+1

就像我一樣。有許多編譯器內在函數。 – 2009-08-14 18:39:18

+0

它是一個好主意,但是他們是否記錄了編譯器的內在函數不依賴於它們自己的C運行時的存在? 我假設我可以檢查編譯器的輸出是否可以,但是這比我想象的更多的工作... – 2009-08-14 18:46:35

4

/NODEFAULTLIB鏈接器標誌實際上並不是正確的標誌。它會忽略所有默認庫,包括其他像uuid.lib

想要的是/Zl編譯器選項,「省略.OBJ中的默認庫名稱」。

4

爲 「調試」 模式試試這個:

  1. 轉到項目\ [項目]屬性...
  2. 打開配置屬性
  3. 打開C/C++
  4. 打開代碼生成
  5. 對於運行時庫選擇多線程調試(/ MTD)代替多線程調試DLL(/ MDd)

對於「釋放」模式,除了在最後一步選擇多線程(/ MT)之外,執行相同的步驟。

這會導致程序中使用的任何C運行時函數都靜態鏈接到您的二進制文件。

+0

那個爲我工作。我不想將依賴關係移除到MSVCRT,而是以某種方式「限制」可能導致「缺失依賴性」錯誤的其他依賴項。 – Matthieu 2016-06-27 13:12:51

相關問題