我正在编写一组库,其中一个充当核心组件,通过插件API 后期绑定其他组件。现在问题如下:
核心库包含一个日志类以及一组用于轻量级日志的宏。
/* File: Log.h */
namespace XYZ
{
class XYZ_API Log
{
/* Logfile and console output management */
};
// Global log object
extern XYZ_API Log logger;
// Macros using aforementioned variable
#ifndef XYZ_DISABLE_LOGGING
#define LOG_DEBUG(msg) /* statements using logger object */
#define LOG_INFO(msg) /* etc. */
#else
#define LOG_DEBUG(msg)
#define LOG_INFO(msg)
#endif
}
logger 变量的定义非常简单:
/* File: Log.cpp */
namespace XYZ
{
// Initialize the global log object
Log logger;
/* Log class implementation */
}
现在,当从核心库本身或客户端应用程序中使用这些宏时,一切正常。但是一旦我尝试在其中一个插件中使用它们:
/* File: MyPlugin.cpp */
namespace XYZ
{
MyPlugin::MyPlugin(/* ... */)
{
LOG_INFO("This won't link!");
logger.
}
}
出现以下链接器错误(使用 MSVC 工具链 v110):
LNK2001: unresolved external symbol "class XYZ::Log XYZ::logger" (?logger@XYZ@@3VLog@1@A)
话虽如此,这个符号肯定是从插件库中导出的(它存在于 .lib 文件中)。该插件也被链接到核心库。其他符号(类及其方法)工作得很好。
我知道对于运行时加载,必须使用 GetProcAddress/dlsym(或其他等效项)查询加载的 DLL 中的符号。此外,我有一个接口,它可以通过一个纯虚拟类,使插件知道核心库中的任何对象。
现在是实际问题:有没有办法使上述计划生效,还是我必须避免在插件代码中使用日志记录宏?
编辑:
编译器命令行选项(核心库)是(去掉冗长的路径名):
/GS /analyze- /W3 /Zc:wchar_t /I"[...]" /ZI /Gm /Od /Fd"[...]" /fp:precise /D "XYZ_EXPORT_SYMBOLS" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_USRDLL" /D "_WINDLL" /D "_UNICODE" /D "UNICODE" /errorReport:prompt /WX- /Zc:forScope /RTC1 /Gd /Oy- /MDd /Fa"[...]" /EHsc /nologo /Fo"[...]" /Fp"[...]"
对于链接器:
/OUT:"[...]" /MANIFEST /NXCOMPAT /PDB:"[...]" /DYNAMICBASE "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 /DLL /MACHINE:X86 /INCREMENTAL /PGD:"[...]" /SUBSYSTEM:WINDOWS /MANIFESTUAC:"level='asInvoker' uiAccess='false'" /ManifestFile:"[...]" /ERRORREPORT:PROMPT /NOLOGO /TLBID:1
插件库也是如此;几乎完全相同的行,除了路径名:
/GS /analyze- /W3 /Zc:wchar_t /I"[...]" /ZI /Gm /Od /Fd"[...]" /fp:precise /D "XYZ_EXPORT_SYMBOLS" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_USRDLL" /D "_WINDLL" /D "_UNICODE" /D "UNICODE" /errorReport:prompt /WX- /Zc:forScope /RTC1 /Gd /Oy- /MDd /Fa"[...]" /EHsc /nologo /Fo"[...]" /Fp"[...]"
和插件链接;同样,除了指向核心库的链接之外,基本上是同一行:
/OUT:"[...]" /MANIFEST /NXCOMPAT /PDB:"[...]" /DYNAMICBASE "kernel32.lib" "user32.lib" "gdi32.lib" "winspool.lib" "comdlg32.lib" "advapi32.lib" "shell32.lib" "ole32.lib" "oleaut32.lib" "uuid.lib" "odbc32.lib" "odbccp32.lib" "[path to core lib]" /IMPLIB:"[...]" /DEBUG /DLL /MACHINE:X86 /INCREMENTAL /PGD:"[...]" /SUBSYSTEM:WINDOWS /MANIFESTUAC:"level='asInvoker' uiAccess='false'" /ManifestFile:"[...]" /ERRORREPORT:PROMPT /NOLOGO /TLBID:1