我有一个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。
如何在我的dll.cpp(dll.dll)中导出我的其他dll可以通过静态do_smt方法使用它的buf静态buf?
我正在使用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中。
主要不是我写的,我没有代码。另外主要是没有真正加载dll.dll。它正在使用 LoadLibrary 加载库以检查某些信息(通过getdllDLLInit(可能是错误命名))并再次卸载。 dll.dll位于exe的根目录中。如有必要,它将由Windows自动加载。其他dll由.exe使用 LoadLibrary 明确加载。
我的第一次尝试是没有任何类或模板,只有全局功能,它工作。之后,我创建了一个模板类,将函数放入。原因是,dll.dll将与其他类型重用,所以我不必重写(只需更改继承class __declspec(dllexport) child: public base <some_other_type> {};
和重新定义静态......)我可以一次又一次地重写所有内容,但这违反了DRY原则。
在willj建议我在没有模板的情况下尝试它,我发现了一些新东西。问题是当方法在头部内部而不是在cpp内部时。如果我只是重写模板
template<typename T>
class __declspec(dllexport) base {...};
到
class __declspec(dllexport) baseInt {...};
它仍然不起作用,但如果我从标题中分离方法并将它们移动到cpp(在我的情况下,将base::buf
移动到cpp更重要)它可以工作。我认为问题是,即使base :: buf成员正确编译到dll.dll中,另一个项目在编译时也找不到定义,即使它是在lib中定义的。我不知道这是msvc中的错误还是正确的行为。我虽然从具有特定类型的基础继承将是这样做的。
由于我想使用模板和1(全局)标题,我开始认为这个问题可能无法解决。
命令:
/ FR“Debug \”/ GS / analyze- / W3 / Zc:wchar_t / I“我的包含路径”/ 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 /PDD:"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
答案 0 :(得分:0)
我发现此帖可能会回答您的问题https://anteru.net/blog/2008/11/19/318/
此外,我认为这个问题是因为您没有在其自己的dll中实例化您的模板。 一种解决方案是在与 base 类相同的dll中定义 child 类。 如果这会破坏类和模块的设计,您可以提取可以由子派生的 A 类,并将 A 与 base 类相同的dll。