【问题标题】:export static member for another dll为另一个 dll 导出静态成员
【发布时间】:2013-08-18 06:03:50
【问题描述】:

我有一个导出一些函数的 dll,以便第二个 dll 可以使用它们。两个 dll 都由 main 加载。现在我在导出 dll 中的数据成员时遇到了问题。

我有一个看起来像这样的模板类 (temp.hpp):

template<typename T>
class __declspec(dllexport) base {
public:
    static T buf;
    static void do_smt(T val);
};

template<typename T>
void base<T>::do_smt(T val) {
    base<T>::buf = val;
}

从模板类 (dll.h) 继承的第二个类。此标头在 2 个 dll 之间共享。

#include "temp.hpp"

class __declspec(dllexport) child
    : public base <int> {};

dll.cpp 看起来像:

#include "dll.h"

base<int> inter;
int base<int>::buf;

还有一些其他功能,所以我尝试将其简化为基础。

这将编译并创建一个 .lib 和一个 .dll。现在我有另一个用.lib 编译的项目。主要是加载两个 dll,所以第二个 dll 可以使用 do_smt (如果我删除了static int buf,它就可以工作)。但是我收到一个错误,我的 buf 未解决。

Error   1   error LNK2001: unresolved external symbol "public: static int base<struct int>::buf" (?buf@?$base@Uint@@@@2HA)  module.obj

我也尝试过类似that

template <class T>
int base<T>::buf;

int base<int>::buf;

但遇到了同样的错误。

没有我的静态缓冲区,一切正常。

如何使我的 buf 静态 buf 导出到我的 dll.cpp (dll.dll) 中,以便我的其他 dll 可以通过静态 do_smt 方法使用它?

我正在使用 vs2012。

编辑:

dumpbin /exports dll.dll 返回:

File Type: DLL

  Section contains the following exports for dll.dll

    00000000 characteristics
    520D5353 time date stamp Fri Aug 16 00:16:51 2013
        0.00 version
           1 ordinal base
           5 number of functions
           5 number of names

    ordinal hint RVA      name

          1    0 000613E9 ??4?$base@Uint@@@@QAEAAV0@ABV0@@Z = @ILT+17380(??4?$base@Uint@@@@QAEAAV0@ABV0@@Z)
          2    1 0005F2BF ??4child@@QAEAAV0@ABV0@@Z = @ILT+8890(??4child@@QAEAAV0@ABV0@@Z)
          3    2 0014F594 ?buf@?$base@Uint@@@@2HA = ?buf@?$base@Uint@@@@2HA (public: static int base<int>::buf)
          4    3 0005D90B ?getdllDLLInit@@YAJPAUPlugInHeader@@@Z = @ILT+2310(?getdllDLLInit@@YAJPAUPlugInHeader@@@Z)
          5    4 0005F0BC dllDLL = @ILT+8375(_dllDLL)

  Summary

        4000 .data
        4000 .idata
       29000 .rdata
        9000 .reloc
        1000 .rsrc
       C6000 .text
       5C000 .textbss
        1000 .tls

似乎 buf 在 dll 中。

编辑 2:

主要不是我写的,我没有代码。另外主要是没有真正加载dll.dll。它正在使用 LoadLibrary 加载库以检查某些信息(通过 getdllDLLInit(可能命名错误))并再次卸载。 dll.dll 位于 exe 的根目录中。如有必要,它将由 Windows 自动加载。其他 dll 由 .exe 使用 LoadLibrary 显式加载。

我的第一次尝试是没有任何类或模板,只有 gobal 函数并且它有效。之后,我创建了一个模板类,将函数放入其中。原因是,dll.dll 将与其他一些类型一起重用,所以我不必重写太多(只需更改继承class __declspec(dllexport) child: public base &lt;some_other_type&gt; {}; 并重新定义静态...)我可以一次又一次地重写,但这将违反DRY原则。

编辑 3:

在 willj 建议我在没有模板的情况下尝试它之后,我发现了一些新东西。问题是该方法位于标头内部而不是 cpp 内部。如果我只是重写模板

template<typename T>
class __declspec(dllexport) base {...};

class __declspec(dllexport) baseInt {...};

它仍然不起作用,但是如果我将方法与标头分开并将它们移动到 cpp 中(在我的情况下,将 base::buf 移动到 cpp 更重要)它可以工作。我认为问题是,即使 base::buf 成员被正确编译为 dll.dll,其他项目在编译时也找不到定义 during 即使它是在 lib 中定义的。我不知道这是 msvc 中的错误还是正确的行为。我虽然通过从具有特定类型的基类继承来做到这一点。

由于我想使用模板和只有 1 个(全局)标题,我开始认为这个问题可能无法解决。

编辑 4:

命令:

  • 编译

/FR"Debug\" /GS /analyze- /W3 /Zc:wchar_t /I"my include path's" /Zi /Gm- /Od /Fd"Debug\vc110.pdb" /fp:precise /D" WIN32" /D "_WINDOWS" /D "_WIN32_WINDOWS=0x0501" /D "_D​​EBUG" /D "_USRDLL" /D "NOMINMAX" /D "_CRT_SECURE_NO_WARNINGS" /D "_WINDLL" /errorReport:prompt /WX- /Zc:forScope /RTC1 /Gd /Oy- /MDd /Fa"Debug\" /EHsc /nologo /Fo"Debug\" /Fp"Debug\test.pch"

  • 链接

/OUT:"Debug\test.dll" /MANIFEST /PDB:"Debug\test.pdb" /DYNAMICBASE:NO "dll.lib" "Winmm.lib" "kernel32.lib" "user32.lib" " gdi32.lib”“winspool.lib”“comdlg32.lib”“advapi32.lib”“shell32.lib”“ole32.lib”“oleaut32.lib”“uuid.lib”“odbc32.lib”“odbccp32.lib”/ IMPLIB:"Debug\test.lib" /DEBUG /DLL /MACHINE:X86 /SAFESEH /INCREMENTAL /PGD:"Debug\test.pgd" /SUBSYSTEM:WINDOWS /MANIFESTUAC:"level='asInvoker' uiAccess='false'" /ManifestFile:"Debug\test.dll.intermediate.manifest" /ERRORREPORT:PROMPT /NOLOGO /LIBPATH:"D:/prg/svn/branches/DLL/Debug" /LIBPATH:"D:\prg\svn\trunk\ LIBS\boost\1.53.0\lib\msvc-32bit" /TLBID:1

【问题讨论】:

  • 导出表为您的dll.dll 显示了什么?
  • @greatwolf 我编辑了我的问题。在愤怒的雪貂谢谢纠正。
  • 这很有趣。您还可以添加 main 的构建方式吗?特别是编译和链接命令的样子。
  • 您是否已经尝试过同样的事情,但将 template&lt;typename T&gt; class base 替换为 class baseInt 并将 base&lt;int&gt; 替换为 baseInt?只是为了排除模板作为一个因素。
  • @greatwolf 我的评论太长了,所以重新编辑 :) 我也会尝试一下 willj 的建议。

标签: c++ templates dll dllexport


【解决方案1】:

我发现这篇文章可能会回答您的问题https://anteru.net/blog/2008/11/19/318/

另外我认为这个问题是因为你没有在它自己的 dll 中实例化你的模板。 一种解决方案是在与 base 类相同的 dll 中定义 child 类。 如果这会破坏类和模块的设计,您可以提取一个可以由 child 派生的类 A,并将 A 放在同一个 dll 中作为基础类。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-03-13
    • 1970-01-01
    • 1970-01-01
    • 2021-11-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多