I keep getting this Visual C++ 2010 LNK2005 linker error saying I have multiple definitions of two functions that are contained in "Error.h". (a header I made for error display)
My project is like this:
BaseImage.h
BaseImage.cpp --> includes BaseImage.h , Error.h
PNGImage.h --> includes BaseImage.h
PNGImage.cpp --> includes PNGImage.h , Error.h
main.cpp --> includes PNGImage.h
And, of course, Error.h:
/*
Optional macros:
AE_EXIT_AT_ERROR
*/
#pragma once
#include <stdexcept>
void aeError(const char *str, int code=1)
{
throw std::runtime_error(str);
#ifdef AE_EXIT_AT_ERROR
std::exit(code);
#endif
}
void aeAssert(bool b, const char *failStr = "assertion failed")
{
if(!b)
aeError(failStr);
}
I have #pragma once in every header file, and I tried adding include guards to Error.h as well.
Here's the compile output:
1>PNGImage.obj : error LNK2005: "void __cdecl aeError(char const *,int)" (?aeError##YAXPBDH#Z) already defined in BaseImage.obj
1>PNGImage.obj : error LNK2005: "void __cdecl aeAssert(bool,char const *)" (?aeAssert##YAX_NPBD#Z) already defined in BaseImage.obj
1>C:\...\Project.exe : fatal error LNK1169: one or more multiply defined symbols found
Could this be a bug?
When you define functions in a .h file, make them inline. Otherwise, the function definitions are part of the object code of all the .cpp files that #include it, with external linkage.
inline void aeError(const char *str, int code=1)
{
throw std::runtime_error(str);
#ifdef AE_EXIT_AT_ERROR
std::exit(code);
#endif
}
inline void aeAssert(bool b, const char *failStr = "assertion failed")
{
if(!b)
aeError(failStr);
}
The other option for you is to declare the functions in the .h file and define them in exactly one .cpp file.
The .h file:
extern void aeError(const char *str, int code=1);
extern void aeAssert(bool b, const char *failStr = "assertion failed");
The .cpp file:
// Don't use inline and don't include the default argument values.
void aeError(const char *str, int code)
{
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);
}
Related
I defined a function to show a message when debug flags are off in a header file as below:
#ifdef NDEBUG
#define debug_msg(expr, msg) (static_cast<void>(0))
#else /* Not NDEBUG. */
#ifndef SHOW_DEBUG_H_
#define SHOW_DEBUG_H_
#include <stdio.h>
void _show_in_debug(const char *_file, unsigned int _line,
const char *_function, const char *_msg)
{
printf("%s\t%d\t%s\t%s\n", _file, _line, _function, _msg);
fflush(NULL);
}
#endif
#define debug_msg(expr, msg) \
((expr) \
? _show_in_debug(__FILE__, __LINE__, __func__, msg) \
: static_cast<void>(0))
#endif
when I include the header in more than a file, I get the following error:
multiple definition of `_show_in_debug(char const*, unsigned int, char
const*, char const*)'
I don't exactly know what I am doing wrong here, any help ?
Even with the include guards, you end up with a definition of _show_in_debug in each compilation unit. Linking those units then results to a multiple definition error.
For a debugging function like this, define the function as static so that it is not visible outside its compilation unit:
static void _show_in_debug(const char *_file, unsigned int _line,
const char *_function, const char *_msg)
{
printf("%s\t%d\t%s\t%s\n", _file, _line, _function, _msg);
fflush(NULL);
}
If you include that header into more than one .c file, each of them will define the function. That is what the error says.
What you should do is to only declare the function in the header (i.e. only put the prototype there; which you always should) and then define it in a single .c file (i.e. put the body in the .c file), encapsulated into the same switches as the prototype.
Header to be changed to this:
/* ... as you quoted ... */
void _show_in_debug(const char *_file, unsigned int _line,
const char *_function, const char *_msg);
/* ... rest of what you quoted ... */
Code file to contain this:
#incude <stdio.h>
#include "Yourheader.h"
#ifdef NDEBUG
void _show_in_debug(const char *_file, unsigned int _line,
const char *_function, const char *_msg)
{
printf("%s\t%d\t%s\t%s\n", _file, _line, _function, _msg);
fflush(NULL);
}
#endif
I assume the file header file that you have presented is included in several source files. Why is this a problem? That is because you have defined your _show_in_debug() function in the header instead of declaring it in the header and defining it in a source file file. This leads to the function be defined in multiple source files that have included your header.
See http://www.cprogramming.com/declare_vs_define.html for more details (especially, see the "Common Cases" section).
I have a test dll. After event in dll I want use callback function from dll to exe.
test.dll
.h
extern "C" __declspec(dllimport) int __stdcall getSum(int , int );
extern "C" __declspec(dllexport) int __stdcall callSum(int , int );
.cpp
int callSum(int a, int b)
{
return getSum(a, b);
}
myexe
.cpp
extern "C" __declspec(dllexport)
int __stdcall getSum(int a, int b)
{
return a + b;
}
typedef int(__stdcall * callSumFn)(int a, int b);
and load
hLib=LoadLibrary(L"test.dll");
if(hLib==NULL)
{
...
return -1;
}
callSumFn callSum = (callSumFn)GetProcAddress(hLib, L"_callSum#8");
if (!callSum)
{
//cerr << "Failed to get function address" << endl;
FreeLibrary(hLib);
return 1;
}
callSum(3, 4);
Error:
Error 18 error LNK2019: unresolved external symbol __imp_getSum
referenced in function callSum test.obj test
with compile test.dll
whats wrong? Maybe there is a better way?
Thank you.
You have a circular dependency: the exe depends on callsum() from the dll and the dll depends on getsum() from the dll.
If you want a callback you need to define a function pointer and pass a function from the exe as a parameter to the dll function.
You have defined the variable function getSum in your DLL, but you haven't declared it. Declaring getSum in test.dll should rid you of the error.
I am working on a project for school. I am aware of my circular dependency(And have read most of the resolutions here for that previously) but it works currently the way I need it to. Sadly I'm pretty sure it is also the cause of my woes. I would like to include concol.h so that it can be used with both files (I'd like to add some color to my output - not a requirement for my assignment but something I would like to do). I've tried placement of this header file in several different locations and I always get the same errors. I considered using the forward declaration like I did to work with the circular dependency but I don't think that will work with a namespace.
Errors:
1>Flight.obj : error LNK2005: "void * eku::std_con_out" (?std_con_out#eku##3PAXA) already defined in BoardingPass.obj
1>Flight.obj : error LNK2005: "bool eku::colorprotect" (?colorprotect#eku##3_NA) already defined in BoardingPass.obj
1>Flight.obj : error LNK2005: "enum eku::concol eku::textcol" (?textcol#eku##3W4concol#1#A) already defined in BoardingPass.obj
1>Flight.obj : error LNK2005: "enum eku::concol eku::backcol" (?backcol#eku##3W4concol#1#A) already defined in BoardingPass.obj
1>Flight.obj : error LNK2005: "enum eku::concol eku::deftextcol" (?deftextcol#eku##3W4concol#1#A) already defined in BoardingPass.obj
1>Flight.obj : error LNK2005: "enum eku::concol eku::defbackcol" (?defbackcol#eku##3W4concol#1#A) already defined in BoardingPass.obj
1>Source.obj : error LNK2005: "void * eku::std_con_out" (?std_con_out#eku##3PAXA) already defined in BoardingPass.obj
1>Source.obj : error LNK2005: "bool eku::colorprotect" (?colorprotect#eku##3_NA) already defined in BoardingPass.obj
1>Source.obj : error LNK2005: "enum eku::concol eku::textcol" (?textcol#eku##3W4concol#1#A) already defined in BoardingPass.obj
1>Source.obj : error LNK2005: "enum eku::concol eku::backcol" (?backcol#eku##3W4concol#1#A) already defined in BoardingPass.obj
1>Source.obj : error LNK2005: "enum eku::concol eku::deftextcol" (?deftextcol#eku##3W4concol#1#A) already defined in BoardingPass.obj
1>Source.obj : error LNK2005: "enum eku::concol eku::defbackcol" (?defbackcol#eku##3W4concol#1#A) already defined in BoardingPass.obj
1>D:\School Stuff\Fall 2015\CIST 2362 C++ II\Final - Airline Reservation System\Debug\Final - Airline Reservation System.exe : fatal error LNK1169: one or more multiply defined symbols found
Source.cpp
#include <fstream>
#include <iostream>
#include <iomanip>
#include "FlightComparators.h" //includes Flight.h
#include "LocationComparators.h"
//prototypes
//methods
Flight.h
#ifndef FLIGHT_H
#define FLIGHT_H
#ifndef BOARDINGPASS_H
#include "BoardingPass.h"
#endif
#include <algorithm>
#include <string>
#include <vector>
#include "Location.h"
#include "Validate.h"
#include "AirlineTypeA.h"
#include "AirlineTypeB.h"
class BoardingPass;
class Flight{
private:
Location *departureLoc;
Location *destinationLoc;
char departureTime[6];
char arrivalTime[6];
int number;
int freqFlyerMiles;
int curOccupancy = 0;
Airline *plane;
vector<BoardingPass*> passengers;
public:
//constructor
Flight(Location*, Location*, string, string, int, int, char type);
//getters
Location* getDepartureLoc(){ return departureLoc; }
Location* getDestinationLoc(){ return destinationLoc; }
int getFlightNumber(){ return number; }
int getFreqFlyerMiles(){ return freqFlyerMiles; }
string getDepTime(){ return departureTime; }
string getAriTime(){ return arrivalTime; }
int getCurOccupancy(){ return curOccupancy; }
Airline* getPlane(){ return plane; }
vector<BoardingPass*> getPassengerList(){ return passengers; }
bool getIsFull(){ return this->plane->getMaxPass() > curOccupancy; }
void addPass(string, string, string);
void cancelReservation(int);
void displayPassengers();
void sortPassengers();
};
#endif
BoardingPass.h
#ifndef BOARDINGPASS_H
#define BOARDINGPASS_H
#ifndef FLIGHT_H
#include "Flight.h"
#endif
#include <fstream>
#include <iostream>
#include <iomanip>
#include <string>
using namespace std;
class Flight;
class BoardingPass{
private:
string fName;
string lName;
Flight* flight;
string seat;
public:
BoardingPass(string, string, Flight *flt, string seat);
string getFName(){ return fName; }
string getLName(){ return lName; }
string getSeat(){ return seat; }
void displayBoardingPass();
void writeBoardingPass(fstream&);
};
#endif
concol.h
#ifndef INC_EKU_IO_CONCOL
#define INC_EKU_IO_CONCOL
/*Header file to color text and background in windows console applications
Global variables - textcol,backcol,deftextcol,defbackcol,colorprotect*/
#include<windows.h>
#include<iosfwd>
namespace eku
{
#ifndef CONCOL
#define CONCOL
enum concol
{
black = 0,
dark_blue = 1,
dark_green = 2,
dark_aqua, dark_cyan = 3,
dark_red = 4,
dark_purple = 5, dark_pink = 5, dark_magenta = 5,
dark_yellow = 6,
dark_white = 7,
gray = 8,
blue = 9,
green = 10,
aqua = 11, cyan = 11,
red = 12,
purple = 13, pink = 13, magenta = 13,
yellow = 14,
white = 15
};
#endif //CONCOL
HANDLE std_con_out;
//Standard Output Handle
bool colorprotect = false;
//If colorprotect is true, background and text colors will never be the same
concol textcol, backcol, deftextcol, defbackcol;
/*textcol - current text color
backcol - current back color
deftextcol - original text color
defbackcol - original back color*/
inline void update_colors()
{
CONSOLE_SCREEN_BUFFER_INFO csbi;
GetConsoleScreenBufferInfo(std_con_out, &csbi);
textcol = concol(csbi.wAttributes & 15);
backcol = concol((csbi.wAttributes & 0xf0) >> 4);
}
inline void setcolor(concol textcolor, concol backcolor)
{
if (colorprotect && textcolor == backcolor)return;
textcol = textcolor; backcol = backcolor;
unsigned short wAttributes = ((unsigned int)backcol << 4) | (unsigned int)textcol;
SetConsoleTextAttribute(std_con_out, wAttributes);
}
inline void settextcolor(concol textcolor)
{
if (colorprotect && textcolor == backcol)return;
textcol = textcolor;
unsigned short wAttributes = ((unsigned int)backcol << 4) | (unsigned int)textcol;
SetConsoleTextAttribute(std_con_out, wAttributes);
}
inline void setbackcolor(concol backcolor)
{
if (colorprotect && textcol == backcolor)return;
backcol = backcolor;
unsigned short wAttributes = ((unsigned int)backcol << 4) | (unsigned int)textcol;
SetConsoleTextAttribute(std_con_out, wAttributes);
}
inline void concolinit()
{
std_con_out = GetStdHandle(STD_OUTPUT_HANDLE);
update_colors();
deftextcol = textcol; defbackcol = backcol;
}
template<class elem, class traits>
inline std::basic_ostream<elem, traits>& operator<<(std::basic_ostream<elem, traits>& os, concol col)
{
os.flush(); settextcolor(col); return os;
}
template<class elem, class traits>
inline std::basic_istream<elem, traits>& operator>>(std::basic_istream<elem, traits>& is, concol col)
{
std::basic_ostream<elem, traits>* p = is.tie();
if (p != NULL)p->flush();
settextcolor(col);
return is;
}
} //end of namespace eku
#endif //INC_EKU_IO_CONCOL
In concol.h you're defining variables inside a namespace, not declaring them. The variables need to be externed
extern HANDLE std_con_out;
in the header (to define them), then declared (without the extern) in a .cpp file (concol.cpp).
The symbols indicated by the linker as "already defined" are items that are declared in header files, but outside of any class. (In "file scope".) As a result, every .cpp file which includes these header files is trying to redefine storage for them. When the linker tries to link the object files together, it sees these multiple definitions, and it complains about them.
The best thing to do to solve your problem is to make all these items "static data members" of a class. This means declaring them within a class, and marking them as static.
If you do not want to move them inside a class, then you must see to it that they will be declared as "extern" when included by all .cpp files but one. This way, only one .cpp file will try to define storage for them, and the linker will be happy.
This is usually done as follows:
a.cpp:
#define DECLARE_STORAGE
#include "myheader.h"
b.cpp, c.cpp etc:
#include "myheader.h" //without defining DECLARE_STORAGE
myheader.h
#ifdef DECLARE_STORAGE
#define POSSIBLY_EXTERN
#else
#define POSSIBLY_EXTERN extern
#endif
POSSIBLY_EXTERN int my_integer;
this will cause a.cpp to compile the statement
int my_integer;
while b.cpp, c.cpp etc. will compile the statement
extern int my_integer;
In such form...
#ifndef UNICODE
#define UNICODE
#endif
#include <Windows.h>
#include <iostream>
class A
{
public:
void makeFoo(TCHAR* output)
{
wcscpy(outputBuffer,TEXT("Hello world ♥"));
}
private:
static const int MAX_OUTPUT_SIZE=2000;
static TCHAR outputBuffer[MAX_OUTPUT_SIZE];
};
int main()
{
TCHAR string[255];
A example;
example.makeFoo(string);
MessageBox(0,string,0,0);
system("Pause");
return 0;
}
... we have a
linking error!
1>main.obj : error LNK2001: unresolved external symbol "private:
static wchar_t * A::outputBuffer" (?outputBuffer#A##0PA_WA)
The linker error occurs because you have not provided a definition for the A::outputBuffer anywhere. Fix this by writing this in file scope:
TCHAR A::outputBuffer[A::MAX_OUTPUT_SIZE];
The value of string is unexpected because that buffer is uninitialized; makeFoo does nothing with its argument, and you do not initialize the buffer manually. Therefore it can contain anything at all ("garbage").
Add:
TCHAR A::outputBuffer[A::MAX_OUTPUT_SIZE];
above main().
I am trying to take some functions that I've made and tested with in a standalone application. Now that I am trying to make a DLL I am getting a few errors stating that the function has been redefined and that the return parameters don't match. This seems to be the only time I am getting these errors, I've tested it by removing this class and it compiles fine as well as the stand-alone app with a main.cpp referencing these directly. Below are the errors and the h and cpp files:
Error 7 error C2371: 'Parser::parse' : redefinition; different basic
types c:\users\seb\documents\visual studio
2005\projects\TestDLL\TestDLL\parser.cpp 17
Error 4 error C2526: 'Parser::parse' : C linkage function cannot
return C++ class 'std::vector<_Ty>' c:\users\seb\documents\visual
studio 2005\projects\TestDLL\TestDLL\parser.h 28
Error 6 error C2556: 'IDVec Parser::parse(const char *)' : overloaded
function differs only by return type from 'void Parser::parse(const
char *)' c:\users\seb\documents\visual studio
2005\projects\TestDLL\TestDLL\parser.cpp 17
Also find the .h file and the function from the .cpp as well:
Parser.h
#ifndef PARSER_H
#define PARSER_H
#if defined DLL_EXPORT
#define TESTAPI __declspec(dllexport)
#else
#define TESTAPI __declspec(dllimport)
#endif
#include <iostream>
#include <vector>
typedef struct _ListEntry {
std::string id, path;
} ListEntry;
typedef std::vector<ListEntry> IDVec;
extern "C"
{
class TESTAPI Parser
{
public:
Parser(void);
~Parser(void);
static IDVec parse(const char* Buffer);
private:
static size_t nextLine(std::string& rstrText, size_t pos);
static std::string nextWord(std::string& rstrText, size_t pos);
static void fixOSSpecificPath(std::string& rstrPath);
};
}
#endif
Parser.cpp
IDVec Parser::parse(const char* Buffer)
{
std::string s = Buffer;
IDVec v;
// Doing stuff here
return v;
}
Thanks for any advice
Remove extern "C" around your class definition.