В настоящее время я разрабатываю игру, которая состоит из двух частей: двигатель находится в .dll, а фактический игровой код является частью .exe. Двигатель, среди других файлов заголовков, содержит тот, который управляет всеми компонентами, начиная от конкретных объектов Win32 и указателей до D3D11. Эти компоненты включены в класс, который позволяет им получить доступ глобально через функцию, которая возвращает ссылку на нее. Кроме того, для каждого элемента, который он управляет, существуют две функции, которые позволяют устанавливать или возвращать компонент. Я также добавил защиту потока, используя критический раздел. Так, в State.h у меня есть:Объект C++ CRITICAL_SECTION в .dll дает нерешенную ошибку внешнего символа
#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;
}
Calling 'NF3DGetEngineState' внутри .dll не вызывает никаких проблем и компиляция отлично работает, но если я использую эту функцию вне двигателя, внутри приложения я получаю ошибку компоновщика в EXE-файле:
2>Main.obj : error LNK2001: unresolved external symbol "struct _RTL_CRITICAL_SECTION NewFrontiers3D::CriticalSection" ([email protected]@@[email protected]@A)
двигатель включен в Наме espace называется 'NewFrontiers3D'. Эта ошибка заинтриговала меня еще больше, когда я объявлял «extern NF3D_API CRITICAL_SECTION CriticalSection» статичным, поскольку он скомпилирован в порядке, но дал исключение нарушения доступа при входе в критический раздел в конструкторе NF3DLock. Кроме того, если я удаляю «EnterCriticalSection» и «LeaveCriticalSection», ошибки компоновщика исчезают. Я не знаю, что происходит и почему это происходит, и поэтому я обращаюсь к этому вопросу с кем-нибудь, кто мог бы мне помочь.
Что вы посоветуете мне сделать? –
@VictorGabrielUngureanu Ну, если я знаю * почему * ваш код не работает, это не значит, что я знаю правильное решение для вашей проблемы. Но тем не менее, первая мысль, которая приходит на ум, заключается в том, чтобы избежать глобальных переменных (или их определений) в публичном заголовке .dll, но вместо этого написать функцию-оболочку, которая возвращает эту переменную (т. Е. Написать GetCriticalSection(), которая возвращает переменная CriticalSection). –
Кроме того, в качестве побочного вопроса вы можете вызвать любую другую функцию, определенную в вашей .dll извне?На втором взгляде кажется, что вы экспортируете только код, но никогда не импортируете (что вы должны делать в случае, когда заголовок включен из внешних проектов) –