我目前正在使用C ++(MSVS 2008)创建自己的框架,该框架使用一堆函数导出一个dll,供我的框架用户使用/调用。一开始,当我的项目仍然很小时,一切正常。我编译了我的项目。一个MyFramework.dll和MyFramework.lib吐了出来。我假装是一个用户;将MyFramework.dll文件放在我的新VS项目的Debug文件夹中,将MyFramework.lib和MyFramework.h文件放在我的项目文件夹中,#include -d MyFramework.h在我的代码和voilá中,我可以调用(仍然很简单)框架在我的新项目中起作用。
但现在我扩展了我的框架。它现在使用它自己的外部DLL(让我称之为Graphics.dll)并以相同的方式包含它(Debug文件夹中的.dll,项目文件夹中的.lib / .h,代码中的#include Graphics.h)。
问题在于,当我创建MyFramework.dll / MyFramework.lib,将其包含在我的新项目和构建中时,链接器抱怨无法包含Graphics.h,这显然包含在某处的MyFramework.dll中。
所以我的问题。我希望MyFramework.dll的用户只需要在他们的项目中包含MyFramework。*文件,而不需要复制/粘贴我决定在MyFramework中使用的所有外部库。我怎么能做到这一点?我看了this thread。它说了一些关于添加现有项目并按下“添加”按钮旁边的小箭头的信息,但是......在我的MSVS版本中箭头不存在......
非常感谢帮助。
亲切的问候 W. Spek
答案 0 :(得分:2)
正在发生的事情是用户包含了一个库的头文件。然后该文件包含“graphics.h”。如果您不希望要求您的用户有权访问此文件,则必须将其从库界面中隐藏。
那就是你的库必须有公共api头文件和私有实现头文件。您的用户仅包含公共api头文件,这些文件不包含任何第三方或私有包含文件。当这些文件引用私有类型或第三方类型时,它们只能使用指针或引用,这些是前向声明的。这使得类的私有部分可以使用私有库代码和第三方类型。
使用Pimpl Idiom的可能性会为您解决此问题。
答案 1 :(得分:1)
“问题在于,当我创建MyFramework.dll / MyFramework.lib,将其包含在我的新项目和构建中时,链接器抱怨无法包含Graphics.h,这显然包含在MyFramework.dll中某处“。
您是否已将路径放入头文件?编译器报告头文件与正在转换的cpp文件不在同一目录中,并且未在其他包含目录中列出。
转到Project-> Properties,然后选择C / C ++
您将看到的第一个选项是“其他包含目录”。你需要将路径放在你的标题Graphics.h中,以及所有需要所有分号分隔的其他路径。我在mo开放的项目有,例如:“../ AudioLibrary; ../ CoreLibrary;”
编辑 :从你的评论到Mark的帖子,你说你想在你的DLL中嵌入Graphics.DLL。我的答案如下:
如果您没有Graphics.dll的源代码,那么您就遇到了问题。你问的问题是可能的,但非常复杂。基本上你不能使用LoadLibrary。您将被迫编写自己的LoadLibaray和GetProcAddress,它将查看嵌入式DLL而不是尝试在磁盘上找到它...它可行,但您需要在{{3上进行大量读取}}
答案 2 :(得分:0)
如果您不想要求用户拥有或包含Graphics.h,那么可以使用LoadLibrary
在运行时动态加载Graphics.dll。
这意味着用户可以在没有Graphics.dll可用的情况下针对MyFramework进行编译,因此如果LoadLibrary失败,进行某种错误报告可能是明智的。
在Graphics.dll上成功调用LoadLibrary
后,您需要使用GetProcAddress
手动导入每个函数(及其签名) - 这实际上会为您提供函数指针。如何存储函数指针取决于您;我通常更喜欢围绕导入的函数包装一个类,但没有什么能阻止你将函数指针保留在全局范围内。
<小时/> 如评论中所述,如果您根本不想分发 Graphics.dll,则需要将其作为静态库(即“内置于MyFramework.dll”)。如果您做想要分发Graphics.dll(因此用户可以使用不带MyFramework.dll的Graphics.dll),那么上述方法仍然是更好的选择。实际上,上述方法假设您使用MyFramework.dll分发Graphics.dll,但用户可能不一定有Graphics.h可用。