c ++ DLL:包含项目中的类

时间:2014-08-31 20:11:34

标签: c++ dll include

案例:我正在创建一个应该能够获取某个文件夹中的所有DLL并加载它们的应用程序。这些DLL充当模块,应该能够执行在主应用程序中可能发生或可能不发生的某些任务。

为了允许从我的DLL访问主应用程序,我已将主应用程序的文件夹添加到DLL的其他包含目录中。这可以达到我可以在主应用程序的头文件上调用#include并使用它的类和函数的程度。

问题:主应用程序头文件中的包含似乎会导致DLL尝试从这些包中访问函数时出现问题。例如:我的主应用程序中有一个“目标”类。这个班有1个包括:

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

如果我在我的DLL中包含Target.h,我会得到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

如果我从Target类中删除原始包含,则不再存在错误。 我可以在我的DLL中包含d3dx9而没有问题,但只有当它没有包含在Target类中时。将d3dx9.h直接包含在我的DLL中会产生与上面完全相同的错误。显然这没有用,因为我需要包含Target类和DLL中的某些类和函数。

我是在寻找不同类型的文件而不是模块的DLL吗?在处理DLL时,有什么我应该记住的吗?

如果我忘记添加任何信息,请告诉我,我会尽我所能。 任何帮助将不胜感激。

更新:只使用math.h将DLL拆解到最低限度,并且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;
}

1 个答案:

答案 0 :(得分:0)

我无法说明您使用行为不当的头文件的原因,尽管从一个没有预编译头的最小示例开始,只包括<windows.h><math.h>和{ {1}}应该帮助您解决问题。

对于如何允许插件DLL重用主应用程序的功能的更大问题,基本上有三种方法,它们的复杂性和耦合性不同。您可能不希望要求所有未来的插件都使用完全相同的编译器构建,您(或者无法将主应用程序移动到新的编译器,直到所有插件也准备好同时移动)。

  1. 将整个应用程序放入DLL中,主EXE只加载并调用此app逻辑DLL。然后插件DLL也可以使用app-logic DLL。
  2. 从主应用程序导出函数,并为EXE创建导入库。 <d3dx9.h>也在EXE中运行。需要对构建选项进行一些调整,以告知链接器创建导入库。
  3. 不要让插件DLL直接调用主应用程序,而是当应用程序加载插件时,它会将上下文对象指针传递给插件初始化函数。该上下文包含指向插件可能需要的函数的指针。当使用插件函数时,也可以在以后提供上下文,而不是在loading / init期间提供。
  4. 所有这些案例都受益于COM程序员熟悉的解耦技术。基本上,API应该只包含三种类型:

    1. 基元
    2. 普通的旧数据结构。所有数据成员都是非静态和公共的,没有非平凡的特殊成员函数。
    3. 指向接口的指针。接口是基类,只有纯虚函数,没有数据。
    4. 关于这些的关键是它们在不同的编译器版本,不同的供应商甚至不同的语言中具有一致的内存布局。有时您需要__declspec(dllexport)来获得最终的布局控制级别。

      我们从COM中学到的另一件事是拥有工厂并让对象通过#pragma pack虚拟成员函数释放自己的内存。为了支持类似shared_ptr的引用计数,COM使用Release()AddRef()对。这里重要的是,当销毁对象的代码是对象的一部分时,它会自动在与工厂相同的模块中使用内存分配器。

      COM不需要的一件事是工厂界面。大多数情况下,简单的工厂功能都足够好。