c++ DLL:包含项目中的类
Posted
技术标签:
【中文标题】c++ DLL:包含项目中的类【英文标题】:c++ DLL: Include classes from project 【发布时间】:2014-08-31 20:11:34 【问题描述】:案例:我正在制作一个应用程序,它应该能够获取某个文件夹中的所有 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 类中删除原始包含,则不再有错误。 我可以毫无问题地将 d3dx9 包含在我的 DLL 中,但前提是它不包含在 Target 类中。 将 d3dx9.h 直接包含在我的 DLL 中会产生与上述完全相同的错误。显然这无济于事,因为我需要在 Target 类以及 DLL 中包含某些类和函数。
我是否正在寻找不同类型的文件而不是模块的 DLL?在使用 DLL 时,我应该记住什么?
如果我忘记添加任何信息,请告诉我,我会尽我所能。 任何帮助将不胜感激。
更新:仅使用 math.h 和 d3dx9.h 将 DLL 剥离到最低限度仍然会给我同样的错误。
// 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;
【问题讨论】:
尝试从它加载的 DLL 调用 EXE 中的函数时会遇到一些有趣的复杂情况,但您的问题要简单得多。在包含其他标头之前,您是否尝试过#include <math.h>
?
是的,我担心这会带来并发症。试着环顾四周,但大多数人都在做完全相反的事情,这更有意义呵呵。我尝试包括 math.h 但不幸的是没有运气。它总是给出同样的错误。
我还发现由于某种原因直接将 d3dx9.h 包含到 DLL 中会产生完全相同的错误。我猜这之前没有发生过,因为项目和 dll 的构建不正确。我已将此信息添加到主帖中。
您是否在任何 directx 内容之前包含了 windows.h?
会尽快尝试。我想知道的是:即使应用程序具有特定的包含,DLL 也必须单独发生包含?以及如何在主应用程序中而不是在 DLL 上加载 DLL 触发错误?我将尝试将 windows.h 包含在 DLL 中,并在可以的时候通知您!
【参考方案1】:
我无法说出您的头文件行为不端的原因,尽管从一个没有预编译头文件且仅包括 <windows.h>
、<math.h>
和 <d3dx9.h>
的最小示例开始,应该会让您顺利上路解决这些问题。
对于如何允许插件 DLL 重用主应用程序的功能这一更大的问题,基本上有三种方法,它们在复杂性和耦合性上有所不同。您可能不想要求所有未来的插件都使用完全相同的编译器构建,是吗(或者在所有插件也准备好同时移动之前,无法将主应用程序移动到新的编译器)。
-
将整个应用程序放入一个 DLL 中,主 EXE 只加载和调用这个应用程序逻辑 DLL。然后插件 DLL 也可以使用 app-logic DLL。
从主应用程序中导出函数并为 EXE 创建一个导入库。
__declspec(dllexport)
也适用于 EXE。需要对构建选项进行一些调整,以告知链接器创建导入库。
不要让插件 DLL 直接调用主应用程序,而是在应用程序加载插件时,将上下文对象指针传递给插件初始化函数。该上下文包含指向插件可能需要的函数的指针。也可以稍后在使用插件函数时提供上下文,而不是在加载/初始化期间提供。
所有这些情况都受益于 COM 程序员熟悉的解耦技术。基本上,API 应该只包含三种类型:
-
原语
普通的旧数据结构。所有数据成员都是非静态和公共的,没有重要的特殊成员函数。
指向接口的指针。接口是只有纯虚函数且没有数据的基类。
关于这些的关键是它们在不同的编译器版本、不同的供应商甚至不同的语言之间具有一致的内存布局。有时您需要#pragma pack
才能获得最终级别的布局控制。
我们从 COM 中学到的另一件事是拥有工厂并让对象通过 Release()
虚拟成员函数释放自己的内存。为了支持类似 shared_ptr 的引用计数,COM 使用 AddRef()
和 Release()
对。这里重要的是,当销毁对象的代码是对象的一部分时,它会自动使用与工厂相同的模块中的内存分配器。
COM 做的一件您不需要的事情是工厂接口。大多数时候,简单的工厂函数就足够了。
【讨论】:
以上是关于c++ DLL:包含项目中的类的主要内容,如果未能解决你的问题,请参考以下文章