2009-07-25 61 views
3

我正在編寫一個應用程序,可以通過模塊/共享對象/ DLL在運行時進行擴展。這些模塊可以使用現有程序的API,但也可以提供新的功能以用於稍後加載的模塊,因此模塊可能彼此依賴。在Windows上使用動態鏈接庫的動態模塊

我目前在Linux下的方法是讓每個模塊定義一個depends()函數,該函數返回它依賴的其他模塊名稱的列表。這樣,我可以編譯並鏈接每個模塊,使用dlopen()和RTLD_LAZY加載模塊,首先解決它的依賴關係,然後用RTLD_GLOBAL完全加載它。這工作得很好,正是我想要的。它還允許我使用不同的版本替換模塊,而不用根據它重新編譯所有其他模塊。

將此代碼移植到Windows時出現實際問題。首先,我沒有找到任何連接DLL的方法,但沒有提供它的所有依賴關係的導出符號表。有沒有我忽略過的一個?其次,來自Windows API的LoadLibraryEx似乎無法執行任何延遲加載,因爲它不會讓我處理依賴關係,而是在它返回之前自動加載所有被引用的DLL。因爲我希望在未來實際加載模塊之前進行版本檢查,所以這不是我想要的。有什麼辦法可以規避這種行爲嗎?

第三個奇怪的是,我無法替換一個DLL,而無需重新編譯所有其他模塊,具體取決於它。它有時確實有效,但通常會發生狂野的事情發生或程序段錯誤。

它甚至有可能在Windows上編寫這樣的模塊化應用程序嗎?任何建議或不同的方法,高度讚賞!

更新:只是爲了提供一些關於我的模塊如何在Linux上使用其他功能的一些說明(我希望Windows上也有這些功能):每個模塊只返回想要調用的另一個模塊的名稱函數在所描述的depends()函數中,幷包含它的頭文件,然後直接在代碼中調用使用的函數而不進行任何包裝。這是有效的,因爲Linux不需要您在鏈接時爲共享對象解析所有符號。

回答

4

您可以手動導出所有功能(使用__declspec(dllexport))並使用GetProcAddress加載它們。在這種情況下,您需要知道每個函數的簽名,並且僅限於C函數,但這是行得通的。如果你編譯了這兩個模塊,你的C函數也可以返回C++類,稍後更多。使用GetProcAddress & LoadLibrary使模塊完全獨立。基本上,你手動進行鏈接,但據我所知,這是你在Linux上做的,對吧?

LoadLibary只加載庫依賴的庫,所以請確保它們不加載依賴於對方。要麼他們真的是獨立的,要麼他們不是,如果做得好,改變一個庫不會強制重新編譯另一個(因爲你沒有把它們連接在一起)。

一個好主意是使用像COM這樣的東西,所以讓你的每個庫都返回一個接口,而不是單獨的函數。這樣,您可以簡單地加載一個完整的DLL,並將它們輕鬆地鏈接在一起(傳遞一個DLL - >傳遞一個對象)。查看XPCOM和COM,實際上很容易。

+1

好的,你對`GetProcAddress`的建議已經有所幫助了。我只是試了一下,並調用一個DLL的函數,這種方式工作,而沒有鏈接它。但是這意味着我不能讓模塊在Linux中包含它所依賴的頭文件,對吧?在調用父模塊的任何東西之前,我必須首先用`GetProcAddress`來收集所有需要的函數指針。 也感謝與COM的提示,我會看看。 – smf68 2009-07-25 13:08:41