2

Linking problem with Visual Studio 2010 Pro

 2 years ago
source link: https://www.codesd.com/item/linking-problem-with-visual-studio-2010-pro.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

Linking problem with Visual Studio 2010 Pro

advertisements

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!


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).


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK