使用MSVC强制符号导出

时间:2009-01-14 19:34:11

标签: c++ dll plugins visual-c++

我在DLL文件中有一个应用程序和几个插件。插件使用来自的符号 通过导出库申请。应用程序链接在几个静态库中,这是大多数符号的来源。只要应用程序使用符号,这就可以正常工作。如果那里没有使用符号,我在编译DLL时会遇到链接器错误。

如何强制导出仅在插件中使用的符号?

为了触发导出,我尝试过这样的事情:

    class MyClassExporter
    {
        MyClass mInstance;
    public:
        MyClassExporter() {}
    };
    static MyClassExporter TheMyClassExporter;

在其中一个静态库中构建应用程序以强制导出,这不起作用。

回应Greg(感谢答案)并澄清:我要强制导出的类是MyClass(已定义__declspec(...),具体取决于我想要导出或导入)。 MyClassExport是我试图强制将未使用的(就应用程序而言)符号包含在应用程序中。我想“触摸”这些符号,以便链接器将它们识别为已使用并将它们包含在应用程序中,以便它可以将这些符号导出到我的插件中。将静态库链接到插件不是一种选择,因为它们包含可复制的单例(app和DLL各自都有自己的静态变量副本)。

5 个答案:

答案 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)

我试图解决这个问题是:

  1. 使用函数void afunction( int )构建一个静态库。
  2. 构建一个dll,链接到静态lib,导出afunction
  3. 使用afunction符号构建exe。
  4. 如何?由于可以告诉链接器使用__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