我有一个导出一些函数的 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
我也尝试过类似的东西
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 <some_other_type> {};
并重新定义静态.. .) 我可以一次又一次地重写所有内容,但这将违反DRY原则。
编辑3:
在 willj 建议我在没有模板的情况下尝试它之后,我发现了一些新东西。问题是该方法位于标头内部而不是 cpp 内部。如果我只是重写模板
template<typename T>
class __declspec(dllexport) base {...};
至
class __declspec(dllexport) baseInt {...};
它仍然不起作用,但是如果我将方法与标题分开并将它们移动到 cpp 中(在我的情况下,移动base::buf
到 cpp 更重要)它可以工作。我认为问题是,即使 base::buf 成员被正确编译为 dll.dll,其他项目在编译时也找不到定义,即使它是在 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 "_DEBUG" /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