2009-10-15 157 views
2

我目前在C++(MSVS 2008)中创建了我自己的框架,该框架为我的框架的用户使用/调用导出了一堆函数。一开始,当我的项目仍然很小时,一切正常。我编译了我的项目。一个MyFramework.dll和MyFramework.lib被吐出。我假装是一个用户;将MyFramework.dll文件放入我的新VS项目的Debug文件夹中,将MyFramework.lib和MyFramework.h文件放在我的项目文件夹中,#include -d MyFramework.h在我的代码和voilá中,我可以调用(仍然很简单)我的新项目中的框架功能。创建一个链接到另一个DLL的DLL(MSVS2008 C++)

但是现在我扩展了我的框架。它现在使用它自己的外部dll(让我把它称为Graphics.dll)并以相同的方式包含它(.dll在Debug文件夹中,.lib/.h在项目文件夹中,#include Graphics.h在代码中)。

问题是,当我创建MyFramework.dll/MyFramework.lib时,将其包含在我的新项目中并构建,链接器抱怨无法包含Graphics.h,显然它包含在MyFramework.dll中某处。

所以我的问题。我希望MyFramework.dll的用户只需将MyFramework。*文件包含在他们的项目中,而不需要复制/粘贴我决定在MyFramework中使用的所有外部库。我怎样才能做到这一点?我看了一下this thread。它说什么关于添加一个现有的项目,并按下“添加”按钮旁边的小箭头,但是...箭头是不存在于我的版本的MSVS ...

帮助非常感谢。

亲切的问候 W.斯贝克

+1

链接器抱怨包含文件?没门! – stijn

+0

你是对的,它是编译器。 –

回答

1

“的问题是,当我现在创建MyFramework.dll/MyFramework.lib,包括它在我的新项目而建,链接器抱怨不能够包括图形.h,这显然包含在MyFramework.dll的某处。“

你把路径的头文件?编译器报告头文件与正在转换的cpp文件不在同一目录中,并且它未在其他包含目录中列出。

转到项目 - >属性,然后选择C/C++

第一个选项,你会看到的是“附加包含目录”。你需要把你的头文件Graphics.h的路径和其他需要分离所有分号的路径一起放在那里。例如,我在mo上打开的项目有:“../AudioLibrary;../CoreLibrary;”

编辑:从您的意见对马克的帖子你说你要嵌入Graphics.DLL在你的DLL。我的回答如下:

如果你没有Graphics.dll的源代码,那么你有问题。你所问的是可能的,但非常复杂。基本上你不能使用LoadLibrary。你将被迫为LoadLibaray和GetProcAddress编写你自己的文件,它将查看嵌入式DLL并且不会尝试在磁盘上找到它......它是可行的,但是您需要在Portable Executable (PE) file structure上进行大量的读取。

+0

而这正是针对我不想做的事情。我可以在“MyFramework”项目中做什么,无需在使用MyFramework.dll的新项目中包含外部文件? –

+0

那么你需要知道函数原型的样子。正如Mark所建议的那样,使用GetProcAddress非常好,但是您必须创建一个头文件,该头文件在Graphics.h中有一个副本,或者您必须包含原始Graphics.h。否则,编译器怎么可能知道需要什么参数? – Goz

+0

我还应该指出,如果你打算使用GetProcAddress,那么你将需要用指针中嵌入的相关函数原型创建一堆正确的函数指针。 – Goz

0

如果您不想要求用户拥有或包含Graphics.h,则一种方法是使用LoadLibrary在运行时动态加载Graphics.dll。

这将意味着用户将能够在没有图形的情况下针对MyFramework进行编译。DLL可用,所以如果LoadLibrary失败,做一些错误报告可能是明智的做法。

在Graphics.dll上成功调用LoadLibrary后,您需要使用GetProcAddress手动导入每个函数(及其签名) - 这实际上会为您提供函数指针。你如何存储函数指针取决于你;我通常更喜欢在导入的函数中包装一个类,但没有任何东西阻止您将函数指针保留在全局范围中。


正如评论所说,如果你不想 在所有分配 Graphics.dll,这将需要一个静态库(即“内置”到MyFramework.dll)。如果你 想分发Graphics.dll(所以用户可以使用Graphics.dll没有MyFramework.dll),那么上述方法仍然是更好的选择。实际上,上述方法假定您将Graphics.dll与MyFramework.dll一起发布,但用户可能不一定具有Graphics.h。

+0

但是,用户可能仍然需要在他的硬盘上某处的Graphics.dll的单独副本,对吧?这也是一种不想要的情况。用户不需要知道Grpahics.dll的存在。他应该只需要关心MyFramework。*文件... –

+0

您是否在讨论将DLL嵌入到可执行文件中?如果是这样......使用静态库而不是动态库! – Goz

+0

是的,我正在讨论将Graphics.dll嵌入到MyFramework.dll中。所以这个建议是一个静态库?但是你的意思是什么?使MyFramework库静态,或者以某种方式在MyFramework.dll中包含静态图形库。请注意,我没有Graphics.dll的源代码,除了Graphics.h。 –

2

发生了什么事是用户包括您的库的头文件之一。这个文件然后包含“graphics.h”。如果您不想要求您的用户访问此文件,则必须将其从库接口中隐藏。

这就是你的库必须有公共的api头文件和私有实现头文件。您的用户只包含公共api头文件,这些文件不包含任何第三方或私人包含文件。当这些文件引用私有类型或第三方类型时,它们只能使用指针或引用,这些都是前向声明的。这使得类的私有部分可以使用私有库代码和第三方类型。

正在使用Pimpl Idiom的机会将为您解决这个问题。

+0

我想你可能是对的。现在我在MyFramework.h接口头文件中包含Graphics.h。这是错误的。我也和我的主管说过话,告诉我也是这样。这就是为什么用户的编译器抱怨缺少Graphics.h文件。我会看看PIMPL模式,看看我能否解决我的问题。必须稍后再做。我会回到最后的解决方案。 –

+0

我正试图使用​​C++/CLI从受管DLL中使用非托管库。不幸的是我的头文件使用的是OpenCV头文件,这意味着它需要混合模式构建,这不起作用。 使用Pimpl成语正是我所需要的 – Fuzz