2015-10-16 6 views
0

В настоящее время я разрабатываю игру, которая состоит из двух частей: двигатель находится в .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», ошибки компоновщика исчезают. Я не знаю, что происходит и почему это происходит, и поэтому я обращаюсь к этому вопросу с кем-нибудь, кто мог бы мне помочь.

ответ

2

Update:

От линии:

#define NF3D_API __declspec(dllexport) 

это выглядит, как вы всегда экспорт, и никогда не импортировать (которые вы должны делать, когда заголовок включен из внешних проектов).

Например, скомпилировать код, используя определение NM3D_API_EXPORTS макрос (если я не ошибаюсь:. Опцию -d

И, затем, в заголовке определяют NM3D_API следующим образом:

#ifdef NM3D_API_EXPORTS 
#define NM3D_API __declspec(dllexport) 
#else 
#define NM3D_API __declspec(dllimport) 
#endif 

Оригинальное сообщение:

Включите поработаем в очень тупой способ Берут все содержимое файла, который вы в том числе, и вставить их на включаемые заявление

..

Именно поэтому, когда вы пытаетесь включить этот заголовок в другой проект, этот проект не знает о вашей декларации в предыдущей .dll. Поскольку это было сделано в другом файле, о котором ваш другой проект ничего не знает.

+0

Что вы посоветуете мне сделать? –

+0

@VictorGabrielUngureanu Ну, если я знаю * почему * ваш код не работает, это не значит, что я знаю правильное решение для вашей проблемы. Но тем не менее, первая мысль, которая приходит на ум, заключается в том, чтобы избежать глобальных переменных (или их определений) в публичном заголовке .dll, но вместо этого написать функцию-оболочку, которая возвращает эту переменную (т. Е. Написать GetCriticalSection(), которая возвращает переменная CriticalSection). –

+0

Кроме того, в качестве побочного вопроса вы можете вызвать любую другую функцию, определенную в вашей .dll извне?На втором взгляде кажется, что вы экспортируете только код, но никогда не импортируете (что вы должны делать в случае, когда заголовок включен из внешних проектов) –

 Смежные вопросы

  • Нет связанных вопросов^_^