私はいくつかの関数をエクスポートする dll を持っているので、2 番目の dll はそれらを使用できます。両方の dll がメインによってロードされます。現在、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 番目のクラス。このヘッダーは、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 をロードしているため、2 番目の 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;
しかし、同じエラーが発生しました。
私の静的バッファなしですべてが機能しています。
他の dll が静的 do_smt メソッドで使用できるように、自分の dll.cpp (dll.dll) にエクスポートされた 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 の中にあるようです。
編集2:
メインは私が書いたものではなく、コードがありません。また、メインは実際にはdll.dllをロードしていません。一部の情報をチェックするためにLoadLibraryを使用してライブラリをロードし(getdllDLLInit (名前が悪い可能性があります))、再度アンロードします。dll.dll は、exe のルート ディレクトリにあります。必要に応じて、ウィンドウによって自動的にロードされます。他の dll は、 LoadLibraryを使用して .exe によって明示的に読み込まれます。
私の最初の試みは、クラスやテンプレートを使用せず、グローバル関数だけで機能しました。その後、関数を配置するテンプレート クラスを作成しました。その理由は、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"インクルード パス" /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