Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

problems with global variables in shared library project (C++)

i have a problem with global variables in a c++ shared library project. my library has to be working as a standard g++ shared library (.so) as well as a dll. i did this by creating files libiup_dll.cpp and libiup_dll.h, where i have something like

#ifdef BUILD_DLL

// code for the dll: wrapper functions around the classes in my shared library

#endif

in my dll, i need functions setloglevel(int) and geterrormsg(). in all my classes, i'd then append to a global variable errormsg all error messages. this variable should then be returned by the geterrormsg() function. i implemented this by using

std::string errormsg;
int loglevel;

in libiup_dll.h (outside and #ifdefs, so it should be globally available), and then putting

extern std::string errormsg;
extern int loglevel;

in my classes' .h files (outside the class, at the top of the files)

now i have two problems:

1) when compiling a command line program with g++, which uses my library, i get errors

Building target: libiup_test Invoking: GCC C++ Linker g++ -L"/home/hilboll/src/libiup/Release" -L/usr/local/lib -o"libiup_test" ./src/stratcalc/SimpleStratosphericColumnCalculatorTest.o ./src/interp/SimpleInterpolatorTest.o ./src/Test.o -lgsl -lhdf5 -lhdf5_cpp -lblas -liup /home/hilboll/src/libiup/Release/libiup.so: undefined reference to loglevel' /home/hilboll/src/libiup/Release/libiup.so: undefined reference toerrormsg' collect2: ld returned 1 exit status make: *** [libiup_test] Error 1

even though in my command line program, there's no reference whatsoever to errormsg or loglevel.

2) when trying to compile the dll under windows with VS2008, i get

z:\src\vs\libiup_dll\libiup_dll.h(229) : error C2086: 'std::string errormsg': Neudefinition z:\src\libiup\src\stratcalc../interp/SimpleInterpolator.h(16): Siehe Deklaration von 'errormsg' z:\src\vs\libiup_dll\libiup_dll.h(234) : error C2086: 'int loglevel': Neudefinition z:\src\libiup\src\stratcalc../interp/SimpleInterpolator.h(17): Siehe Deklaration von 'loglevel'

as far as i understand, it means that VS thinks i'm defining the two variables twice. however, in SimpleInterpolator.h 16/17, there's the extern declarations only ...

it seems i somehow haven't understood how global variables work, yet. any help is greatly appreciated!

like image 277
andreas-h Avatar asked Dec 29 '22 16:12

andreas-h


1 Answers

The trick is to know that each .cpp file is a compilation unit - ie the things that get compiled. Each one is a total individual and know nothing about each other. Its only at the link stage that these are brought together.

Now, extern says "this variable can be found elsewhere" to the compiled cpp file, the compiler just places a reference hint to the linker to sort things out.

So, as you've put the variable definitions in a header file, chances are you're including that header into 2 (or more) cpp files. So each of those cpp files, when compiled, think they have the real variable. The linker then comes along and sees too many.

Place the variables into a cpp file of their own (or into the main cpp file), and only put extern references in header files. You should be ok with multiply-defined symbols then.

like image 180
gbjbaanb Avatar answered Jan 24 '23 17:01

gbjbaanb