2014-08-31 175 views
0

案例:我正在創建一個應用程序,該應用程序應該能夠獲取位於特定文件夾中的所有DLL並加載它們。這些DLL充當模塊,應該能夠執行可能發生或可能不發生在主應用程序中的某些任務。C++ DLL:包含來自項目的類

若要允許從我的DLL訪問主應用程序我已將主應用程序的文件夾添加到DLL的其他包含目錄。這可以在我的主應用程序的頭文件中調用#include並使用它的類和函數。

問題:包括那些在主應用程序的頭文件中似乎會導致試圖從這些包含函數中訪問DLL的問題。例如:我的主應用程序中有一個'Target'類。這個類有1包括:

#ifndef D3DX9_INCLUDED 
#define D3DX9_INCLUDED 
#include <d3dx9.h> // Direct3D 9 
#endif 

如果我有Target.h在我的DLL,我得到4級相同的錯誤:

Error 2 error C3861: 'sqrtf': identifier not found c:\program files (x86)\microsoft directx sdk (june 2010)\include\d3dx9math.inl 1585 1 WW 
Error 3 error C3861: 'sqrtf': identifier not found c:\program files (x86)\microsoft directx sdk (june 2010)\include\d3dx9math.inl 1717 1 WW 
Error 4 error C3861: 'sqrtf': identifier not found c:\program files (x86)\microsoft directx sdk (june 2010)\include\d3dx9math.inl 1862 1 WW 
Error 5 error C3861: 'sqrtf': identifier not found c:\program files (x86)\microsoft directx sdk (june 2010)\include\d3dx9math.inl 2032 1 WW 

如果我刪除原來的目標類包括有沒有錯誤了。 我可以在我的DLL中包含d3dx9而不會出現問題,但只有當它不包含在Target類中時纔會如此。 將d3dx9.h直接包含到我的DLL中,給出與上述完全相同的錯誤。很明顯,這並沒有幫助,因爲我需要在Target類以及DLL中包含某些類和函數。

我正在尋找一個不同類型的文件,而不是模塊的DLL?在使用DLL時,有什麼我應該記住的?

如果我忘記添加任何信息,請告訴我,我會盡我所能。 任何幫助將不勝感激。

更新:剝離DLL的最低限度只有math.h和d3dx9.h包括仍給我相同的錯誤。

// dllmain.cpp : Defines the entry point for the DLL application. 
#include "stdafx.h" 
#include <math.h> 
#include <d3dx9.h> // Direct3D 9 


BOOL APIENTRY DllMain(HMODULE hModule, 
         DWORD ul_reason_for_call, 
         LPVOID lpReserved 
        ) 
{ 
    switch (ul_reason_for_call) 
    { 
    case DLL_PROCESS_ATTACH: 
    case DLL_THREAD_ATTACH: 
    case DLL_THREAD_DETACH: 
    case DLL_PROCESS_DETACH: 
     break; 
    } 
    return TRUE; 
} 
+2

嘗試從它加載的DLL中調用EXE函數有一些有趣的複雜性,但是您的問題要簡單得多。你有沒有試過'#包括'提前包括這個其他頭? – 2014-08-31 20:19:55

+0

是的,我擔心這會發生併發症。試圖環顧四周,但大多數人做的是完全相反,這是更有意義的嘿嘿。我試圖包括math.h,但不幸的是沒有運氣。它不斷給出相同的錯誤。 – Tim 2014-08-31 20:40:24

+0

我還發現,由於某種原因,將d3dx9.h直接包含到DLL中會給出完全相同的錯誤。我想這是以前沒有發生的,因爲項目和DLL的構建不正確。我已將此信息添加到主帖子中。 – Tim 2014-08-31 20:46:25

回答

0

我不能給你有行爲不端的頭文件的原因說,雖然從一個小例子開始,沒有預編譯頭,只包括<windows.h><math.h><d3dx9.h>應該讓你用自己的方式解決那些。

對於如何允許插件DLL重用主應用程序的功能這個大問題,基本上有三種方法,它們在複雜性和耦合方面有所不同。您可能不希望所有將來的插件都用完全相同的編譯器構建,您是否(或者直到所有插件都可以同時移動時才能將主應用程序移動到新的編譯器中)。

  1. 把幾乎整個應用程序放到一個DLL中,主EXE只是加載並調用這個應用程序邏輯DLL。然後,插件DLL也可以使用應用程序邏輯DLL。
  2. 從主應用程序導出函數併爲EXE創建導入庫。 __declspec(dllexport)也適用於EXE內部。一些調整構建選項需要告訴鏈接器創建一個導入庫。
  3. 不要讓插件DLL直接調用主應用程序,而是在應用程序加載插件時,它會將上下文對象指針傳遞給插件init函數。該上下文包含指向插件可能需要的函數的指針。上下文也可以在稍後使用插件函數時提供,而不是在加載/ init期間提供。

所有這些情況都受益於COM程序員熟悉的解耦技術。基本上,API應該由只有三種類型:

  1. 基元
  2. 平原舊的數據結構。所有數據成員都是非靜態和公共的,沒有不重要的特殊成員函數。
  3. 指向接口的指針。接口是隻有純虛函數且沒有數據的基類。

關鍵在於它們在不同的編譯器版本,不同的供應商甚至不同的語言中具有一致的內存佈局。有時您需要#pragma pack才能獲得最終的佈局控制級別。

我們從COM學到的另一件事是讓工廠讓對象通過Release()虛擬成員函數釋放自己的內存。爲了支持shared_ptr-like引用計數,COM使用了AddRef()Release()對。這裏最重要的是,當銷燬對象的代碼是對象的一部分時,它會自動使用與工廠相同的模塊中的內存分配器。

COM不需要的一件事就是工廠界面。大多數時候,簡單的工廠功能都不夠好。

相關問題