0

我正在编写一组库,其中一个充当核心组件,通过插件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 
4

1 回答 1

1

听起来你有一个循环依赖问题。我已经尝试复制您的问题,但是我在 Linux 中运行,它对我来说并没有失败。

我假设您正在为 Windows 编写,回复:LNK2001 错误。搜索该错误会提供微软帮助页面。他们可能应该有所帮助。

也就是说,您将编译标志设置为什么(编译器和链接器)?

于 2013-03-17T13:00:28.440 回答