.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 中的声明。由于它是在不同的文件中完成的,您的其他项目对此一无所知。