C++ C++;.dll中的CRITICAL_SECTION对象给出了未解析的外部符号错误

C++ C++;.dll中的CRITICAL_SECTION对象给出了未解析的外部符号错误,c++,winapi,dll,dllexport,C++,Winapi,Dll,Dllexport,我目前正在开发一个包含两部分的游戏:引擎在.dll中,实际的游戏代码是.exe的一部分。在其他头文件中,引擎包含一个管理所有组件的头文件,范围从Win32特定对象和指针到D3D11。这些组件包含在一个类中,该类允许通过返回引用的函数全局访问这些组件。此外,对于它管理的每个项目,有两个函数允许设置或返回组件。我还添加了一个使用临界部分的线程保护。 因此,在状态h中,我有: #if defined(NF3D_NONCLIENT_BUILD) #define NF3D_API __de

我目前正在开发一个包含两部分的游戏:引擎在.dll中,实际的游戏代码是.exe的一部分。在其他头文件中,引擎包含一个管理所有组件的头文件,范围从Win32特定对象和指针到D3D11。这些组件包含在一个类中,该类允许通过返回引用的函数全局访问这些组件。此外,对于它管理的每个项目,有两个函数允许设置或返回组件。我还添加了一个使用临界部分的线程保护。 因此,在状态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\u API CRITICAL\u SECTION CriticalSection”声明为静态时,这个错误让我更感兴趣,因为它编译得很好,但在NF3DLock的构造函数中输入CRITICAL SECTION时出现了访问冲突异常。此外,如果删除“EnterCriticalSection”和“LeaveCriticalSection”,链接器错误将消失。我不知道发生了什么,为什么会发生,这就是为什么我要向任何可能帮助我的人提出这个问题。

更新:

从这一行:

#define NF3D_API __declspec(dllexport)
看起来您总是在导出,而从不导入(当标题包含在外部项目中时,您应该这样做)

例如,使用定义NM3D\u API\u EXPORTS宏编译代码(如果我没有弄错的话:-d选项)

然后,在标题中按以下方式定义NM3D_API:

#ifdef NM3D_API_EXPORTS
#define NM3D_API __declspec(dllexport)
#else
#define NM3D_API __declspec(dllimport)
#endif
原创帖子:

Include以一种非常愚蠢的方式工作。它们将包含的文件的全部内容粘贴到Include语句上


这就是为什么,当您试图将此头包含到另一个项目中时,该项目不知道您在上一个.dll中的声明。因为它是在另一个文件中完成的,而您的另一个项目对此一无所知。

您建议我做什么?@VictorGabrielUngureanu好吧,如果我知道您的代码失败的原因,我不知道我的意思是我知道您的问题的正确解决方案。但是,我想到的第一个想法是避免在public.dll头中使用全局变量(或它们的定义),而是编写一个包装函数,返回该变量(即编写GetCriticalSection()返回CriticalSection变量)。另外,作为一个附带问题,您是否可以从外部调用.dll中定义的任何其他函数?从第二个角度看,您似乎只是在导出代码,而从未导入(如果标头包含在外部项目中,则应该这样做)事实上,我也考虑过同样的问题,但我只是尽量避免使用其他函数,我想知道是否有其他方法可以解决这个问题。感谢您急需的帮助。是的,我可以调用其他函数。我有一个函数,以完全相同的方式返回对日志系统的引用,并且它我很好。