2012-12-18 13 views
1

背景結束語一個DLL - 理解爲什麼導入失敗

我有它運行原文爲C++和Visual Studio中,這會導致一個可執行文件和30多個DLL文件編譯的應用程序的嵌入式系統。這些庫不能在VS Object Browser或其他工具(如P/Invoke Interop Assistant)中瀏覽。

加載一些在Dependency Walker中的DLL文件的顯示,所有的人都缺少一些依賴深藏在他們的依賴關係樹(cdfview.dlldwmapi.dll文件w32topl.dll,...),但根據this question,很可能不是一個問題。

我有一些的源代碼文件,和所有編譯的DLL。該應用程序目前運行沒有問題,表明沒有真正的依賴性問題。

我試圖調用一些庫函數,最終使使用C#的包裝,但我無法成功導入,並呼籲即使是最簡單的功能。我總是收到以下錯誤:

Unable to load DLL 'dllName.dll': A dynamic link library (DLL) initialization routine failed. (Exception from HRESULT: 0x8007045A)

示例代碼[EDITED]

從C++源代碼的頭文件我有以下聲明:

#define OB_API __declspec(dllexport) __cdecl 

typedef unsigned long DWORD; // From windef.h 
typedef DWORD OBSTATUS; 

OBSTATUS OB_API TestObj(void); 

在C++源碼文件中的以下定義給出了(這似乎總是返回):

BOOL WINAPI DllMain(HANDLE /* hModule */, 
         DWORD ul_reason_for_call, 
         LPVOID /* lpReserved */ 
        ) 
{ 
    switch (ul_reason_for_call) 
    { 
    case DLL_PROCESS_ATTACH: 
    case DLL_PROCESS_DETACH: 
    case DLL_THREAD_ATTACH: 
    case DLL_THREAD_DETACH: 
     break; 
    } 
    return TRUE; 
} 

在我的C#應用​​程序類,我添加了以下聲明:

[DllImport(@"dllName.dll", CallingConvention=CallingConvention.Cdecl) 
public static extern ulong TestObj(); 

的DLL和C#應用程序二進制駐留在同一目錄中。

問題

從研究的錯誤,似乎還有大量的原因,這特定的異常可能會被拋出,我想知道我怎麼能進一步解決此類問題。

有沒有什麼辦法讓爲什麼初始化程序失敗的更多詳細信息?

(注:目標系統運行.NET Framework 2.0)

+0

與加載問題無關,但需要在p/invoke聲明中使用'CallingConvention.Cdecl',以匹配C++端。 –

+0

更新了'CallingConvention' – nicholas

回答

4

正在加載的DLL包含的DllMain()函數。這很常見,這樣的函數會初始化DLL的狀態。窗戶可以確保這個函數被調用每當DLL被加載時,它會自動出現在你第一次的PInvoke由DLL導出的函數。

問題是,該函數返回FALSE表明它無法正確初始化DLL。那當然不會給出關於的全部信息,爲什麼它返回FALSE。 Windows無法執行任何操作,但會生成錯誤1114,ERROR_DLL_INIT_FAILED。如果DLL本身不輸出任何診斷,那麼除了調試代碼之外,你什麼也做不了。從Project + Properties,Debug選項卡開始,勾選「啓用非託管代碼調試」選項。

手指交叉在輸出窗口中看到消息。賠率不是很好。如果您沒有DLL的源代碼,那麼您需要DLL的供應商或作者的幫助。給他一個這樣失敗的測試項目的副本。

+0

因此,init失敗的原因是由於'DLLMain'的返回值?這非常有用。我確實有這個庫的源代碼,包括'DLLMain'的定義,儘管我看不到函數可能返回一個錯誤的值。 – nicholas

+1

如果代碼是用C或C++編寫的,那麼這個間接級別就是間接的,Windows調用的真正的DllMain()是_DllMainCRTStartup()。它初始化CRT並調用初始化器,然後調用DllMain()。初始化器失敗也會導致返回值爲FALSE,通常會看到拋出的異常。 –

+0

有什麼方法可以知道哪些初始化函數被調用? – nicholas