Visual Studio 2010 Pro 的链接器问题

发布于 2024-12-11 20:22:22 字数 18399 浏览 0 评论 0原文

我在 VS 2010 中设置 DirectX 9(与该问题无关......我认为)框架时遇到一个非常令人沮丧的问题。这是我的 DirectX 框架:

#ifndef _DX9_H_
#define _DX9_H_

// window includes
#define WIN32_LEAN_AND_MEAN
#include <Windows.h>

// required for ush typedef and window properties to setup backbuffer
#include "sys_params.h"

// directx9 includes
#define DIRECTINPUT_VERSION 0x0800
#include <d3dx9.h>
#include <dinput.h>
#include <DxErr.h>
#include <vector>
#include <iterator>

// directx9 libraries
#pragma comment(lib, "d3d9.lib")
#pragma comment(lib, "d3dx9.lib")
#pragma comment(lib, "dinput8.lib")
#pragma comment(lib, "dxguid.lib")
#pragma comment(lib, "dxerr.lib")

namespace nsdx9
{
    using nssysprms::ush;

    #define CheckHR(hr) CheckForDXError(__FILE__, __LINE__, hr)

    class DX9
    {
        public:
            DX9(HINSTANCE& inst, int cmdShow, const std::string& title, ush wndwidth, ush wndheight, short wndx, short wndy);
            ~DX9();

            // windows message processor
            UINT ProcessMessages();

            // --- DIRECTX GAME FUNCTIONS --- //
            // input functions
            void InputUpdate();
            BYTE KeyHeld(ush key);
            bool KeyPressed(ush key);

            // sprite functions
            const LPD3DXSPRITE& GetSpriteInterface();
            void SpriteBeginDraw(DWORD flags = D3DXSPRITE_ALPHABLEND);
            void SpriteEndDraw();

            // font functions
            void MakeFont(int height, int width, UINT weight = FW_DONTCARE, LPCSTR face = "Calibri", bool italic = false);
            const LPD3DXFONT& GetFontAtIndex(ush index);
            const std::vector<LPD3DXFONT>& GetFontVector();
            // --- END DIRECTX GAME FUNCTIONS --- //

        private:
            // --- WINDOW FUNCTIONS/VARIABLES --- //
            WNDCLASSEX _wc;
            HWND _hwnd;
            MSG _msg;

            HINSTANCE _inst;
            std::string _title;

            static LRESULT CALLBACK WinProc(HWND hwnd, UINT msg, WPARAM wprm, LPARAM lprm);
            // --- END WINDOW FUNCTIONS/VARIABLES --- //

            // --- DIRECTX FUNCTIONS/VARIABLES --- //
            // D3D interfaces
            LPDIRECT3D9 _d3d;
            LPDIRECT3DDEVICE9 _d3ddev;
            D3DPRESENT_PARAMETERS _d3dpp;

            // directinput interfaces
            LPDIRECTINPUT8 _dInput;
            LPDIRECTINPUTDEVICE8 _diMouse;
            LPDIRECTINPUTDEVICE8 _diKeyboard;

            DIMOUSESTATE _mouseState;
            BYTE _keys[256];
            bool _keyStates[256];
            bool _keyboardStateChanged;

            void AcquireInputDevice(const LPDIRECTINPUTDEVICE8& dev);

            // sprite interfaces
            LPD3DXSPRITE _spriteBatch;

            // font vector
            std::vector<LPD3DXFONT> _fonts;

            // hresult checker, for debugging only
            void CheckForDXError(const char *file, int line, HRESULT hr);
            // --- END DIRECTX FUNCTIONS/VARIABLES --- //
    };

    /*=================================================*/
    /*--------------DIRECTX CONSTRUCTOR----------------*/
    /*=================================================*/
    DX9::DX9(HINSTANCE& inst, int cmdShow, const std::string& title, ush wndwidth, ush wndheight, short wndx, short wndy)
    {
        /*=================================================*/
        /*--------------WINDOW INITIALIZATION--------------*/
        /*=================================================*/
        _title = title;
        _inst = inst;

        // init window class struct
        _wc.cbClsExtra = NULL;
        _wc.cbSize = sizeof(WNDCLASSEX);
        _wc.cbWndExtra = NULL;
        _wc.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
        _wc.hCursor = LoadCursor(NULL, IDC_ARROW);
        _wc.hIcon = NULL;
        _wc.hIconSm = NULL;
        _wc.hInstance = inst;
        _wc.lpfnWndProc = (WNDPROC)WinProc;
        _wc.lpszClassName = title.c_str();
        _wc.lpszMenuName = NULL;
        _wc.style = CS_HREDRAW | CS_VREDRAW;
        RegisterClassEx(&_wc);

        // create handle to the window
        _hwnd = CreateWindow(title.c_str(),
                             title.c_str(),
                             WS_OVERLAPPEDWINDOW, 
                             wndx,
                             wndy,
                             wndwidth,
                             wndheight,
                             NULL,
                             NULL,
                             inst,
                             NULL);

        // required to make the window show up
        ShowWindow(_hwnd, cmdShow);
        UpdateWindow(_hwnd);
        /*=================================================*/
        /*--------------END WINDOW INITIALIZATION----------*/
        /*=================================================*/
        /*=================================================*/
        /*--------------DIRECTX INITIALIZATION-------------*/
        /*=================================================*/
        // --- INITIALIZE DIRECTX9 VARIABLES --- //
        SecureZeroMemory(&_d3dpp, sizeof(_d3dpp));
        SecureZeroMemory(&_mouseState, sizeof(_mouseState));
        SecureZeroMemory(&_keys, sizeof(_keys));

        for (int i = 0; i < 256; i++)
        {
            _keyStates[i] = true;
        }

        _d3d = NULL;
        _d3ddev = NULL;
        _dInput = NULL;
        _diMouse = NULL;
        _diKeyboard = NULL;
        _keyboardStateChanged = false;
        _spriteBatch = NULL;
        // --- END INITIALIZE DIRECTX9 VARIABLES --- //

        // --- DIRECTX9 INITIALIZATION --- //
        _d3d = Direct3DCreate9(D3D_SDK_VERSION);

        if (!_d3d)
        {
            OutputDebugString("Error: Failed to create Direct3D.\n");
        }

        // set d3d present parameters
        _d3dpp.AutoDepthStencilFormat = D3DFMT_D24S8;
        _d3dpp.BackBufferCount = 1;
        _d3dpp.BackBufferFormat = D3DFMT_X8R8G8B8;
        _d3dpp.BackBufferHeight = nssysprms::WND_HEIGHT;
        _d3dpp.BackBufferWidth = nssysprms::WND_WIDTH;
        _d3dpp.EnableAutoDepthStencil = 1;
        _d3dpp.Flags = D3DPRESENTFLAG_DISCARD_DEPTHSTENCIL;
        //_d3dpp.FullScreen_RefreshRateInHz
        _d3dpp.hDeviceWindow = _hwnd;
        //_d3dpp.MultiSampleQuality
        //_d3dpp.MultiSampleType
        _d3dpp.PresentationInterval = D3DPRESENT_INTERVAL_DEFAULT;
        _d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
        _d3dpp.Windowed = nssysprms::isWindowed;

        // create d3d device
        CheckHR(_d3d->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, _hwnd, D3DCREATE_MIXED_VERTEXPROCESSING, &_d3dpp, &_d3ddev));
        // --- END DIRECTX9 INITIALIZATION --- //

        // --- INITIALIZE DIRECTINPUT --- //
        CheckHR(DirectInput8Create(inst, DIRECTINPUT_VERSION, IID_IDirectInput8, (void**)&_dInput, NULL));

        // create mouse and keyboard
        CheckHR(_dInput->CreateDevice(GUID_SysKeyboard, &_diKeyboard, NULL));
        CheckHR(_dInput->CreateDevice(GUID_SysMouse, &_diMouse, NULL));

        // initialize keyboard
        CheckHR(_diKeyboard->SetDataFormat(&c_dfDIKeyboard));
        CheckHR(_diKeyboard->SetCooperativeLevel(_hwnd, DISCL_NONEXCLUSIVE | DISCL_FOREGROUND));
        AcquireInputDevice(_diKeyboard);

        // initialize mouse
        CheckHR(_diMouse->SetDataFormat(&c_dfDIMouse));
        CheckHR(_diMouse->SetCooperativeLevel(_hwnd, DISCL_NONEXCLUSIVE | DISCL_FOREGROUND));
        AcquireInputDevice(_diMouse);

        // create sprite object
        CheckHR(D3DXCreateSprite(_d3ddev, &_spriteBatch));
        // --- END INITIALIZE DIRECTINPUT --- //
        /*=================================================*/
        /*--------------END DIRECTX INITIALIZATION---------*/
        /*=================================================*/
    }
    /*=================================================*/
    /*--------------END DIRECTX CONSTRUCTOR------------*/
    /*=================================================*/
    /*=================================================*/
    /*--------------DIRECTX DESTRUCTOR-----------------*/
    /*=================================================*/
    DX9::~DX9()
    {
        // set all stack variables to NULL
        SecureZeroMemory(&_d3dpp, sizeof(_d3dpp));
        SecureZeroMemory(&_mouseState, sizeof(_mouseState));
        SecureZeroMemory(&_keys, sizeof(_keys));
        SecureZeroMemory(&_keyStates, sizeof(_keyStates));

        // free all the D3D interfaces from memory
        if (!_fonts.empty())
        {
            for (std::vector<LPD3DXFONT>::iterator it = _fonts.begin(); it != _fonts.end(); it++)
            {
                // SOLVEPROBLEM figure out why this doesn't work
                //*it->OnLostDevice();
            }

            _fonts.erase(_fonts.begin(), _fonts.end() - 1);
        }

        if (_spriteBatch != NULL)
        {
            _spriteBatch->Release();
            _spriteBatch = NULL;
        }

        if (_diKeyboard != NULL)
        {
            _diKeyboard->Release();
            _diKeyboard = NULL;
        }

        if (_diMouse != NULL)
        {
            _diMouse->Release();
            _diMouse = NULL;
        }

        if (_d3ddev != NULL)
        {
            _d3ddev->Release();
            _d3ddev = NULL;
        }

        if (_d3d != NULL)
        {
            _d3d->Release();
            _d3d = NULL;
        }

        // free the window class from memory
        UnregisterClass(_title.c_str(), _inst);
    }
    /*=================================================*/
    /*--------------END DIRECTX DESTRUCTOR-------------*/
    /*=================================================*/
    /*=================================================*/
    /*--------------HRESULT ERROR CHECK----------------*/
    /*=================================================*/
    void DX9::CheckForDXError(const char *file, int line, HRESULT hr)
    {
        if (SUCCEEDED(hr))
        {
            return;
        }

        // Get the direct X error and description
        char desc[1024];
        sprintf_s(desc,"(DX) %s - %s", DXGetErrorString(hr), DXGetErrorDescription(hr));

        // Output the file and line number in the correct format + the above DX error
        char buf[2048];
        sprintf_s(buf,"%s(%d) : Error: %s\n", file, line, desc);
        OutputDebugString(buf);
    }
    /*=================================================*/
    /*--------------END HRESULT ERROR CHECK------------*/
    /*=================================================*/
    /*=================================================*/
    /*--------------MESSAGE PROCESSOR------------------*/
    /*=================================================*/
    UINT DX9::ProcessMessages()
    {
        if (PeekMessage(&_msg, NULL, NULL, NULL, PM_REMOVE))
        {
            TranslateMessage(&_msg);
            DispatchMessage(&_msg);
        }

        return _msg.message;
    }
    /*=================================================*/
    /*--------------END MESSAGE PROCESSOR--------------*/
    /*=================================================*/
    /*=================================================*/
    /*--------------MESSAGE HANDLER--------------------*/
    /*=================================================*/
    LRESULT CALLBACK DX9::WinProc(HWND hwnd, UINT msg, WPARAM wprm, LPARAM lprm)
    {
        switch (msg)
        {
            case WM_DESTROY:
                PostQuitMessage(0);
                break;
        }

        return DefWindowProc(hwnd, msg, wprm, lprm);
    }
    /*=================================================*/
    /*--------------END MESSAGE HANDLER----------------*/
    /*=================================================*/
    /*=================================================*/
    /*--------------DIRECTINPUT FUNCTIONS--------------*/
    /*=================================================*/
    // for init only, helper function to initially acquire the
    // mouse and keyboard
    void DX9::AcquireInputDevice(const LPDIRECTINPUTDEVICE8& dev)
    {
        // loop and attempt to acquire the device until success
        while (FAILED(dev->Acquire()))
        {
            dev->Acquire();
        }
    }

    // update the state of the mouse and keyboard
    void DX9::InputUpdate()
    {
        _diKeyboard->GetDeviceState(sizeof(_keys), (LPVOID)_keys);
        _diMouse->GetDeviceState(sizeof(_mouseState), (LPVOID)&_mouseState);

        // after directinput has been updated, check to see if any keys are no,
        // longer pressed, and reset the keystate array at that key's index if,
        // this is the case
        // keystates true = key is available for key press
        if (_keyboardStateChanged)
        {
            for (int i = 0; i < 256; i++)
            {
                if (!KeyHeld(i))
                {
                    _keyStates[i] = true;
                }
            }
        }

        _keyboardStateChanged = false;
    }

    // captures a key being held down
    BYTE DX9::KeyHeld(ush key)
    {
        return _keys[key] & 0x80;
    }

    // captures a single key press
    bool DX9::KeyPressed(ush key)
    {
        if (KeyHeld(key) && _keyStates[key])
        {
            _keyStates[key] = false;
            return true;
        }
        else
        {
            if (!KeyHeld(key) && !_keyStates[key])
            {
                _keyboardStateChanged = true;
            }

            return false;
        }
    }
    /*=================================================*/
    /*--------------END DIRECTINPUT FUNCTIONS----------*/
    /*=================================================*/
    /*=================================================*/
    /*--------------SPRITE FUNCTIONS-------------------*/
    /*=================================================*/
    // returns the sprite interface
    const LPD3DXSPRITE& DX9::GetSpriteInterface()
    {
        return _spriteBatch;
    }

    // begin drawing with the sprite batch
    void DX9::SpriteBeginDraw(DWORD flags)
    {
        _spriteBatch->Begin(flags);
    }

    // end sprite batch drawing
    void DX9::SpriteEndDraw()
    {
        _spriteBatch->End();
    }
    /*=================================================*/
    /*--------------END SPRITE FUNCTIONS---------------*/
    /*=================================================*/
    /*=================================================*/
    /*--------------FONT FUNCTIONS---------------------*/
    /*=================================================*/
    // create a font
    void DX9::MakeFont(int height, int width, UINT weight, LPCSTR face, bool italic)
    {
        LPD3DXFONT newfont;

        CheckHR(D3DXCreateFont(_d3ddev,
                               height,
                               width,
                               weight,
                               0,
                               italic,
                               DEFAULT_CHARSET,
                               OUT_DEFAULT_PRECIS, 
                               CLEARTYPE_QUALITY,
                               DEFAULT_PITCH | FF_DONTCARE,
                               face,
                               &newfont));

        _fonts.push_back(newfont);
    }

    // gets a font at the specified index
    const LPD3DXFONT& DX9::GetFontAtIndex(ush index)
    {
        return _fonts[index];
    }

    const std::vector<LPD3DXFONT>& DX9::GetFontVector()
    {
        return _fonts;
    }
    /*=================================================*/
    /*--------------END FONT FUNCTIONS-----------------*/
    /*=================================================*/
}
#endif

除了创建和初始化窗口、DirectX 和一些基本的 DirectX 函数。

实际错误是这样的:

Error   1   error LNK2005: "public: __thiscall nsdx9::DX9::DX9(struct HINSTANCE__ * &,int,class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > const &,unsigned short,unsigned short,short,short)" (??0DX9@nsdx9@@QAE@AAPAUHINSTANCE__@@HABV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@GGFF@Z) already defined in game_manager.obj C:\Users\JAREK\documents\visual studio 2010\Projects\example\example\main.obj

dx9.h 中的每个函数都会重复此错误。如果我只在 main.cpp 中包含 dx9.h,则不会收到此错误。只有当我在任何其他 cpp 文件中包含 dx9.h,或者在 cpp 文件中使用 dx9.h 中的任何参数(通过包含在 main.cpp 中的 dx9.h 之后才能访问 dx9.h)时,我才会得到此信息错误。这听起来令人困惑,所以这里是程序其他部分的一些示例:

main.cpp:

#include "sys_params.h"
#include "dx9.h"
#include "game_manager.h"

int WINAPI WinMain (HINSTANCE inst, HINSTANCE pinst, LPSTR cmdLine, int cmdShow)
{
    // state of the program
    bool appEnd = false;

    // create and initialize the window and directx9
    nsdx9::DX9* _dx9 = new nsdx9::DX9(inst, cmdShow, nssysprms::GAME_TITLE,
                                      nssysprms::WND_WIDTH, nssysprms::WND_HEIGHT,
                                      nssysprms::WND_POS_X, nssysprms::WND_POS_Y);

    // create and initialize the game manager
    Game_Manager* _mngr = new Game_Manager(_dx9);

    // Windows message handler
    // also the entry point for the main game loop
    while (_dx9->ProcessMessages() != WM_QUIT && !appEnd)
    {
        if (!_mngr->Game_Run())
        {
            appEnd = true;
        }
    }

    // clean up everything
    delete _mngr;
    delete _dx9;

    return 0;
}

game_manager.h:

#ifndef _GAME_MANAGER_H_
#define _GAME_MANAGER_H_

#include <stack>
#include <vector>
#include "dx9.h"
#include "screen.h"
#include "message_handler.h"

class Game_Manager
{
    public:
        Game_Manager(nsdx9::DX9* dx9);
        ~Game_Manager();
        bool Game_Run();

    private:
        nsdx9::DX9* _dx9;
        std::stack<Screen*> _screens;
        Message_Handler* _msg_hnd;

        // *** DECLARE SCREENS HERE *** //

        void InitFonts();
        void InitScreens();
};
#endif

这应该是实际导致问题的原因。该问题源自 main.cpp 到 game_manager.h。我尝试过的任何方法都没有为我解决问题。我在 dx9.h 中包含了标头防护,所以我不知道是什么原因导致的。如果你们需要更多信息,请告诉我。谢谢!

I'm having a very frustrating issue setting up a DirectX 9 (irrelevant to the issue.. I think) framework in VS 2010. Here is my DirectX framework:

#ifndef _DX9_H_
#define _DX9_H_

// window includes
#define WIN32_LEAN_AND_MEAN
#include <Windows.h>

// required for ush typedef and window properties to setup backbuffer
#include "sys_params.h"

// directx9 includes
#define DIRECTINPUT_VERSION 0x0800
#include <d3dx9.h>
#include <dinput.h>
#include <DxErr.h>
#include <vector>
#include <iterator>

// directx9 libraries
#pragma comment(lib, "d3d9.lib")
#pragma comment(lib, "d3dx9.lib")
#pragma comment(lib, "dinput8.lib")
#pragma comment(lib, "dxguid.lib")
#pragma comment(lib, "dxerr.lib")

namespace nsdx9
{
    using nssysprms::ush;

    #define CheckHR(hr) CheckForDXError(__FILE__, __LINE__, hr)

    class DX9
    {
        public:
            DX9(HINSTANCE& inst, int cmdShow, const std::string& title, ush wndwidth, ush wndheight, short wndx, short wndy);
            ~DX9();

            // windows message processor
            UINT ProcessMessages();

            // --- DIRECTX GAME FUNCTIONS --- //
            // input functions
            void InputUpdate();
            BYTE KeyHeld(ush key);
            bool KeyPressed(ush key);

            // sprite functions
            const LPD3DXSPRITE& GetSpriteInterface();
            void SpriteBeginDraw(DWORD flags = D3DXSPRITE_ALPHABLEND);
            void SpriteEndDraw();

            // font functions
            void MakeFont(int height, int width, UINT weight = FW_DONTCARE, LPCSTR face = "Calibri", bool italic = false);
            const LPD3DXFONT& GetFontAtIndex(ush index);
            const std::vector<LPD3DXFONT>& GetFontVector();
            // --- END DIRECTX GAME FUNCTIONS --- //

        private:
            // --- WINDOW FUNCTIONS/VARIABLES --- //
            WNDCLASSEX _wc;
            HWND _hwnd;
            MSG _msg;

            HINSTANCE _inst;
            std::string _title;

            static LRESULT CALLBACK WinProc(HWND hwnd, UINT msg, WPARAM wprm, LPARAM lprm);
            // --- END WINDOW FUNCTIONS/VARIABLES --- //

            // --- DIRECTX FUNCTIONS/VARIABLES --- //
            // D3D interfaces
            LPDIRECT3D9 _d3d;
            LPDIRECT3DDEVICE9 _d3ddev;
            D3DPRESENT_PARAMETERS _d3dpp;

            // directinput interfaces
            LPDIRECTINPUT8 _dInput;
            LPDIRECTINPUTDEVICE8 _diMouse;
            LPDIRECTINPUTDEVICE8 _diKeyboard;

            DIMOUSESTATE _mouseState;
            BYTE _keys[256];
            bool _keyStates[256];
            bool _keyboardStateChanged;

            void AcquireInputDevice(const LPDIRECTINPUTDEVICE8& dev);

            // sprite interfaces
            LPD3DXSPRITE _spriteBatch;

            // font vector
            std::vector<LPD3DXFONT> _fonts;

            // hresult checker, for debugging only
            void CheckForDXError(const char *file, int line, HRESULT hr);
            // --- END DIRECTX FUNCTIONS/VARIABLES --- //
    };

    /*=================================================*/
    /*--------------DIRECTX CONSTRUCTOR----------------*/
    /*=================================================*/
    DX9::DX9(HINSTANCE& inst, int cmdShow, const std::string& title, ush wndwidth, ush wndheight, short wndx, short wndy)
    {
        /*=================================================*/
        /*--------------WINDOW INITIALIZATION--------------*/
        /*=================================================*/
        _title = title;
        _inst = inst;

        // init window class struct
        _wc.cbClsExtra = NULL;
        _wc.cbSize = sizeof(WNDCLASSEX);
        _wc.cbWndExtra = NULL;
        _wc.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
        _wc.hCursor = LoadCursor(NULL, IDC_ARROW);
        _wc.hIcon = NULL;
        _wc.hIconSm = NULL;
        _wc.hInstance = inst;
        _wc.lpfnWndProc = (WNDPROC)WinProc;
        _wc.lpszClassName = title.c_str();
        _wc.lpszMenuName = NULL;
        _wc.style = CS_HREDRAW | CS_VREDRAW;
        RegisterClassEx(&_wc);

        // create handle to the window
        _hwnd = CreateWindow(title.c_str(),
                             title.c_str(),
                             WS_OVERLAPPEDWINDOW, 
                             wndx,
                             wndy,
                             wndwidth,
                             wndheight,
                             NULL,
                             NULL,
                             inst,
                             NULL);

        // required to make the window show up
        ShowWindow(_hwnd, cmdShow);
        UpdateWindow(_hwnd);
        /*=================================================*/
        /*--------------END WINDOW INITIALIZATION----------*/
        /*=================================================*/
        /*=================================================*/
        /*--------------DIRECTX INITIALIZATION-------------*/
        /*=================================================*/
        // --- INITIALIZE DIRECTX9 VARIABLES --- //
        SecureZeroMemory(&_d3dpp, sizeof(_d3dpp));
        SecureZeroMemory(&_mouseState, sizeof(_mouseState));
        SecureZeroMemory(&_keys, sizeof(_keys));

        for (int i = 0; i < 256; i++)
        {
            _keyStates[i] = true;
        }

        _d3d = NULL;
        _d3ddev = NULL;
        _dInput = NULL;
        _diMouse = NULL;
        _diKeyboard = NULL;
        _keyboardStateChanged = false;
        _spriteBatch = NULL;
        // --- END INITIALIZE DIRECTX9 VARIABLES --- //

        // --- DIRECTX9 INITIALIZATION --- //
        _d3d = Direct3DCreate9(D3D_SDK_VERSION);

        if (!_d3d)
        {
            OutputDebugString("Error: Failed to create Direct3D.\n");
        }

        // set d3d present parameters
        _d3dpp.AutoDepthStencilFormat = D3DFMT_D24S8;
        _d3dpp.BackBufferCount = 1;
        _d3dpp.BackBufferFormat = D3DFMT_X8R8G8B8;
        _d3dpp.BackBufferHeight = nssysprms::WND_HEIGHT;
        _d3dpp.BackBufferWidth = nssysprms::WND_WIDTH;
        _d3dpp.EnableAutoDepthStencil = 1;
        _d3dpp.Flags = D3DPRESENTFLAG_DISCARD_DEPTHSTENCIL;
        //_d3dpp.FullScreen_RefreshRateInHz
        _d3dpp.hDeviceWindow = _hwnd;
        //_d3dpp.MultiSampleQuality
        //_d3dpp.MultiSampleType
        _d3dpp.PresentationInterval = D3DPRESENT_INTERVAL_DEFAULT;
        _d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
        _d3dpp.Windowed = nssysprms::isWindowed;

        // create d3d device
        CheckHR(_d3d->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, _hwnd, D3DCREATE_MIXED_VERTEXPROCESSING, &_d3dpp, &_d3ddev));
        // --- END DIRECTX9 INITIALIZATION --- //

        // --- INITIALIZE DIRECTINPUT --- //
        CheckHR(DirectInput8Create(inst, DIRECTINPUT_VERSION, IID_IDirectInput8, (void**)&_dInput, NULL));

        // create mouse and keyboard
        CheckHR(_dInput->CreateDevice(GUID_SysKeyboard, &_diKeyboard, NULL));
        CheckHR(_dInput->CreateDevice(GUID_SysMouse, &_diMouse, NULL));

        // initialize keyboard
        CheckHR(_diKeyboard->SetDataFormat(&c_dfDIKeyboard));
        CheckHR(_diKeyboard->SetCooperativeLevel(_hwnd, DISCL_NONEXCLUSIVE | DISCL_FOREGROUND));
        AcquireInputDevice(_diKeyboard);

        // initialize mouse
        CheckHR(_diMouse->SetDataFormat(&c_dfDIMouse));
        CheckHR(_diMouse->SetCooperativeLevel(_hwnd, DISCL_NONEXCLUSIVE | DISCL_FOREGROUND));
        AcquireInputDevice(_diMouse);

        // create sprite object
        CheckHR(D3DXCreateSprite(_d3ddev, &_spriteBatch));
        // --- END INITIALIZE DIRECTINPUT --- //
        /*=================================================*/
        /*--------------END DIRECTX INITIALIZATION---------*/
        /*=================================================*/
    }
    /*=================================================*/
    /*--------------END DIRECTX CONSTRUCTOR------------*/
    /*=================================================*/
    /*=================================================*/
    /*--------------DIRECTX DESTRUCTOR-----------------*/
    /*=================================================*/
    DX9::~DX9()
    {
        // set all stack variables to NULL
        SecureZeroMemory(&_d3dpp, sizeof(_d3dpp));
        SecureZeroMemory(&_mouseState, sizeof(_mouseState));
        SecureZeroMemory(&_keys, sizeof(_keys));
        SecureZeroMemory(&_keyStates, sizeof(_keyStates));

        // free all the D3D interfaces from memory
        if (!_fonts.empty())
        {
            for (std::vector<LPD3DXFONT>::iterator it = _fonts.begin(); it != _fonts.end(); it++)
            {
                // SOLVEPROBLEM figure out why this doesn't work
                //*it->OnLostDevice();
            }

            _fonts.erase(_fonts.begin(), _fonts.end() - 1);
        }

        if (_spriteBatch != NULL)
        {
            _spriteBatch->Release();
            _spriteBatch = NULL;
        }

        if (_diKeyboard != NULL)
        {
            _diKeyboard->Release();
            _diKeyboard = NULL;
        }

        if (_diMouse != NULL)
        {
            _diMouse->Release();
            _diMouse = NULL;
        }

        if (_d3ddev != NULL)
        {
            _d3ddev->Release();
            _d3ddev = NULL;
        }

        if (_d3d != NULL)
        {
            _d3d->Release();
            _d3d = NULL;
        }

        // free the window class from memory
        UnregisterClass(_title.c_str(), _inst);
    }
    /*=================================================*/
    /*--------------END DIRECTX DESTRUCTOR-------------*/
    /*=================================================*/
    /*=================================================*/
    /*--------------HRESULT ERROR CHECK----------------*/
    /*=================================================*/
    void DX9::CheckForDXError(const char *file, int line, HRESULT hr)
    {
        if (SUCCEEDED(hr))
        {
            return;
        }

        // Get the direct X error and description
        char desc[1024];
        sprintf_s(desc,"(DX) %s - %s", DXGetErrorString(hr), DXGetErrorDescription(hr));

        // Output the file and line number in the correct format + the above DX error
        char buf[2048];
        sprintf_s(buf,"%s(%d) : Error: %s\n", file, line, desc);
        OutputDebugString(buf);
    }
    /*=================================================*/
    /*--------------END HRESULT ERROR CHECK------------*/
    /*=================================================*/
    /*=================================================*/
    /*--------------MESSAGE PROCESSOR------------------*/
    /*=================================================*/
    UINT DX9::ProcessMessages()
    {
        if (PeekMessage(&_msg, NULL, NULL, NULL, PM_REMOVE))
        {
            TranslateMessage(&_msg);
            DispatchMessage(&_msg);
        }

        return _msg.message;
    }
    /*=================================================*/
    /*--------------END MESSAGE PROCESSOR--------------*/
    /*=================================================*/
    /*=================================================*/
    /*--------------MESSAGE HANDLER--------------------*/
    /*=================================================*/
    LRESULT CALLBACK DX9::WinProc(HWND hwnd, UINT msg, WPARAM wprm, LPARAM lprm)
    {
        switch (msg)
        {
            case WM_DESTROY:
                PostQuitMessage(0);
                break;
        }

        return DefWindowProc(hwnd, msg, wprm, lprm);
    }
    /*=================================================*/
    /*--------------END MESSAGE HANDLER----------------*/
    /*=================================================*/
    /*=================================================*/
    /*--------------DIRECTINPUT FUNCTIONS--------------*/
    /*=================================================*/
    // for init only, helper function to initially acquire the
    // mouse and keyboard
    void DX9::AcquireInputDevice(const LPDIRECTINPUTDEVICE8& dev)
    {
        // loop and attempt to acquire the device until success
        while (FAILED(dev->Acquire()))
        {
            dev->Acquire();
        }
    }

    // update the state of the mouse and keyboard
    void DX9::InputUpdate()
    {
        _diKeyboard->GetDeviceState(sizeof(_keys), (LPVOID)_keys);
        _diMouse->GetDeviceState(sizeof(_mouseState), (LPVOID)&_mouseState);

        // after directinput has been updated, check to see if any keys are no,
        // longer pressed, and reset the keystate array at that key's index if,
        // this is the case
        // keystates true = key is available for key press
        if (_keyboardStateChanged)
        {
            for (int i = 0; i < 256; i++)
            {
                if (!KeyHeld(i))
                {
                    _keyStates[i] = true;
                }
            }
        }

        _keyboardStateChanged = false;
    }

    // captures a key being held down
    BYTE DX9::KeyHeld(ush key)
    {
        return _keys[key] & 0x80;
    }

    // captures a single key press
    bool DX9::KeyPressed(ush key)
    {
        if (KeyHeld(key) && _keyStates[key])
        {
            _keyStates[key] = false;
            return true;
        }
        else
        {
            if (!KeyHeld(key) && !_keyStates[key])
            {
                _keyboardStateChanged = true;
            }

            return false;
        }
    }
    /*=================================================*/
    /*--------------END DIRECTINPUT FUNCTIONS----------*/
    /*=================================================*/
    /*=================================================*/
    /*--------------SPRITE FUNCTIONS-------------------*/
    /*=================================================*/
    // returns the sprite interface
    const LPD3DXSPRITE& DX9::GetSpriteInterface()
    {
        return _spriteBatch;
    }

    // begin drawing with the sprite batch
    void DX9::SpriteBeginDraw(DWORD flags)
    {
        _spriteBatch->Begin(flags);
    }

    // end sprite batch drawing
    void DX9::SpriteEndDraw()
    {
        _spriteBatch->End();
    }
    /*=================================================*/
    /*--------------END SPRITE FUNCTIONS---------------*/
    /*=================================================*/
    /*=================================================*/
    /*--------------FONT FUNCTIONS---------------------*/
    /*=================================================*/
    // create a font
    void DX9::MakeFont(int height, int width, UINT weight, LPCSTR face, bool italic)
    {
        LPD3DXFONT newfont;

        CheckHR(D3DXCreateFont(_d3ddev,
                               height,
                               width,
                               weight,
                               0,
                               italic,
                               DEFAULT_CHARSET,
                               OUT_DEFAULT_PRECIS, 
                               CLEARTYPE_QUALITY,
                               DEFAULT_PITCH | FF_DONTCARE,
                               face,
                               &newfont));

        _fonts.push_back(newfont);
    }

    // gets a font at the specified index
    const LPD3DXFONT& DX9::GetFontAtIndex(ush index)
    {
        return _fonts[index];
    }

    const std::vector<LPD3DXFONT>& DX9::GetFontVector()
    {
        return _fonts;
    }
    /*=================================================*/
    /*--------------END FONT FUNCTIONS-----------------*/
    /*=================================================*/
}
#endif

This really doesn't do anything but create and initialize a window, DirectX and some basic DirectX functions.

The actual error is this:

Error   1   error LNK2005: "public: __thiscall nsdx9::DX9::DX9(struct HINSTANCE__ * &,int,class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > const &,unsigned short,unsigned short,short,short)" (??0DX9@nsdx9@@QAE@AAPAUHINSTANCE__@@HABV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@GGFF@Z) already defined in game_manager.obj C:\Users\JAREK\documents\visual studio 2010\Projects\example\example\main.obj

This error is repeated for every single function in dx9.h. If I ONLY include dx9.h in main.cpp, I do not get this error. It is only if I include dx9.h in any other cpp file, or use any of the parameters in dx9.h in cpp files that have access to dx9.h by being included after dx9.h in main.cpp that I get this error. This sounds confusing, so here are some samples from other parts of the program:

main.cpp:

#include "sys_params.h"
#include "dx9.h"
#include "game_manager.h"

int WINAPI WinMain (HINSTANCE inst, HINSTANCE pinst, LPSTR cmdLine, int cmdShow)
{
    // state of the program
    bool appEnd = false;

    // create and initialize the window and directx9
    nsdx9::DX9* _dx9 = new nsdx9::DX9(inst, cmdShow, nssysprms::GAME_TITLE,
                                      nssysprms::WND_WIDTH, nssysprms::WND_HEIGHT,
                                      nssysprms::WND_POS_X, nssysprms::WND_POS_Y);

    // create and initialize the game manager
    Game_Manager* _mngr = new Game_Manager(_dx9);

    // Windows message handler
    // also the entry point for the main game loop
    while (_dx9->ProcessMessages() != WM_QUIT && !appEnd)
    {
        if (!_mngr->Game_Run())
        {
            appEnd = true;
        }
    }

    // clean up everything
    delete _mngr;
    delete _dx9;

    return 0;
}

game_manager.h:

#ifndef _GAME_MANAGER_H_
#define _GAME_MANAGER_H_

#include <stack>
#include <vector>
#include "dx9.h"
#include "screen.h"
#include "message_handler.h"

class Game_Manager
{
    public:
        Game_Manager(nsdx9::DX9* dx9);
        ~Game_Manager();
        bool Game_Run();

    private:
        nsdx9::DX9* _dx9;
        std::stack<Screen*> _screens;
        Message_Handler* _msg_hnd;

        // *** DECLARE SCREENS HERE *** //

        void InitFonts();
        void InitScreens();
};
#endif

This should be what is actually causing the issue. The issue is originating from main.cpp through game_manager.h. Nothing I've tried has solved the problem for me. I've included header guards in dx9.h, so I have no idea what could be causing this. if you guys need more information, please let me know. Thanks!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

探春 2024-12-18 20:22:22

您对 DX9 方法的定义(而不只是类定义)似乎位于 dx9.h 头文件中 - 因此,当您将 dx9.h 包含在多个 .cpp 文件中。要解决此问题,请将方法实现移至 .cpp 文件(例如 dx9.cpp)。

Your definitions of the DX9 methods (as opposed to just the class definition) seem to be in the dx9.h header file - so you violate C++'s one-definition rule when you include dx9.h in multiple .cpp files. To solve this, move the method implementations into a .cpp file (e.g. dx9.cpp).

私野 2024-12-18 20:22:22

不要在头文件中包含实现。这会导致在包含它的所有地方再次编译实现。

例如:

/*=================================================*/
/*--------------DIRECTX CONSTRUCTOR----------------*/
/*=================================================*/
DX9::DX9(HINSTANCE& inst, int cmdShow, const std::string& title, ush wndwidth, ush wndheight, short wndx, short wndy)
    {
    ....  et al

将其放入自己的 cpp 中

Don't include the implementation in the header file. This causes the implementation to be compiled again everywhere it is included.

for example:

/*=================================================*/
/*--------------DIRECTX CONSTRUCTOR----------------*/
/*=================================================*/
DX9::DX9(HINSTANCE& inst, int cmdShow, const std::string& title, ush wndwidth, ush wndheight, short wndx, short wndy)
    {
    ....  et al

put that in it's own cpp

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文