Jump to content

  • Log In with Google      Sign In   
  • Create Account

#ifndef not working


Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.

  • You cannot reply to this topic
24 replies to this topic

#1 Hawkblood   Members   -  Reputation: 725

Like
0Likes
Like

Posted 23 March 2014 - 07:40 AM

Ok. I have decided to try my hand at DX11. I'm starting from scratch here because the "empty project" provided by the SDK has a butt-load of crap that I don't want to use right now (just want to learn the basics). Until now I've been using only one .cpp file and all others were .h files. Each class had 2 .h files, one for the header info and the other for the functions. I know this is bad practice, but it was the only way I could control the compile order. I WANT TO CORRECT THIS! So here is my project as it stands:

Main.cpp:

 

 

globals.h:

#ifndef GLOBALS_H
#define GLOBALS_H
#include <windows.h>  
#include <windowsx.h>

void Init3D(HWND hWnd);
void GameLoop(void);
void RenderFrame(void);
void ExitProgram(void);


float SCREEN_WIDTH =float(GetSystemMetrics( SM_CXSCREEN ));
float SCREEN_HEIGHT = float(GetSystemMetrics( SM_CYSCREEN ));


#include "Graphics.h"

#endif


Graphics.h:

#include <d3d11.h>
#include <d3dx11.h>
#include <d3dx10.h>
#pragma comment (lib, "C:/Program Files (x86)/Microsoft DirectX SDK (June 2010)/Lib/x86/d3d11.lib")
#pragma comment (lib, "C:/Program Files (x86)/Microsoft DirectX SDK (June 2010)/Lib/x86/d3dx11.lib")
#pragma comment (lib, "C:/Program Files (x86)/Microsoft DirectX SDK (June 2010)/Lib/x86/d3dx10.lib")

IDXGISwapChain *swapchain;             // the pointer to the swap chain interface
ID3D11Device *dev;                     // the pointer to our Direct3D device interface
ID3D11DeviceContext *devcon;           // the pointer to our Direct3D device context

void InitD3D(HWND hWnd);     // sets up and initializes Direct3D
void CleanD3D(void);         // closes Direct3D and releases memory


Graphics.cpp:

#include "globals.h"

void InitD3D(HWND hWnd)
{
    // create a struct to hold information about the swap chain
    DXGI_SWAP_CHAIN_DESC scd;

    // clear out the struct for use
    ZeroMemory(&scd, sizeof(DXGI_SWAP_CHAIN_DESC));

    // fill the swap chain description struct
    scd.BufferCount = 1;                                    // one back buffer
    scd.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;     // use 32-bit color
    scd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;      // how swap chain is to be used
    scd.OutputWindow = hWnd;                                // the window to be used
    scd.SampleDesc.Count = 4;                               // how many multisamples
    scd.Windowed = TRUE;                                    // windowed/full-screen mode

    // create a device, device context and swap chain using the information in the scd struct
    D3D11CreateDeviceAndSwapChain(NULL,
                                  D3D_DRIVER_TYPE_HARDWARE,
                                  NULL,
                                  NULL,
                                  NULL,
                                  NULL,
                                  D3D11_SDK_VERSION,
                                  &scd,
                                  &swapchain,
                                  &dev,
                                  NULL,
                                  &devcon);
}
void CleanD3D()
{
    // close and release all existing COM objects
    swapchain->Release();
    dev->Release();
    devcon->Release();
}

The problem is that the compiler says that the stuff in globals.h is already defined:

Error	1	error LNK2005: "float SCREEN_WIDTH" (?SCREEN_WIDTH@@3MA) already defined in Grapgics.obj	C:\Empty DX11 Project1\main.obj	Empty DX11 Project1
Error	2	error LNK2005: "struct ID3D11DeviceContext * devcon" (?devcon@@3PAUID3D11DeviceContext@@A) already defined in Grapgics.obj	C:\Empty DX11 Project1\main.obj	Empty DX11 Project1
Error	3	error LNK2005: "struct ID3D11Device * dev" (?dev@@3PAUID3D11Device@@A) already defined in Grapgics.obj	C:\Empty DX11 Project1\main.obj	Empty DX11 Project1
Error	4	error LNK2005: "struct IDXGISwapChain * swapchain" (?swapchain@@3PAUIDXGISwapChain@@A) already defined in Grapgics.obj	C:\Empty DX11 Project1\main.obj	Empty DX11 Project1
Error	5	error LNK2005: "float SCREEN_HEIGHT" (?SCREEN_HEIGHT@@3MA) already defined in Grapgics.obj	C:\Empty DX11 Project1\main.obj	Empty DX11 Project1
Error	6	error LNK1169: one or more multiply defined symbols found	C:\Empty DX11 Project1\Release\DX11Test.exe	Empty DX11 Project1

Doesn't the "#ifndef" stuff work? Am I using it wrong? HOW DO I GET IT TO "DEFINE" ONLY ONCE?



					
					

Edited by Hawkblood, 23 March 2014 - 08:10 AM.


Sponsor:

#2 Hawkblood   Members   -  Reputation: 725

Like
0Likes
Like

Posted 23 March 2014 - 07:44 AM

I can't seem to get main.cpp to copy onto the post. Here is another attempt:

#include "globals.h"
LRESULT WINAPI WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);  
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInst, LPSTR lpCmdLine,int nShow)
{
	MSG msg;
	WNDCLASSEX wc = {sizeof(WNDCLASSEX), CS_VREDRAW|CS_HREDRAW|CS_OWNDC, 
		WndProc, 0, 0, hInstance, NULL, NULL, (HBRUSH)(COLOR_WINDOW+1), 
		NULL, "DX11_CLASS", NULL}; 
	RegisterClassEx(&wc);
	HWND hMainWnd = CreateWindow("DX11_CLASS", 
		"DirectX 11 Bare Bones", 
		WS_EX_TOPMOST | WS_POPUP, 0, 0, int(SCREEN_WIDTH), int(SCREEN_HEIGHT), 
		NULL, NULL, hInstance, NULL);
	ShowWindow(hMainWnd, nShow);
	UpdateWindow(hMainWnd);
	Init3D(hMainWnd);
	while(GetMessage(&msg, NULL, 0, 0))
	{
		TranslateMessage(&msg);
		DispatchMessage(&msg);
	}
	ExitProgram();
	return(0);
} 

LRESULT WINAPI WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam){
	switch(msg)
	{
	case WM_DESTROY:
		PostQuitMessage(0);
		return(0);

	case WM_PAINT: // <— ADD THIS BLOCK
		// drawing code goes here…
		GameLoop();
		ValidateRect(hwnd, NULL);
		return(0);

	case WM_CHAR:

		switch(wParam){
			case VK_ESCAPE:
				PostMessage(hwnd,WM_QUIT,0,0);
				break;
		}
		break;

	}

	return(DefWindowProc(hwnd, msg, wParam, lParam));
}

void Init3D(HWND hWnd){
//will be calling Graphics class to initialize 
}
void GameLoop(void){
	//check DX device
	//frame move
	//render
	RenderFrame();
}
void RenderFrame(void){
}
void ExitProgram(void){
// call Graphics class to clear device objects
}

I HAD TO BREAK IT UP IN CHUNKS FOR IT TO SHOW ON THE POST. WTF!







 

 

 




Edited by Hawkblood, 23 March 2014 - 08:07 AM.


#3 rip-off   Moderators   -  Reputation: 8737

Like
8Likes
Like

Posted 23 March 2014 - 08:07 AM

float SCREEN_WIDTH =float(GetSystemMetrics( SM_CXSCREEN ));
float SCREEN_HEIGHT = float(GetSystemMetrics( SM_CYSCREEN ));
These are variable definitions. C++ says you may only define a variable once, and because your header file is included in multiple locations you are getting those errors. The same goes for the globals in Graphics.h.

Note that the include guards are working fine. What include guards prevent is a given header file being included more than once during compilation of a given source file. The classic C++ compilation model is that each source file (.cpp) is compiled once in isolation. This involves running the preprocessor (which is a glorified automatic copy & paste tool) to create a so-called translation unit, which is then compiled to an object file (note: terminology pre-dates object-orientation, an "object" here is more or less any non-local C++ identifier). Interesting to note that the C++ compiler proper sees the output of the pre-processor, not the original code you wrote! Finally, when that process completes for all source files, the linker is invoked on the object files, which fixes up references between them to produce an executable.

So to clarify the problem, each source file compiles perfectly, but each object file ends up containing a SCREEN_WIDTH and SCREEN_HEIGHT object. The linker is confused, it has no way to know that these are really the "same" objects (the information is literally lost in translation!), it complains just as if you accidentally created two separate globals with the same name, perhaps with separate values, in two source files.

Note there are special rules for certain things, such as const integral values, inline functions or member functions defined in a class body, and static values.

The solution is to follow the rules in Organizing code files in C and C++, in this case declare these variables in a header file and define them in a single source file. Alternative solutions might be to convert some values to inline functions, or try to avoid using globals altogether.

Edited by rip-off, 23 March 2014 - 08:43 AM.


#4 Hawkblood   Members   -  Reputation: 725

Like
0Likes
Like

Posted 23 March 2014 - 08:26 AM

Ok. I declared them in globals.h and defined them in Graphics.cpp within void Init3D(HWND hWnd)

I get this:

Error	1	error LNK2005: "float SCREEN_WIDTH" (?SCREEN_WIDTH@@3MA) already defined in Grapgics.obj	C:\Empty DX11 Project1\main.obj	Empty DX11 Project1
Error	2	error LNK2005: "struct ID3D11DeviceContext * devcon" (?devcon@@3PAUID3D11DeviceContext@@A) already defined in Grapgics.obj	C:\Empty DX11 Project1\main.obj	Empty DX11 Project1
Error	3	error LNK2005: "struct ID3D11Device * dev" (?dev@@3PAUID3D11Device@@A) already defined in Grapgics.obj	C:\Empty DX11 Project1\main.obj	Empty DX11 Project1
Error	4	error LNK2005: "float SCREEN_HEIGHT" (?SCREEN_HEIGHT@@3MA) already defined in Grapgics.obj	C:\Empty DX11 Project1\main.obj	Empty DX11 Project1
Error	5	error LNK2005: "struct IDXGISwapChain * swapchain" (?swapchain@@3PAUIDXGISwapChain@@A) already defined in Grapgics.obj	C:\Empty DX11 Project1\main.obj	Empty DX11 Project1
Error	6	error LNK1169: one or more multiply defined symbols found	C:\Empty DX11 Project1\Release\DX11Test.exe	Empty DX11 Project1

Which, to me, looks the same....... Also, I can't find the article you linked me to. The link just goes to a list of articles. I searched through them and didn't find the one you were pointing me to.



#5 rip-off   Moderators   -  Reputation: 8737

Like
1Likes
Like

Posted 23 March 2014 - 08:46 AM

Sorry, had some issues with the editor, the link should be fixed now. Can we see your current code?

#6 Guns   Members   -  Reputation: 150

Like
2Likes
Like

Posted 23 March 2014 - 08:47 AM

Use headers for declarations only and define in source files.

 

Declare this way:

// Keyword "extern" basically means "declare something that's defined somewhere else".
extern float SCREEN_WIDTH;
extern float SCREEN_HEIGHT;

extern IDXGISwapChain *swapchain;
extern ID3D11Device *dev;
extern ID3D11DeviceContext *devcon;

Define this way:

float SCREEN_WIDTH = float(GetSystemMetrics(SM_CXSCREEN));
float SCREEN_HEIGHT = float(GetSystemMetrics(SM_CYSCREEN));

// Always initialize your variables, in this case a pointer to null.
IDXGISwapChain *swapchain = nullptr;
ID3D11Device *dev = nullptr;
ID3D11DeviceContext *devcon = nullptr;

Also, you forgot a header guard in the "Graphics.h".


Edited by Guns, 23 March 2014 - 08:52 AM.


#7 Hawkblood   Members   -  Reputation: 725

Like
0Likes
Like

Posted 23 March 2014 - 09:21 AM

I hope I corrected the issues with "main.cpp" that kept me from posting the code. Here is the attempt:

main.cpp:

#include "stdafx.h"
#include "globals.h"

LRESULT WINAPI WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);  
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInst, LPSTR lpCmdLine,int nShow)
{
	MSG msg;
	WNDCLASSEX wc = {sizeof(WNDCLASSEX), CS_VREDRAW|CS_HREDRAW|CS_OWNDC, 
		WndProc, 0, 0, hInstance, NULL, NULL, (HBRUSH)(COLOR_WINDOW+1), 
		NULL, "DX11_CLASS", NULL}; 
	RegisterClassEx(&wc);
	HWND hMainWnd = CreateWindow("DX11_CLASS", 
		"DirectX 11 Bare Bones", 
		WS_EX_TOPMOST | WS_POPUP, 0, 0, int(SCREEN_WIDTH), int(SCREEN_HEIGHT), 
		NULL, NULL, hInstance, NULL);
	ShowWindow(hMainWnd, nShow);
	UpdateWindow(hMainWnd);
	Init3D(hMainWnd);
	while(GetMessage(&msg, NULL, 0, 0))
	{
		TranslateMessage(&msg);
		DispatchMessage(&msg);
	}
	ExitProgram();
	return(0);
} 
LRESULT WINAPI WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam){
	switch(msg)
	{
	case WM_DESTROY:
		PostQuitMessage(0);
		return(0);
	case WM_PAINT: // <— ADD THIS BLOCK
		// drawing code goes here…
		GameLoop();
		ValidateRect(hwnd, NULL);
		return(0);
	case WM_CHAR:
		switch(wParam){
			case VK_ESCAPE:
				PostMessage(hwnd,WM_QUIT,0,0);
				break;
		}
		break;
	}

	return(DefWindowProc(hwnd, msg, wParam, lParam));
}
void Init3D(HWND hWnd){
//will be calling Graphics class to initialize 
	Graphics.InitD3D(hWnd,SCREEN_WIDTH,SCREEN_HEIGHT);
}
void GameLoop(void){
	//check DX device
	//frame move
	//render
	RenderFrame();
}
void RenderFrame(void){
	Graphics.devcon->ClearRenderTargetView(Graphics.backbuffer, D3DXCOLOR(0.0f, 0.2f, 0.4f, 1.0f));



	Graphics.swapchain->Present(0, 0);
}
void ExitProgram(void){
// call Graphics class to clear device objects
	Graphics.CleanD3D();
}

stdafx.h:

#include <windows.h>  
#include <windowsx.h>

void Init3D(HWND hWnd);
void GameLoop(void);
void RenderFrame(void);
void ExitProgram(void);


#include "Graphics.h"

Graphics.h:

#include <d3d11.h>
#include <d3dx11.h>
#include <d3dx10.h>
#pragma comment (lib, "C:/Program Files (x86)/Microsoft DirectX SDK (June 2010)/Lib/x86/d3d11.lib")
#pragma comment (lib, "C:/Program Files (x86)/Microsoft DirectX SDK (June 2010)/Lib/x86/d3dx11.lib")
#pragma comment (lib, "C:/Program Files (x86)/Microsoft DirectX SDK (June 2010)/Lib/x86/d3dx10.lib")

struct GRAPHICS{
	IDXGISwapChain *swapchain;             // the pointer to the swap chain interface
	ID3D11Device *dev;                     // the pointer to our Direct3D device interface
	ID3D11DeviceContext *devcon;           // the pointer to our Direct3D device context

	ID3D11RenderTargetView *backbuffer;


	void InitD3D(HWND hWnd,float SW,float SH);     // sets up and initializes Direct3D
	void CleanD3D(void);         // closes Direct3D and releases memory
};

Graphics.cpp:

#include "stdafx.h"


void GRAPHICS::InitD3D(HWND hWnd,float SW,float SH)
{
    // create a struct to hold information about the swap chain
    DXGI_SWAP_CHAIN_DESC scd;

    // clear out the struct for use
    ZeroMemory(&scd, sizeof(DXGI_SWAP_CHAIN_DESC));

    // fill the swap chain description struct
    scd.BufferCount = 1;                                    // one back buffer
    scd.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;     // use 32-bit color
    scd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;      // how swap chain is to be used
    scd.OutputWindow = hWnd;                                // the window to be used
    scd.SampleDesc.Count = 4;                               // how many multisamples
    scd.Windowed = TRUE;                                    // windowed/full-screen mode

    // create a device, device context and swap chain using the information in the scd struct
    D3D11CreateDeviceAndSwapChain(NULL,
                                  D3D_DRIVER_TYPE_HARDWARE,
                                  NULL,
                                  NULL,
                                  NULL,
                                  NULL,
                                  D3D11_SDK_VERSION,
                                  &scd,
                                  &swapchain,
                                  &dev,
                                  NULL,
                                  &devcon);

	// get the address of the back buffer
	ID3D11Texture2D *pBackBuffer;
	swapchain->GetBuffer(0, __uuidof(ID3D11Texture2D), (LPVOID*)&pBackBuffer);
	// use the back buffer address to create the render target
	dev->CreateRenderTargetView(pBackBuffer, NULL, &backbuffer);
	pBackBuffer->Release();
	// set the render target as the back buffer
	devcon->OMSetRenderTargets(1, &backbuffer, NULL);

	D3D11_VIEWPORT viewport;
	ZeroMemory(&viewport, sizeof(D3D11_VIEWPORT));
	viewport.TopLeftX = 0;
	viewport.TopLeftY = 0;
	viewport.Width = SW;
	viewport.Height = SH;
	devcon->RSSetViewports(1, &viewport);

}
void GRAPHICS::CleanD3D()
{
    // close and release all existing COM objects
    swapchain->Release();
	backbuffer->Release();
    dev->Release();
    devcon->Release();
}

globals.h:

#include <windows.h>  
#include <windowsx.h>

float SCREEN_WIDTH =float(GetSystemMetrics( SM_CXSCREEN ));
float SCREEN_HEIGHT = float(GetSystemMetrics( SM_CYSCREEN ));

GRAPHICS Graphics;

I modified the project so that I wouldn't get the errors. Now my concern is "how will this screw up my project?"


Edited by Hawkblood, 23 March 2014 - 09:22 AM.


#8 rip-off   Moderators   -  Reputation: 8737

Like
4Likes
Like

Posted 23 March 2014 - 09:33 AM

You'd need to amend globals.h to be like so:
#include <windows.h>  
#include <windowsx.h>

extern float SCREEN_WIDTH;
extern float SCREEN_HEIGHT;

extern GRAPHICS Graphics;
And to add a globals.cpp (or to another file such as main.cpp):
#include "globals.h"

float SCREEN_WIDTH = float(GetSystemMetrics( SM_CXSCREEN ));
float SCREEN_HEIGHT = float(GetSystemMetrics( SM_CYSCREEN ));

GRAPHICS Graphics;
You'll probably need to #include "graphics.h" in globals.h too.

#9 Buckeye   Crossbones+   -  Reputation: 6312

Like
1Likes
Like

Posted 23 March 2014 - 10:35 AM

First, I would recommend that you NOT declare functions in stdafx.h. Any time you change anything in stdafx.h, you'll likely have to recompile the entire project.

 

I.e., these forward declarations belong in a header (e.g., main.h - which you don't appear to have) for main.cpp, where those functions are defined.

void Init3D(HWND hWnd);
void GameLoop(void);
void RenderFrame(void);
void ExitProgram(void);

If, for instance, you just want to add an exit code and change ExitProgram(void) to ExitProgram(int returnCode), you'll have to recompile every cpp file that includes stdafx.h, whether ExitProgram is called in that cpp file or not.

 

In general, header files describe what can be found in an associated code file. E.g., graphics.h describes what can be found in graphics.cpp; commonStuff.h would describe what's in commonStuff.cpp, etc.


Edited by Buckeye, 23 March 2014 - 10:36 AM.

Please don't PM me with questions. Post them in the forums for everyone's benefit, and I can embarrass myself publicly.


#10 Hawkblood   Members   -  Reputation: 725

Like
0Likes
Like

Posted 23 March 2014 - 12:20 PM


First, I would recommend that you NOT declare functions in stdafx.h. Any time you change anything in stdafx.h, you'll likely have to recompile the entire project.

That's not a real concern right now, but I moved them to main.cpp anyway....

 

@rip-off

I tried that. I got lots of errors. So far the only place I need any kind of global variables is in main.cpp, so I made a "main.h" and placed all those variables and function definitions in that.



#11 Buckeye   Crossbones+   -  Reputation: 6312

Like
0Likes
Like

Posted 23 March 2014 - 02:06 PM


so I made a "main.h" and placed all those variables and function definitions in that.

Hopefully you meant "declarations." Don't put the definitions in a header!


Please don't PM me with questions. Post them in the forums for everyone's benefit, and I can embarrass myself publicly.


#12 rip-off   Moderators   -  Reputation: 8737

Like
1Likes
Like

Posted 23 March 2014 - 02:25 PM

I tried that. I got lots of errors.

Please post the revised code, and the error messages. I have not tried to compile your code, but something like that should work. For example, I didn't include the header guards in globals.h, you'll still need them. And as mentioned, if you're declaring a global instance of Graphics, you'll need to include graphics.h in globals.h.

I'd second Buckeye's suggestion to remove all references to your functions and headers from stdafx.h. Unless you really know what you're doing, it is probably best to reserve stdafx.h for referencing external headers (like Windows.h) that really are used everywhere. In fact, it might be best to leave stdafx.h empty for the time being until you've figured out this problem first.

#13 Hawkblood   Members   -  Reputation: 725

Like
1Likes
Like

Posted 24 March 2014 - 10:04 AM


I'd second Buckeye's suggestion to remove all references to your functions and headers from stdafx.h. Unless you really know what you're doing, it is probably best to reserve stdafx.h for referencing external headers (like Windows.h) that really are used everywhere. In fact, it might be best to leave stdafx.h empty for the time being until you've figured out this problem first.

The problem with doing that is I have dependencies that require a certain order of "inclusion". I can't depend on the compiler to look through the header files in the right order.

 


Please post the revised code

I have a lot of code to look at now. I could post it if you think it will help, but here is the gist of what I have done:

--I have a header file for each .cpp file

--Each header file is "#included" is the stdafx.h file (in the order I need them)

--Each header file has:

     #ifndef (header name in all caps such as GLOBALS_H)

     #define (header name in all caps such as GLOBALS_H)

     ..... all the stuff needed in the header file.......

     #endif

--Each .cpp file "#includes" the stdafx.h file

--stdafx.h has the same #ifndef / #define / #endif stuff as all the other headers

 

Here is the errors I'm getting when I do this:

Error	1	error LNK2005: "float SCREEN_WIDTH" (?SCREEN_WIDTH@@3MA) already defined in globals.obj	C:\Empty DX11 Project1\Grapgics.obj	Empty DX11 Project1
Error	2	error LNK2005: "float SCREEN_HEIGHT" (?SCREEN_HEIGHT@@3MA) already defined in globals.obj	C:\Empty DX11 Project1\Grapgics.obj	Empty DX11 Project1
Error	3	error LNK2005: "struct GRAPHICS Graphics" (?Graphics@@3UGRAPHICS@@A) already defined in globals.obj	C:\Empty DX11 Project1\Grapgics.obj	Empty DX11 Project1
Error	4	error LNK2005: "float SCREEN_WIDTH" (?SCREEN_WIDTH@@3MA) already defined in globals.obj	C:\Empty DX11 Project1\LargeMath.obj	Empty DX11 Project1
Error	5	error LNK2005: "float SCREEN_HEIGHT" (?SCREEN_HEIGHT@@3MA) already defined in globals.obj	C:\Empty DX11 Project1\LargeMath.obj	Empty DX11 Project1
Error	6	error LNK2005: "struct GRAPHICS Graphics" (?Graphics@@3UGRAPHICS@@A) already defined in globals.obj	C:\Empty DX11 Project1\LargeMath.obj	Empty DX11 Project1
Error	7	error LNK2005: "float SCREEN_WIDTH" (?SCREEN_WIDTH@@3MA) already defined in globals.obj	C:\Empty DX11 Project1\main.obj	Empty DX11 Project1
Error	8	error LNK2005: "float SCREEN_HEIGHT" (?SCREEN_HEIGHT@@3MA) already defined in globals.obj	C:\Empty DX11 Project1\main.obj	Empty DX11 Project1
Error	9	error LNK2005: "struct GRAPHICS Graphics" (?Graphics@@3UGRAPHICS@@A) already defined in globals.obj	C:\Empty DX11 Project1\main.obj	Empty DX11 Project1
Error	10	error LNK2005: "float SCREEN_WIDTH" (?SCREEN_WIDTH@@3MA) already defined in globals.obj	C:\Empty DX11 Project1\MeshObject.obj	Empty DX11 Project1
Error	11	error LNK2005: "float SCREEN_HEIGHT" (?SCREEN_HEIGHT@@3MA) already defined in globals.obj	C:\Empty DX11 Project1\MeshObject.obj	Empty DX11 Project1
Error	12	error LNK2005: "struct GRAPHICS Graphics" (?Graphics@@3UGRAPHICS@@A) already defined in globals.obj	C:\Empty DX11 Project1\MeshObject.obj	Empty DX11 Project1
Error	13	error LNK2005: "float SCREEN_WIDTH" (?SCREEN_WIDTH@@3MA) already defined in globals.obj	C:\Empty DX11 Project1\Text.obj	Empty DX11 Project1
Error	14	error LNK2005: "float SCREEN_HEIGHT" (?SCREEN_HEIGHT@@3MA) already defined in globals.obj	C:\Empty DX11 Project1\Text.obj	Empty DX11 Project1
Error	15	error LNK2005: "struct GRAPHICS Graphics" (?Graphics@@3UGRAPHICS@@A) already defined in globals.obj	C:\Empty DX11 Project1\Text.obj	Empty DX11 Project1
Error	16	error LNK1169: one or more multiply defined symbols found	C:\Empty DX11 Project1\Release\DX11Test.exe	1	1	Empty DX11 Project1
	17	IntelliSense: command-line error: invalid macro definition: /MDd	c:\Empty DX11 Project1\Text.cpp	1	1	Empty DX11 Project1

The /MDd error only shows up when the other errors do. When I change it to the way I *was* doing it, that error doesn't occur.....



#14 Buckeye   Crossbones+   -  Reputation: 6312

Like
0Likes
Like

Posted 24 March 2014 - 10:35 AM

From the errors you listed, it appears you're still defining (not declaring but defining) globals in header files. Either that, or you're defining the same global in more than one cpp file.

 

That is, it appears that some header file has something like:

float SCREEN_WIDTH; // not in a header file!

instead of

extern float SCREEN_WIDTH;

Check for that problem, and also ensure that float SCREEN_WIDTH; appears in only one cpp file.

 

 


Each header file is "#included" is the stdafx.h file (in the order I need them)

Two things:

 

First: if header files other than system-related files (sdkver, windows, etc.) have to be in a particular order, that's an indication of a potential problem. Can you describe why the order of header files makes a difference?

 

Second: As mentioned, stdafx.h should be reserved for information that all (or most) cpp files need - things like windows.x, etc. Including all project header files in stdafx.h isn't recommended. Cpp files should have include only those header files that are needed.

 

You may not want to try it at this point, but the #ifndef HEADER/#define HEADER/#endif can be replaced with a single #pragma once at the very top of the file.

 

EDIT: with regard to structs: [EDIT: deleted some incorrect terminology about structs - apologies]


Edited by Buckeye, 24 March 2014 - 11:12 AM.

Please don't PM me with questions. Post them in the forums for everyone's benefit, and I can embarrass myself publicly.


#15 Hawkblood   Members   -  Reputation: 725

Like
0Likes
Like

Posted 24 March 2014 - 01:22 PM

I need some variables as global variables so that they may be used in multiple .cpp files. Exactly how should I do this? Should I use:

extern float WhateverVariable;

in a header file?

#16 rip-off   Moderators   -  Reputation: 8737

Like
3Likes
Like

Posted 24 March 2014 - 04:24 PM

I'd recommend starting simple, you've a lot going on in your current program, so it is difficult to diagnose what is happening. Can you create a new project to try a simpler program - two source files and a header.

The following should work:

globals.h
#ifndef GLOBALS_H
#define GLOBALS_H

extern float SCREEN_WIDTH;
extern float SCREEN_HEIGHT;

#endif

globals.cpp:
#include "globals.h"

float SCREEN_WIDTH = 13.0f;
float SCREEN_HEIGHT = 42.0f;

main.cpp:
#include "globals.h"
#include <iostream>

int main() {
	std::cout << "Screen: " << SCREEN_WIDTH << "x" << SCREEN_HEIGHT << std::endl;
}

You can either disable pre-compiled headers, or just include an empty one for the time being until you have a successful build.

#17 Hawkblood   Members   -  Reputation: 725

Like
0Likes
Like

Posted 24 March 2014 - 05:26 PM

That gives me:

Error	1	error LNK2005: "float SCREEN_WIDTH" (?SCREEN_WIDTH@@3MA) already defined in globals.obj	C:\Empty DX11 Project1\main.obj	Empty DX11 Project1
Error	2	error LNK2005: "float SCREEN_HEIGHT" (?SCREEN_HEIGHT@@3MA) already defined in globals.obj	C:\Empty DX11 Project1\main.obj	Empty DX11 Project1
Error	3	error LNK1169: one or more multiply defined symbols found	C:\Empty DX11 Project1\Release\DX11Test.exe	Empty DX11 Project1

I tried playing with PCH, but all I got were errors.

 

The main thing is that I want to have *some* global variables. These would be common-use variables like the graphics interface. I want to do this so I don't have to send a reference each time some part of the program needs a pointer to the device......



#18 Hawkblood   Members   -  Reputation: 725

Like
0Likes
Like

Posted 24 March 2014 - 05:35 PM

GOT IT! 

in stdafx.h I (extern) declare:

extern GRAPHICS *GE;//my graphics interface pointer 

 

and in main.h I actually declare it:

GRAPHICS *GE;

 

this gives me "global" availability of the variable.................



#19 Buckeye   Crossbones+   -  Reputation: 6312

Like
0Likes
Like

Posted 25 March 2014 - 04:23 AM

GOT IT! 

in stdafx.h I (extern) declare:

extern GRAPHICS *GE;//my graphics interface pointer 

 

and in main.h I actually declare it:

GRAPHICS *GE;

 

this gives me "global" availability of the variable.................

 

Actually, you don't got it. sad.png

 

First: GRAPHICS *GE both declares GE AND defines it.

 

Read this --> Don't define variables in header files. If you must have a global variable, define it in a CPP file.

 

Also, if you're going to define a global variable, it's good practice to initialize it. I.e., GRAPHICS *GE = NULL;

 

 


I WANT TO CORRECT THIS!


Just trying to help out, Hawkblood. You posted this thread, looking to solve a problem, but you're ignoring the solution.


Edited by Buckeye, 25 March 2014 - 05:32 AM.

Please don't PM me with questions. Post them in the forums for everyone's benefit, and I can embarrass myself publicly.


#20 rip-off   Moderators   -  Reputation: 8737

Like
0Likes
Like

Posted 25 March 2014 - 05:01 AM

Works for me:

user@host:~/help$ for file in globals.{h,cpp} main.cpp; do echo "${file}:"; cat $file; done
globals.h:
#ifndef GLOBALS_H
#define GLOBALS_H
 
extern float SCREEN_WIDTH;
extern float SCREEN_HEIGHT;
 
#endif
 
globals.cpp:
#include "globals.h"
 
float SCREEN_WIDTH = 13.0f;
float SCREEN_HEIGHT = 42.0f;
main.cpp:
#include "globals.h"
#include <iostream>
 
int main() {
std::cout << "Screen: " << SCREEN_WIDTH << "x" << SCREEN_HEIGHT << std::endl;
}
user@host:~/help$ g++ main.cpp globals.cpp -o help
user@host:~/help$ ./help
Screen: 13x42
 

 


GOT IT! 

...

and in main.h I actually declare it:

GRAPHICS *GE;

This will appear to work fine if main.h is only #included into a single source file (i.e. main.cpp). Remember #include is glorified copy and paste - the compiler will see a file that ends with the contents of main.cpp with the contents of every included file at the top (assuming the convention where #include occurs at the top of the file).

 

If another source file #includes main.h, this will stop "working".






Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.



PARTNERS