I have an issue when I try to use dlopen() to load a shared library into another shared library. I checked all tutorials on how to use dlopen() correctly. So here is the simplified code:
The main shared library contains a class with pure virtual functions which the sub-shared library (aka plug-in) must implement. Additionally, it has some other functions which are implemented with a default behavior. I created a macro which is added to every plug-in to have a symbol to load and create the class.
Main shared library
plugin.h:
Class A {
public:
virtual int func1() = 0;
virtual bool func2() const;
}
#define CREATE_CLASS(cls) extern "C" void *CreateClass(void) { return new cls; }
plugin.cpp:
bool A::func2() const { return true; }
Build and link main.so
g++ -g -Wall -Woverloaded-virtual -Wno-parentheses -O2 -fPIC -c -o plugin.o plugin.cpp
g++ -g -Wall -Woverloaded-virtual -Wno-parentheses -O2 -fPIC -rdynamic -shared plugin.o -ldl -o main-plugin.so
The sub-shared library does only implement the pure-virtual functions. The other function can be overridden though it is optional.
Sub shared library
plugin-impl.cpp
Class B : public A {
public:
virtual int func1() { return 0; }
}
CREATE_CLASS(B)
These are the lines to build and link the sub-shared library.
Build and link sub.so
g++ -g -O3 -Wall -Werror=overloaded-virtual -Wno-parentheses -fPIC -c -o subPlugin.o subPlugin.cpp
g++ -g -O3 -Wall -Werror=overloaded-virtual -Wno-parentheses -fPIC -shared subPlugin.o -o subPlugin.so
This is the line to open the sub-shared library. I tried LAZY, NOW, NOW | GLOBAL and so on, without any effects.
dlopen() call somewhere in the main-shared library:
handle = dlopen(file.c_str(), RTLD_LAZY);
Most of this is working very well. However, when I try to load the sub-shared library into the main shared library, dlopen complains about the undefined symbol of bool A::func2() const
. The function does only exists in the main shared library, so I guess it must be exported anyway. Please help me out! I am very confused!
SOLUTION
Because I cannot change the executable, I have to link the main-shared library with the sub-shared librarys by adding the following options to g++:
-L$(PLUGINDIR) -Wl,-R$(PLUGINDIR) -lmain-shared
With this set, it is not required to set the LD_LIBRARY_PATH
.