Visual Studio 2010 Pro 的链接器问题
我在 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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
您对 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 thedx9.h
header file - so you violate C++'s one-definition rule when you includedx9.h
in multiple .cpp files. To solve this, move the method implementations into a .cpp file (e.g.dx9.cpp
).不要在头文件中包含实现。这会导致在包含它的所有地方再次编译实现。
例如:
将其放入自己的 cpp 中
Don't include the implementation in the header file. This causes the implementation to be compiled again everywhere it is included.
for example:
put that in it's own cpp