2010-02-11 4 views
3

저는 rLog를 Windows에서 DLL로 빌드하려고하는데, rlog 네임 스페이스의 일부 전역 심볼과 관련하여 정의되지 않은 심볼 오류가 발생했습니다. 특히이 RLogChannel.cpp에서 :네임 스페이스에서 extern을 올바르게 사용하는 방법은 무엇입니까?

내가 문제를 가정
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) 그들은 그래서 다른 일을 액세스 할 수 헤더에 선언되지 않았다. 그래서 나는 그들에게합니다 (RLOG_DECL 매크로 통해) __declspec (dllexport)를 추가하고, 헤더에 넣어 :

namespace rlog { 
... 
    RLOG_DECL extern RLogChannel *_RLDebugChannel; 
    RLOG_DECL extern RLogChannel *_RLInfoChannel; 
    RLOG_DECL extern RLogChannel *_RLWarningChannel; 
    RLOG_DECL extern RLogChannel *_RLErrorChannel; 
... 
}; 

을하지만 RLogChannel.cpp의 변수를 선언 아무리 내가에도 불구하고 재정의 오류 내 머리글에있는 이들을 제외하고 ...이 작업을 수행하는 올바른 방법은 무엇입니까? 그것이 직설적이어야하지만 나는 그것의 주위에 나의 머리를 아주 감쌀 수 없다.

편집 : 오류 메시지 (4 개 기호 같은)

Error 12 error C2086: 'rlog::RLogChannel *rlog::_RLDebugChannel' : redefinition rlog-1.4\rlog\RLogChannel.cpp 45 rlog 

는 편집 : 무슨 일이 있었는지 모르는 (코드는 이전과 동일한 정확히하지만 지금은 컴파일 느낌 MSVC와 같은 이상한 점 ...), 불행히도 내 라이브러리에 링크 할 때 여전히 기호가 해결되지 않은 것으로 표시됩니다.

+1

? 여기에 게시 할 수 있습니다. –

+0

무엇 –

+0

뭔가 흡사합니다. NT는 질문에서 제외되었습니다. 이 오류를 제공하는 간결하고 완전한 테스트 케이스 (예 : 컴파일러에 그대로 전달할 수있는 파일 하나)를 제공 할 수 있습니까? –

답변

1

한 가지 방법은 한 번에 한 곳에서 헤더를 정의하는 것입니다. 그러나 모든 정의를 헤더로 옮기면 다중 정의 문제가 발생합니다.

이것에 대한 해결책은 다음과 같습니다. 파일을 가정하는 & rlog.h rlog.c 이름이 지정됩니다

--- (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로 선언 된 경우를 상상해보십시오. 예기치 않은 부작용이 생길 수 있습니다. 이렇게하면 이러한 유형의 문제를 방지하는 데 도움이됩니다.

희망이 있습니다.

+0

그는 이미 cpp 파일에서 한 번 정의한 다음 머리글에 선언했다고 말했습니다. – Potatoswatter

+0

불행하게도 여러 정의 오류가 발생하는 경우 ... –

+0

.c 파일에서 정의하는 일반적인 해결책은 프로젝트에서 한 번만 정의된다는 것을 의미합니다. 이 파일의 헤더 (선언 포함)를 포함하면 실수로 컴파일러에서 오류가 발생할 수 있으므로 실수로 인한 불일치가 발생하지 않습니다. 요컨대, 당신이 제공하는 코드에는 아무런 이점이 없지만, 더 복잡하고 일반적인 관행을 따르지 않는 단점이 있습니다. –

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 상징으로 여기에 나타나야합니다

감사합니다, 마치에이 블론스키를

가 I보다 조금 더 좋은 포맷 그래서 위의 업데이트 정확한 오류 메시지
관련 문제