我正在编写一组库,其中一个库充当核心组件,后期通过插件 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
}
记录器变量的定义非常简单:
/* 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
答案 0 :(得分:1)
听起来你有一个循环依赖问题。 我试过复制你的问题,但我在Linux上运行,对我来说并没有失败。
我假设您正在为Windows编写,重新:LNK2001错误。搜索该错误会提供Microsoft软件帮助页面。他们可能应该帮忙。
那就是说,你编译标志设置为什么(编译器和链接器)?