Reputation: 22084
I compiled a shared library with gcc and linked it to my main. The main class should initialize a logger class, which should be visible inside the shared library, but it looks as if the shared library has it's own instance of it.
The include file looks like this:
extern Log gLog;
In main it is declared.
Log gLog(new StreamWriter());
When I try to link it, I get linker errors undefined symbol _gLog
in the shared library. I thought that it might be because it is a class instance, so I changed it to a pointer, but I get the same. To make it worse, I figured I could create a small dummy module where I create the same global variable in the shared library and then call a function to initialize it. But for this function I also get a linker error because it is not visible in main.
In the shared library:
Log *gLogger;
int initLibrary(Log *pLogger)
{
gLogger = pLogger;
}
And in main:
Log gLog(new StreamWriter());
int initLibrary(Log *pLogger);
main()
{
initLibrary(&gLog);
}
Again I get an undefined symbol in the linker, this time for my initLibrary function.
For now I solve the problem by creating a dummy class, which works. However, I would like to know how to properly define symbols across shared library boundaries, as my understanding seems to be wrong about it.
When using google I found some threads here Using a global variable in a shared library and Global variables, shared libraries and -fPIC effect as examples (there are several others as well with this problem). However I tried to recompile everything with -fpic
, also the main module and it still doesn't work. The -rdynamic
option is unknown so I don't know where this comes from.
I can use classes from the shared library and vice versa, so this affects only global symbols. So what am I doing wrong that the main code and the shared library can not see symbols from each other?
Upvotes: 1
Views: 1143
Reputation: 22084
I finally found the problem why this didn't work for global symbols(no problem with classes).
I'm compiling under cygwin, and apparently the shared object is compiled as a DLL. I tried to look into the library and notized that it is an EXE format and not ELF. So I tried to use the Microsoft DLL syntax for exporting symbols and suddenly it worked. Adding a __declspec(dllexport)
to the symbol did the trick.
I expected that I would have to use __declspec(dllimport)
in the main project for importing the symbols, but this doesn't work. Not sure if I missunderstood this parameter or if the cygwin version of gcc does some magic work.
So when you compile a shared library under cygwin it must look like this if you want to export symbols.
Shared library foo.h:
__declspec(dllexport) int foo(int a);
Shared library foo.cpp:
int foo(int a)
{
....
}
In the executable foo.h:
int foo(int a);
In the executable main.cpp:
main()
{
foo(1);
}
The shared library must be compiled with the -fpic
switch and linked with -shared
.
Upvotes: 0
Reputation: 506925
You need to declare you variables with default visibility to make it visible to other shared libraries or the main program. It appears that you are compiling with -fvisibility=hidden
, so that a symbol in the library does not resolve to a definition in the main program or other libraries and vice versa. With the visibility attribute of GCC, you can reverse this effect.
In a nutshell
Another possibility is that you are mixing C and C++ code and messing up with the language linkage.
Upvotes: 0
Reputation: 10947
The right approach is to create the instance of the Logger inside the shared library, using either a global variable (better if encapsulated in a namespace) or a Singleton class. Then let your main program use it.
Upvotes: 1