c++ link error, cannot find global.h struct - c++

I've defined a struct in a header file global.h, that i try to use it in a another class, but i get this error : Error 6 error LNK2001: unresolved external symbol "struct tag_KG_Data g_GlobalVar" (?g_GlobalVar##3Utag_KG_Data##A) KGComThread.obj
#ifndef GLOBAL_H_
#define GLOBAL_H_
#include <stdio.h>
typedef struct tag_KG_Data
{
int nKGStationID;
int nKGComPort;
}GLOBAL_VAR;
#endif
and in KGComThread.cpp file i use it like this:
#include "global.h"
extern GLOBAL_VAR g_GlobalVar;
I think the compiler can't find the global.h file so it defines a meaningless tag_KG_Data struct, but i can't understand why.

This
extern GLOBAL_VAR g_GlobalVar;
is only a declaration. The variable is not yet defined:
GLOBAL_VAR g_GlobalVar;
You need the previous line in a single implementation file.
Also, since this is C++, you don't need a tag for the struct, you can just write
struct GLOBAL_VAR
{
int nKGStationID;
int nKGComPort;
};

Related

Global initialized variable in a DLL

Is it possible to use a global variable from one DLL module to initialize global variable in other DLL module? If so, how?
I am using Microsoft Visual Studio 17.3.6 and use a C++/CLI wrapper class with some C files. I am in a bigger project but I have put together a smaller example that exhibits the behavior.
I would have thought that it would work like this. There are four files, file1.c, file1.h in one project and file2.c and file2.h in second project. They are built to two DLLs, file1.dll and file2.dll. First project has file1_EXPORTS preprocessor symbol defined and second has file2_EXPORTS defined. Include guards omitted for clarity.
file1.c:
#include <file1.h>
#include <file2.h>
structure1_t struct1 = {
&struct2
};
file1.h:
typedef struct
{
structure2_t* ptr;
} structure1_t;
#ifdef file1_EXPORTS
#define EXPORT_SYMBOL __declspec(dllexport)
#else
#define EXPORT_SYMBOL __declspec(dllimport)
#endif
EXPORT_SYMBOL structure1_t struct1;
file2.h:
typedef struct
{
int* i;
} structure2_t;
#if defined (file2_EXPORTS)
#define EXPORT_SYMBOL __declspec(dllexport)
#else
#define EXPORT_SYMBOL __declspec(dllimport)
#endif
EXPORT_SYMBOL structure2_t struct2;
file2.c:
#include <file2.h>
#include <file1.h>
int i;
structure2_t struct2 = {
&i
};
However, it cannot be compiled like this. There is an error C2099: initializer is not a constant. When I change the line (in file2.h) #define EXPORT_SYMBOL __declspec(dllimport) to #define EXPORT_SYMBOL extern, there are linker errors LNK2001: unresolved external symbol struct2 and LNK1120: 1 unresolved externals. Only combination that works for me is leaving the definition empty, e.g. #define EXPORT_SYMBOL. Other change that I must do is leave the definition in file1.h or the program fails in the next step.
Now those are built correctly and libraries file1.dll and file2.dll are created.
Assume that there is a third file file3.cpp which uses the DLLs:
#include <file1.h>
#include <file2.h>
#include <iostream>
int main(void)
{
std::cout << struct1.ptr << std::endl;
std::cout << struct2.i << std::endl;
return 0;
}
it prints:
0000000000000000
0000000000000000
So, my question is, is there some way this could work without the NULL pointers (e.g. struct1 has pointer to struct2 and struct2 has pointer to the integer)? Why is the program behaving like this, is it because file3.cpp sees only the declarations in the header and the variables are never initialized correctly? Other variant and solution would perhaps be to have an initialization function that puts the needed values to the structures. However, I am hesitant to doing this as I have a lot of structures that I would have to manually fill in. Or perhaps it could be filled in the DllMain as per here. Furthermore, I should mention that the C files have the extern "C" blocks in them.
I tried different combinations of __declspec(dllimport), __declspec(dllexport) and extern keywords but I cannot manage to make it work correctly. Also, putting EXPORT_SYMBOL to the C files as per Exporting global variables from DLL did not help either.
This answer would suggest that what I want to do is not possible but I do not know if it is relevant only to const variables or not.
What I was trying to do is not possible. Address of dllimported symbol cannot be used in an initializer of static data. I solved it by including the .c files with the structures' definition in each module that needed them. Structures themselves may stay extern when it is implemented this way. So with regards to my code examples, it would look like this:
file1.c:
#include <file1.h>
#include <file2.h>
#include <file2.c>
structure1_t struct1 = {
&struct2
};
file1.h:
typedef struct
{
structure2_t* ptr;
} structure1_t;
extern structure1_t struct1;
file2.h:
typedef struct
{
int* i;
} structure2_t;
extern structure2_t struct2;
file2.c:
#include <file2.h>
int i;
structure2_t struct2 = {
&i
};
(for illustration, have not tested it). This way, effectively no data are shared across DLLs as each one has its own copy. If data had to stay in the separate DLLs or if including the .c files was not possible, other solution would be not to have an initializer at all, use __declspec() instead of extern and initialize structures in a function call. However, I chose not to do that as I have hundreds of structures and it would not be feasible this way.

C++ LNK2005 error related to enum

I am getting LNK error 2005 due to the use of enum in header file. I am not sure what is wrong with it though. Is enum usually included in the header file?
Here is my code. I have 4 files: board.h, board.cpp, Solitaire.h, Solitaire.cpp.
board.h:
#ifndef BOARD_H__
#define BOARD_H__
#include <iostream>
using namespace std;
const int NUM_ROWS = 6;
const int NUM_COLS = 6;
enum PieceType {
HasPiece, NoPiece, Invalid
};
PieceType board_data[NUM_ROWS][NUM_COLS];
#endif
board.cpp:
#include "board.h"
Solitaire.h
#ifndef Solitaire_h__
#define Solitaire_h__
#include "board.h"
#endif
Solitaire.cpp
#include "Solitaire.h"
int main() {
}
The error I get is
Error LNK2005 "enum PieceType (* board_data)[6]"
(?board_data##3PAY05W4PieceType##A) already defined in board.obj
Thank you!
The problem has to do with including definitions in headers. This line
PieceType board_data[NUM_ROWS][NUM_COLS];
defines a new array board_data in each translation unit from which the header is included. To fix this issue, declare the array external, i.e.
extern PieceType board_data[NUM_ROWS][NUM_COLS];
After that, define the array in one of your CPP files.
Note: This problem is not about enum - you would get the same error with any other type.

Why linker is giving error for global variable in header file

I have declared a global variable in header.h and included that header in source.cpp and main.cpp but linker is giving error
Source.obj : error LNK2005: "int globalVariable" (?globalVariable##3HA) already defined in Main.obj
GlobalVariableAndLinkageIssue.exe fatal error LNK1169: one or more multiply defined symbols found
header.h
int globalVariable;
source.cpp
#include "header.h"
main.cpp
#include"header.h"
void main() {}
Move the declaration to a .cpp file. You can use a declaration in a header file by using:
extern int globalVariable; // declaration in header - can have as many as you need
But the .cpp file should have the definition:
int globalVariable; // definition in .cpp - only need one across all your files
C and C++ use textual pre-processor to include headers, this is basically a text insertion, not a smart module system as in some languages. By including it as you were, you are creating multiple definitions, one per .cpp file.
As a matter of good practice, you need to get used to using include guards to protect against multiple nested includes (though it would not solve your current issue). If using Visual C++, you can use #pragma once or to use a portable solution wrap your header code in:
#ifndef _INCLUDE_FOO_H_
#endif
To create a global variable, you should do the following. Note that in the header, we mark the variable as extern, and we actually create the object in a cpp file.
header.h
extern int globalVariable;
header.cpp
#include "header.h"
int globalVariable;
main.cpp
#include "header.h"
int main() {}
Put global variable in some .c or .cpp file, so that it can be defined only once and refer in header file using extern
for example,
header.h
extern int globalVariable;
header.cpp
int globalVariable = 0;
source.cpp
#include "header.h"
main.cpp
#include"header.h"
int main() {
return 0;
}
Because BOTH sources #include your header, and thus it is DEFINED twice.
In such situation,it is common to use some #define as follows:
//header.h
#ifdef DEFINE_VARS
#define DEFINE_OR_DECLARE
#else
#define DEFINE_OR_DECLARE extern
#endif
DEFINE_OR_DECLARE int globalVariable;
//main.cpp
#define DEFINE_VARS
#include "header.h"
...
//header.cpp
#include "header.h"
...

LNK2005: " already defined error

I am trying to use a global variable from separated .cpp files. I have got an init.h file as:
//init.h
#ifndef init
#define init
int a = 3;
#endif
I have got an init.cpp file as:
//init.cpp
#include init.h
Then finally my main.cpp file is:
//main.cpp
#include "init.h"
int main(void)
{
while(1)
{
}
}
After this, I get the error:
1>init.obj : error LNK2005: "int a" (?a##3HA) already defined in main.obj
1> ..deneme.exe : fatal error LNK1169: one or more multiply defined symbols found
Why my #infdef control does not solve this problem?. I also tried using #pragma once but I got same error. What is wrong with my code?
You need to mark your variable as extern and define it only once in an implementation file.
As the code is now, you're breaking the one definition rule. The include guards don't help in this case, since all translation units that include that header re-define the variable.
What you actually need:
//init.h
#ifndef init
#define init
extern int a;
#endif
and the definition:
//init.cpp
#include "init.h"
int a = 3;
Also, think twice before using globals. What is it that you're actually trying to achieve?

Multiple Definition (LNK2005) errors

I recently tried to create a global header file which would have all definitions of error codes (i.e. NO_ERROR, SDL_SCREEN_FLIP_ERROR, etc.) these would just be integers which I would define here.
I included these in both of my .cpp files, however I am getting an error where it is stated that I am defining then twice.
globals.h:
#pragma once
// error related globals
int SCREEN_LOAD_ERROR = 1;
int NO_ERROR = 0;
main.cpp:
#include "globals.h"
#include "cTile.h"
/* rest of the code */
cTile.h:
#pragma once
#include "globals.h"
class cTile {
};
It is complaining that SCREEN_LOAD_ERROR and NO_ERROR are defined twice, but as far as I know #pragma once should prevent this (I also tried #ifndef, but this also did not work).
compiler output:
1>main.obj : error LNK2005: "int SCREEN_LOAD_ERROR" (?SCREEN_LOAD_ERROR##3HA) already defined in cTile.obj
1>main.obj : error LNK2005: "int NO_ERROR" (?NO_ERROR##3HA) already defined in cTile.obj
Am I missing something?
Do not declare variables inside your header file.
When you declare a variable in header file a copy of the variable gets created in each translation unit where you include the header file.
Solution is:
Declare them extern inside one of your header file and define them in exactly one of your cpp file.
globals.h:
extern int SCREEN_LOAD_ERROR;
extern int NO_ERROR;
globals.cpp:
#include "globals.h"
int SCREEN_LOAD_ERROR = 0;
int NO_ERROR = 0;
main.cpp:
#include "globals.h"
cTile.h:
#include "globals.h"
You could simply use an enum:
globals.h:
enum
{
SCREEN_LOAD_ERROR = 1,
NO_ERROR = 0,
// ...
}
using #ifndef works fine.(Although it works, this is not best practice). try like this:
globals.h
#ifndef GLOBALS
#define GLOBALS
int SCREEN_LOAD_ERROR = 1;
int NO_ERROR = 0;
#endif
cTile.h:
#include "globals.h"
class cTile {
};
main.cpp:
#include "globals.h"
#include "cTile.h"
/* rest of the code */