2014-08-31 178 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不需要的一件事就是工厂界面。大多数时候,简单的工厂功能都不够好。

相关问题