我在DLL文件中有一个应用程序和几个插件。插件使用来自的符号 通过导出库申请。应用程序链接在几个静态库中,这是大多数符号的来源。只要应用程序使用符号,这就可以正常工作。如果那里没有使用符号,我在编译DLL时会遇到链接器错误。
如何强制导出仅在插件中使用的符号?
为了触发导出,我尝试过这样的事情:
class MyClassExporter
{
MyClass mInstance;
public:
MyClassExporter() {}
};
static MyClassExporter TheMyClassExporter;
在其中一个静态库中构建应用程序以强制导出,这不起作用。
回应Greg(感谢答案)并澄清:我要强制导出的类是MyClass(已定义__declspec(...),具体取决于我想要导出或导入)。 MyClassExport是我试图强制将未使用的(就应用程序而言)符号包含在应用程序中。我想“触摸”这些符号,以便链接器将它们识别为已使用并将它们包含在应用程序中,以便它可以将这些符号导出到我的插件中。将静态库链接到插件不是一种选择,因为它们包含可复制的单例(app和DLL各自都有自己的静态变量副本)。
答案 0 :(得分:3)
您可能想查看__declspec(导出/导入)
#ifdef DLL_EXPORTING
#define WHDLL __declspec(dllexport)
#else
#define WHDLL __declspec(dllimport)
#endif
将静态模块链接到dll时,它只会引入使用的代码。我从来没有从静态库导入东西只是简单地导出它 也许你只需要在编译静态库时将它标记为可导出的。
但这让我想起将std容器放入导出的类中,并在msvc中使用一些技巧来导出专用容器的“实例”。模板代码类似于您的静态代码(在我的想法中)
例如,如果没有模板,您会收到警告,模板代码不会导出以支持该类 - 这是我理解的MSVC
template class DLL_EXPORTING std::auto_ptr<wxCursor>;
class DLL_EXPORTING imageButton : public wxWindow
{
std::auto_ptr<wxCursor> m_Cursor;
};
答案 1 :(得分:3)
/INCLUDE指令可用于强制MSVC链接器包含符号。或者,/OPT:NOREF可用于禁用一般未使用的符号的删除。
一种常见的方法是创建一个未使用的函数,该函数引用为插件导出的所有对象。那么你只需要一个/ INCLUDE指令用于该函数。
答案 2 :(得分:2)
我试图解决这个问题是:
void afunction( int )
构建一个静态库。afunction
。afunction
符号构建exe。如何?由于可以告诉链接器使用__declspec(dllexport)
指令导出函数,因此dll只需要声明一个待导出的符号。
lib有一个标题“afunction.h”和一个附带的cpp文件,其中包含函数体:
// stat/afunction.h
namespace static_lib { void afunction(int); }
// stat/afunction.cpp
#include "afunction.h"
namespace static_lib { void afunction(int){ } }
dll有一个包含文件“indirect.h”,包含要导出的函数的声明。 dll与静态lib具有链接时依赖性。 (链接器选项:输入/附加依赖项:“static_library.lib”)
// dll/indirect.h
namespace static_lib {
__declspec( dllexport ) void afunction(int);
}
可执行文件只包含间接包含的文件:
#include <dll/indirect.h>
int main() { static_lib::afunction(1); }
猜猜是什么?它编译,链接甚至运行!
答案 3 :(得分:2)
“使用库依赖项输入”选项可以解决VS2005中的问题!
此选项可在配置属性 - &gt;下找到。链接器 - &gt;一般 - &gt;使用库依赖项输入。设置为“true”以强制链接所有符号和&amp;在每个指定为项目输入的LIB中声明的代码。
您可以执行以下操作以获取从DLL导出的符号:在库项目中定义LIB_EXPORTS,在DLL项目或DLL客户端项目中没有任何内容。
#ifdef LIB_EXPORTS
#define DLLAPI __declspec(dllexport)
#else
#define DLLAPI __declspec(dllimport)
#endif
事实证明,在编译DLL项目时,不需要#include LIB项目中的任何头文件;只需将LIB指定为链接器输入。但是,如果需要在DLL中使用LIB代码,则需要#define DLLAPI作为空宏;将符号设置为dllexport或dllimport将分别生成错误或警告。
答案 4 :(得分:1)
在MSDN上有一些关于这个问题的讨论非常有用。事实证明,/ OPT:NOREF在这种情况下并不是特别有用。 / INCLUDE可以工作,但很难自动找出需要/ INCLUDEd的内容。遗憾的是没有银弹。
http://social.msdn.microsoft.com/forums/en-US/vclanguage/thread/2aa2e1b7-6677-4986-99cc-62f463c94ef3