.dll 中的 C++ CRITICAL_SECTION 对象给出未解析的外部符号错误
C++ CRITICAL_SECTION object in .dll gives unresolved external symbol error
我目前正在开发一款分为两部分的游戏:引擎位于 .dll 中,实际游戏代码位于 .exe 中。该引擎与其他头文件一起包含一个管理所有组件的引擎,范围从 Win32 特定对象和指针到 D3D11。这些组件包含在 class 中,允许通过 returns 对其进行引用的函数全局访问它们。此外,对于它管理的每个项目,都有两个函数允许设置或返回组件。我还使用关键部分添加了线程保护。
所以,在 State.h 我有:
#if defined(NF3D_NONCLIENT_BUILD)
#define NF3D_API __declspec(dllexport)
#else
#if defined(__MINGW32__)
#define NF3D_API NF3D_API
#else
#define NF3D_API __declspec(dllimport)
#endif
#endif
...
#endif
...
extern NF3D_API CRITICAL_SECTION CriticalSection;
class NF3D_API NF3DLock
{
public:
#pragma prefast( suppress:26166, "Thread safeness is enabeled." )
FORCEINLINE _Acquires_lock_(CriticalSection) NF3DLock(void) { EnterCriticalSection(&CriticalSection); }
#pragma prefast( suppress:26165, "Thread safeness is enabeled." )
FORCEINLINE _Releases_lock_(CriticalSection) ~NF3DLock(void) { LeaveCriticalSection(&CriticalSection); }
};
class NF3D_API STATE
{
public:
...
inline void SetMember(int val) { NF3DLock Lock; Elements.Member = val; }
inline int GetMember(void) { NF3DLock Lock; return Elements.Member; }
private:
struct ELEMENTS
{
int Member;
} Elements;
}
FORCEINLINE NF3D_API STATE* NF3DGetEngineState(void);
在 State.cpp 中,我初始化并删除了临界区,而且:
CRITICAL_SECTION CriticalSection;
...
FORCEINLINE NF3D_API STATE* NF3DGetEngineState(void)
{
static STATE s_State;
return &s_State;
}
在 .dll 中调用 'NF3DGetEngineState' 不会导致任何问题并且编译运行完美,但是如果我在引擎外部使用此函数,在应用程序内部我会在 .exe 中遇到链接器错误:
2>Main.obj : error LNK2001: unresolved external symbol "struct _RTL_CRITICAL_SECTION NewFrontiers3D::CriticalSection" (?CriticalSection@NewFrontiers3D@@3U_RTL_CRITICAL_SECTION@@A)
该引擎包含在名为 'NewFrontiers3D' 的命名空间中。
当我将 'extern NF3D_API CRITICAL_SECTION CriticalSection' 声明为静态时,这个错误更让我感兴趣,因为它编译正常但在进入 NF3DLock 的构造函数中的关键部分时给出了访问冲突异常。此外,如果我删除 'EnterCriticalSection' 和 LeaveCriticalSection',链接器错误就会消失。我不知道发生了什么,也不知道为什么会这样,这就是为什么我要向任何可能帮助我的人提出这个问题。
更新:
来自行:
#define NF3D_API __declspec(dllexport)
看起来您总是在导出,而从不导入(当 header 包含在外部项目中时您应该这样做)。
例如,使用定义 NM3D_API_EXPORTS 宏编译代码(如果我没记错的话:-d 选项。
然后,在 header 中按以下方式定义 NM3D_API:
#ifdef NM3D_API_EXPORTS
#define NM3D_API __declspec(dllexport)
#else
#define NM3D_API __declspec(dllimport)
#endif
原文Post:
Include 的工作方式非常愚蠢。他们获取您要包含的文件的全部内容,并将它们粘贴到包含语句中。
这就是为什么当您尝试将此 header 包含到另一个项目时,该项目不知道您在之前的 .dll 中的声明。由于它是在不同的文件中完成的,您的其他项目对此一无所知。
我目前正在开发一款分为两部分的游戏:引擎位于 .dll 中,实际游戏代码位于 .exe 中。该引擎与其他头文件一起包含一个管理所有组件的引擎,范围从 Win32 特定对象和指针到 D3D11。这些组件包含在 class 中,允许通过 returns 对其进行引用的函数全局访问它们。此外,对于它管理的每个项目,都有两个函数允许设置或返回组件。我还使用关键部分添加了线程保护。 所以,在 State.h 我有:
#if defined(NF3D_NONCLIENT_BUILD)
#define NF3D_API __declspec(dllexport)
#else
#if defined(__MINGW32__)
#define NF3D_API NF3D_API
#else
#define NF3D_API __declspec(dllimport)
#endif
#endif
...
#endif
...
extern NF3D_API CRITICAL_SECTION CriticalSection;
class NF3D_API NF3DLock
{
public:
#pragma prefast( suppress:26166, "Thread safeness is enabeled." )
FORCEINLINE _Acquires_lock_(CriticalSection) NF3DLock(void) { EnterCriticalSection(&CriticalSection); }
#pragma prefast( suppress:26165, "Thread safeness is enabeled." )
FORCEINLINE _Releases_lock_(CriticalSection) ~NF3DLock(void) { LeaveCriticalSection(&CriticalSection); }
};
class NF3D_API STATE
{
public:
...
inline void SetMember(int val) { NF3DLock Lock; Elements.Member = val; }
inline int GetMember(void) { NF3DLock Lock; return Elements.Member; }
private:
struct ELEMENTS
{
int Member;
} Elements;
}
FORCEINLINE NF3D_API STATE* NF3DGetEngineState(void);
在 State.cpp 中,我初始化并删除了临界区,而且:
CRITICAL_SECTION CriticalSection;
...
FORCEINLINE NF3D_API STATE* NF3DGetEngineState(void)
{
static STATE s_State;
return &s_State;
}
在 .dll 中调用 'NF3DGetEngineState' 不会导致任何问题并且编译运行完美,但是如果我在引擎外部使用此函数,在应用程序内部我会在 .exe 中遇到链接器错误:
2>Main.obj : error LNK2001: unresolved external symbol "struct _RTL_CRITICAL_SECTION NewFrontiers3D::CriticalSection" (?CriticalSection@NewFrontiers3D@@3U_RTL_CRITICAL_SECTION@@A)
该引擎包含在名为 'NewFrontiers3D' 的命名空间中。 当我将 'extern NF3D_API CRITICAL_SECTION CriticalSection' 声明为静态时,这个错误更让我感兴趣,因为它编译正常但在进入 NF3DLock 的构造函数中的关键部分时给出了访问冲突异常。此外,如果我删除 'EnterCriticalSection' 和 LeaveCriticalSection',链接器错误就会消失。我不知道发生了什么,也不知道为什么会这样,这就是为什么我要向任何可能帮助我的人提出这个问题。
更新:
来自行:
#define NF3D_API __declspec(dllexport)
看起来您总是在导出,而从不导入(当 header 包含在外部项目中时您应该这样做)。
例如,使用定义 NM3D_API_EXPORTS 宏编译代码(如果我没记错的话:-d 选项。
然后,在 header 中按以下方式定义 NM3D_API:
#ifdef NM3D_API_EXPORTS
#define NM3D_API __declspec(dllexport)
#else
#define NM3D_API __declspec(dllimport)
#endif
原文Post:
Include 的工作方式非常愚蠢。他们获取您要包含的文件的全部内容,并将它们粘贴到包含语句中。
这就是为什么当您尝试将此 header 包含到另一个项目时,该项目不知道您在之前的 .dll 中的声明。由于它是在不同的文件中完成的,您的其他项目对此一无所知。