Defining global variables over multiple files outside main loop - c++

I know it's not very good, but I need global variables across multiple files in my program. These are my graphics window's variables:
Name
Size
Status
.
I know I can make a .h file and declare all variables:
#pragma once
extern std::string GameName;
extern sf::RenderWindow Window;
extern std::string Status;
.
Then I want to define my variables in my main.cpp, so all files can access these values. But I cannot define these unless they are in the int main() loop. Is there another way, so I can define these variables not in main loop?
EDIT
Using Visual Studio 2017.
Errors:
LNK2001 unresolved external symbol "class sf::RenderWindow Window"
(?Window##3VRenderWindow#sf##A) Cubes
Library C:\Users\George\Documents\C++\Files\Libraries\Cubes
Library\Cubes Library\Cubes Library.obj 1
.
LNK2001 unresolved external symbol "class
std::basic_string,class
std::allocator > Status"
(?Status##3V?$basic_string#DU?$char_traits#D#std##V?$allocator#D#2##std##A) Cubes
Library C:\Users\George\Documents\C++\Files\Libraries\Cubes
Library\Cubes Library\Cubes Library.obj 1
.
LNK1120 2 unresolved externals Cubes
Library C:\Users\George\Documents\C++\Files\Libraries\Cubes
Library\Debug\Cubes Library.dll 1

You can declare them in your main.cpp file, but in order to make them globally accessible, you have to define them outside your main function/loop. If you decalre them inside your main function/loop, they are local variables and cannot (easily) be accessed globally. Doing it this way combined with the header file you suggested will work.
// Global variables...
std::string GameName;
sf::RenderWindow Window;
std::string Status;
int main()
{
return 0;
}
You could also put them in another file, for example globals.cpp.

You would do it like this...
File: Main.h
#ifndef __MAIN_H__
#define __MAIN_H__
#include <string>
extern std::string GameName;
//extern sf::RenderWindow Window;
extern std::string Status;
#endif
File: Main.cpp
#include "stdafx.h"
#include <iostream>
#include "Main.h"
std::string GameName;
//sf::RenderWindow Window;
std::string Status;
extern void foo(); // Function Prototype
int main()
{
GameName = "none";
Status = "none";
foo();
std::cout << GameName << " - " << Status << std::endl;
std::cout << "(HIT A KEY TO CONTINUE)" << std::endl;
getchar();
return 0;
}
File: Other.cpp
#include "stdafx.h"
#include "Main.h"
void foo()
{
// Global variables declared in Main.cpp are now accessible here
GameName = "Horizon New Dawn";
Status = "Finished";
}

This is how to do it using globals in a DLL.
// File: DLLGlobals.h
// This file is used in the DLL project
#ifndef __GLOBALS_H__
#define __GLOBALS_H__
#include <string>
extern "C"
{
extern __declspec(dllexport) std::string GameName;
extern __declspec(dllexport) std::string Status;
}
#endif//__GLOBALS_H__
// File: DLLGlobals.cpp
#include "stdafx.h"
#include "DLLGlobals.h"
extern "C"
{
// Define Global Variables (no C++ mangling)
__declspec(dllexport) std::string GameName = "Dishonored 2";
__declspec(dllexport) std::string Status = "Not Started";
}
// File: DLL.h
#ifndef __DLL_H__
#define __DLL_H__
// This file is included by code using the DLL project
#include <string>
extern "C"
{
__declspec(dllimport) std::string GameName;
__declspec(dllimport) std::string Status;
}
#endif//__DLL_H__
// File: Main.cpp
#include "stdafx.h"
#include <iostream>
#include "Main.h"
#include "<path_to_dll_header>\DLL.h"
int main()
{
std::cout << GameName << ": " << Status << std::endl;
std::cout << "(HIT A KEY TO CONTINUE)" << std::endl;
getchar();
return 0;
}

Related

"multiple definition of" while variable is not defined anywhere else in the scope

I have these three source files:
test.h
#ifndef __TESTH
#define __TESTH
#ifdef __cplusplus
#define EXTERNC extern "C"
#else
#define EXTERNC
#endif
typedef struct {
uint8_t value;
} my_struct;
EXTERNC void initialise();
EXTERNC void load(my_struct**);
#endif
test.cpp:
#include <cstdint>
#include "test.h"
my_struct test;
void initialise() {
test.value = 200;
}
void load(my_struct** struct_ptr) {
*struct_ptr = &test;
}
main.cpp:
#include <cstdint>
#include <iostream>
#include "test.h"
my_struct *test;
int main() {
initialise();
load(&test);
while (true) {
std::cout << test->value << std::endl;
}
}
When I compile it, the linker gives me an error telling me that test has been defined multiple times (first defined in test.cpp).
Why? To me it seems like it doesn't leave the scope of test.cpp.
And when I remove the definition of test in main.cpp, it gives me an undefined error!
Thank you for taking the time out of your day to help me.
I think you would need to scope test.cpp's test variable to that file only, assuming your test pointer in main.cpp is different than test in test.cpp
namespace {
my_struct test;
}
See here

C++ DLL import class unresolved external symbol

Hi I'm sorry I've seen that there is a lot of "unresolved external symbol error" questions, and I've seen them but none of the answers that I found fixed my error.
I've tested 2 ways to compile the DLL and use the HelloWorld method from SerialPort class.
btw I'm using VS2019 community edition
Both ways are throwing the same error :
Error LNK2019 unresolved external symbol "public: void __thiscall SerialPort::HelloWorld(void)" (?HelloWorld#SerialPort##QAEXXZ) referenced in function _main Test DriverCore C:\Users\$USER\source\repos\Test DriverCore\Test DriverCore\Main.obj 1
To what I've understood it's a linker error and the name of the method that I'm using is unresolved (not found) but I have no idea how to fix that (I thought that extern "C" prevented this to happen)
I've also tried to add #pragma comment(lib, "DriverCore.lib")(with DriverCore.lib in the same Dir as DriverCore.h) but still nothing :/
Way 1
using a function to return a pointer to the class
DriverCore.h
#pragma once
#ifdef DRIVERCORE_EXPORTS
#define DLLCALL __declspec(dllexport)
#else
#define DLLCALL __declspec(dllimport)
#endif
class SerialPort
{
private:
bool connected = 0;
public:
SerialPort() {};
void HelloWorld();
bool isConnected() { return 0; };
int readSerialPort(char* buffer, unsigned int buf_size) { return 0; };
bool writeSerialPort(char* buffer, unsigned int buf_size) { return 0; };
};
extern "C" {
DLLCALL SerialPort* __stdcall CreateSerialPort();
};
DriverCore.cpp
#include "pch.h"
#include "DriverCore.h"
#include <iostream>
#define DRIVERCORE_EXPORTS
BOOL APIENTRY DllMain( HMODULE hModule,DWORD ul_reason_for_call,LPVOID lpReserved)
{
return TRUE;
}
SerialPort* __stdcall CreateSerialPort()
{
return new SerialPort();
}
void SerialPort::HelloWorld()
{
std::cout << "Hello World !";
}
Main.cpp
#include "pch.h"
#include <Windows.h>
#include <iostream>
#include "DriverCore.h"
typedef SerialPort* (__stdcall *SerialPortImported) ();
int main()
{
// instantiate the dll location
HINSTANCE hDLL = LoadLibraryW(L"DriverCore.dll");
if (!hDLL) {
std::cout << "could not load the dynamic library" << std::endl;
return EXIT_FAILURE;
}
//Resolve Objects Addr
SerialPortImported pCSerialPort = (SerialPortImported) GetProcAddress(hDLL, "CreateSerialPort") ;
SerialPort* CSerialPort = pCSerialPort();
CSerialPort->HelloWorld();
return 0;
}
Way 2
without using extern "c" {...} but using __declspec directly onto the class declaration
DriverCore.h
#pragma once
#ifdef DRIVERCORE_EXPORTS
#define DLLCALL __declspec(dllexport)
#else
#define DLLCALL __declspec(dllimport)
#endif
class DLLCALL SerialPort
{
private:
bool connected = 0;
public:
SerialPort() {};
void HelloWorld();
bool isConnected() { return 0; };
int readSerialPort(char* buffer, unsigned int buf_size) { return 0; };
bool writeSerialPort(char* buffer, unsigned int buf_size) { return 0; };
};
DriverCore.cpp
#include "pch.h"
#include "DriverCore.h"
#include <iostream>
#define DRIVERCORE_EXPORTS
BOOL APIENTRY DllMain( HMODULE hModule,DWORD ul_reason_for_call,LPVOID lpReserved)
{
return TRUE;
}
void SerialPort::HelloWorld()
{
std::cout << "Hello World !";
}
Main.cpp
#include "pch.h"
#include <Windows.h>
#include <iostream>
#include "DriverCore.h"
int main()
{
// instantiate the dll location
HINSTANCE hDLL = LoadLibraryW(L"DriverCore.dll");
if (!hDLL) {
std::cout << "could not load the dynamic library" << std::endl;
return EXIT_FAILURE;
}
//Resolve Objects Addr
SerialPort* pSerialPort = (SerialPort*) GetProcAddress(hDLL, "SerialPort") ;
pSerialPort->HelloWorld();
return 0;
}
Thanks a lot in advance for your help !
You are calling HelloWorld which is missing its implementation in your application.
There is some fundamental misunderstanding about how C++ executables are compiled and linked against DLLs.
No libraries:
All symbols that the Application needs must be defined in the Application.
All needed symbol definitions must be available to the linker.
Static libraries:
All symbols that the Application needs must be defined in the Application or a static library.
All needed symbol definitions must be available to the linker.
The symbols are added to the generated Application's executable.
Dynamic libraries:
All symbols that the Application needs must be defined in the Application or a dynamiclibrary.
All needed symbol definitions must be available to the linker.
The symbols remain at their original places and they are loaded only at load time. This allows swap the dynamic libraries with any other ABI-compatible one at load time.
Since you are not linking with the dll and only load it at runtime, the linker correctly complains about the missing HelloWorld method.
Extern "C" is irrelevant here.

static and extern keywords LINK Error C++

I have wrote program to test static and extern keywords in C++.
source1.cpp
#include "Header.h"
using namespace std;
static int num;
int main(){
num = 1;
cout << num << endl;
func();
}
source2.cpp
#include "Header.h"
using namespace std;
extern int num;
void func(){
num = 100;
cout << num << endl;
}
Header.h
#ifndef HEADER_H
#define HEADER_H
#include <iostream>
void func();
#endif
When i compile this program it gives me a link error.
error LNK2001, LNk1120 unresolved externals.
What is the reason to causes this Link error?
This Link Error causes because of num variable declared as a static variable.
Even though the variable num is declared as an extern in the source2.cpp file, the linker won’t find it because it has been declared static in source1.cpp.
When you declared variable static, it is local to the file; it has file scope. That variable is unavailable outside of this file.

Compiler acts as if a preprocessor directive isn't defined

I have a header file and its cpp file (Error.h, Error.cpp). The cpp file performs a check on a preprocessor directive but it always fails.
Error.h:
/*
Optional macros:
AE_EXIT_AT_ERROR
AE_CONSOLE_WRITE_AT_ERROR
*/
#pragma once
extern void aeError(const char *str, int code=1);
extern void aeAssert(bool b, const char *failStr = "assertion failed");
Error.cpp:
#include "Error.h"
#include <stdexcept>
#ifdef AE_CONSOLE_WRITE_AT_ERROR
#include <iostream>
#endif
void aeError(const char *str, int code)
{
#ifdef AE_CONSOLE_WRITE_AT_ERROR
std::cout << str << std::endl;
#endif
throw std::runtime_error(str);
#ifdef AE_EXIT_AT_ERROR
std::exit(code);
#endif
}
void aeAssert(bool b, const char *failStr)
{
if(!b)
aeError(failStr);
}
main.cpp:
//define both macros:
#define AE_CONSOLE_WRITE_AT_ERROR
#define AE_EXIT_AT_ERROR
#include "Error.h"
//rest of code
//...
both std::cout << str << std::endl; and std::exit(code); don't get compiled (I checked it "manually", although they are also marked gray by the IDE, which is VS2010).
What might be the cause of this?
main.cpp and Error.cpp are different translation units. You define the macro only for main.cpp, not for Error.cpp.
You should either put your #define directives in a header file included by both .cpp files, or define these macros in project settings/makefile.

Reference C++ struct object in another file?

I'm in the process of trying to make a game-in-progress more modular. I'd like to be able to declare a single array of all the room_t objects in the game (room_t rooms[]), store it in world.cpp and call it from other files.
The truncated code below does not work, but it's as far as I've gotten. I think I need to use extern but have not been able to find a method that works correctly. If I try and declare the array in the header file, I get a duplicate object error (as each file calls world.h, I'd assume).
main.cpp
#include <iostream>
#include "world.h"
int main()
{
int currentLocation = 0;
cout << "Room: " << rooms[currentLocation].name << "\n";
// error: 'rooms' was not declared in this scope
cout << rooms[currentLocation].desc << "\n";
return 0;
}
world.h
#ifndef WORLD_H
#define WORLD_H
#include <string>
const int ROOM_EXIT_LIST = 10;
const int ROOM_INVENTORY_SIZE = 10;
struct room_t
{
std::string name;
std::string desc;
int exits[ROOM_EXIT_LIST];
int inventory[ROOM_INVENTORY_SIZE];
};
#endif
world.cpp
#include "world.h"
room_t rooms[] = {
{"Bedroom", "There is a bed in here.", {-1,1,2,-1} },
{"Kitchen", "Knives! Knives everywhere!", {0,-1,3,-1} },
{"Hallway North", "A long corridor.",{-1,-1,-1,0} },
{"Hallway South", "A long corridor.",{-1,-1,-1,1} }
};
Just add extern room_t rooms[]; in your world.h file.
world.h
extern room_t rooms[];
The problem is that you're trying to reference a variable you've declared in the .cpp file. There's no handle on this outside of the scope of this file. In order to fix this, why not declare the variable in the .h file but have an Init function:
room_t rooms[];
void Init();
Then in the .cpp
void Init() {
// create a room_t and copy it over
}