我正在努力让rLog在windows下构建为DLL,并且我得到了与rlog命名空间中的某些全局符号相关的未定义符号错误。特别是在RLogChannel.cpp:
中namespace rlog {
...
RLogChannel *_RLDebugChannel = GetGlobalChannel( "debug", Log_Debug );
RLogChannel *_RLInfoChannel = GetGlobalChannel( "info", Log_Info );
RLogChannel *_RLWarningChannel = GetGlobalChannel( "warning", Log_Warning );
RLogChannel *_RLErrorChannel = GetGlobalChannel( "error", Log_Error );
...
};
我认为问题在于1)它们没有被导出,2)它们没有在标题中声明,因此其他东西可以访问它们。所以我在它们中添加了__declspec(dllexport)(通过RLOG_DECL宏),并在标题中添加:
namespace rlog {
...
RLOG_DECL extern RLogChannel *_RLDebugChannel;
RLOG_DECL extern RLogChannel *_RLInfoChannel;
RLOG_DECL extern RLogChannel *_RLWarningChannel;
RLOG_DECL extern RLogChannel *_RLErrorChannel;
...
};
但无论我如何在RLogChannel.cpp中声明变量,我都会得到一个重新定义错误,尽管我在标题中对它们进行了外设...这样做的正确方法是什么?看起来它应该是直截了当但我无法完全绕过它。
编辑:错误消息
Error 12 error C2086: 'rlog::RLogChannel *rlog::_RLDebugChannel' : redefinition rlog-1.4\rlog\RLogChannel.cpp 45 rlog
(所有4个符号都相同)
编辑:我不知道发生了什么,代码完全相同,但现在它将编译(感觉像MSVC奇怪......),遗憾的是,当链接到我的库时,符号仍然显示为未解析答案 0 :(得分:1)
解决此问题的一种方法是在一个位置和标题中定义它们一次。 但是如果你只是将所有定义转移到标题,你最终会遇到多重定义问题。
解决方案就是这样。假设这些文件名为rlog.c& rlog.h
--- (rlog.h) ---
#ifdef RLOG_DEFINES
#define EXTERN
#else
#define EXTERN extern
#endif
namespace rlog {
...
RLOG_DECL EXTERN RLogChannel *_RLDebugChannel;
RLOG_DECL EXTERN RLogChannel *_RLInfoChannel;
RLOG_DECL EXTERN RLogChannel *_RLWarningChannel;
RLOG_DECL EXTERN RLogChannel *_RLErrorChannel;
...
};
--- (rlog.c) ---
#define RLOG_DEFINES
#include "rlog.h"
...
--- (other .c files) ---
#include "rlog.h"
这个解决方案的优点在于,因为定义只在项目中定义一次,所以您不会让它们彼此不同步,您只需要在一个地方更改它们。想象一下,如果你将变量定义为long,但在extern定义中它被声明为short?你最终会出现意想不到的副作用。所以这样做有助于防止这些类型的问题。
希望有所帮助。
答案 1 :(得分:1)
我认为马特非常接近。我曾经有一段时间面对这个问题并且正确(而且最便携的解决方案就是这样:
--- (rlog.h) ---
#ifdef RLOG_DEFINES
#define RLOG_DECL __declspec(dllexport)
#else
#define RLOG_DECL __declspec(dllimport)
#endif
namespace rlog {
...
RLOG_DECL extern RLogChannel *_RLDebugChannel;
RLOG_DECL extern RLogChannel *_RLInfoChannel;
RLOG_DECL extern RLogChannel *_RLWarningChannel;
RLOG_DECL extern RLogChannel *_RLErrorChannel;
...
};
--- (rlog.c) ---
#define RLOG_DEFINES
#include "rlog.h"
namespace rlog {
...
__declspec(dllexport) RLogChannel *_RLDebugChannel = GetGlobalChannel( "debug", Log_Debug );
__declspec(dllexport) RLogChannel *_RLInfoChannel = GetGlobalChannel( "info", Log_Info );
__declspec(dllexport) RLogChannel *_RLWarningChannel = GetGlobalChannel( "warning", Log_Warning );
__declspec(dllexport) RLogChannel *_RLErrorChannel = GetGlobalChannel( "error", Log_Error );
...
};
--- (other .c files) ---
#include "rlog.h"
规则很简单。编译提供dllexport的dll时,必须在符号声明和定义中进行匹配。另一方面,当外面的世界使用你的图书馆时 - 它必须显示为dllimport符号。
此致 Maciej Jablonski