The set up is unclear, so I improvised
There are multiple descriptions of your set up that are slightly conflicting. So, my description may not match up with what you have, but hopefully it addresses your question.
The setup I used
The stub implementations of the libs are included at the bottom of this answer, as is the Makefile. But the basic organization is:
myLib.so has the class with a method that will throw an exception
myLib1.so has the function that loads myLib.so and invokes the method
I then attempted various versions of the myTest.cpp to see what would work.
RTLD_GLOBAL does not work on myLib1.so
Invoking dlopen("./myLib1.so", RTLD_GLOBAL | RTLD_NOW) is just like trying to link it into the executable. My attempt to use the above call resulted in a NULL handler being returned. When I attempted to link it directly into the executable instead, I got a linker error.
g++ -g myTest.cpp ./myLib1.so -ldl -o myTest
./myLib1.so: undefined reference to `MyNamespace::MyClass::function1()'
./myLib1.so: undefined reference to `MyNamespace::getClass()'
collect2: error: ld returned 1 exit status
This is an explanation as to why using RTLD_GLOBAL failed. It could not resolve the symbols that are defined in myLib.so. I could fix this by including myLib.so in the link line too, but then there is no dynamic loading happening at all.
RTLD_LAZY can be made to work
If you are not insistent on being able to invoke the code directly, you can use RTLD_LAZY on myLib1.so instead. This would require d dlsym() call to find the entry point function to call. But that lookup will trigger a lazy symbol resolution mechanism that causes the inner code to succeed.
Below is the working myTest.cpp file I used.
#include "myLib1.h"
#include <dlfcn.h>
int main () {
void * h = dlopen("./myLib1.so", RTLD_LAZY);
void (*foo)() = (void(*)())dlsym(h, "foo");
foo();
dlclose(h);
}
The source files
myLib.h
#pragma once
namespace MyNamespace {
struct Exception1 {
const char *what_;
Exception1(const char *what) : what_(what) {}
const char * what () const { return what_; }
};
struct MyClass {
friend MyClass * MyNamespace::getClass ();
void function1 () throw(Exception1);
private:
MyClass () {}
};
MyClass * getClass ();
}
myLib.cpp
#include "myLib.h"
namespace MyNamespace {
void MyClass::function1() throw(Exception1) {
throw Exception1("Error message");
}
MyClass * getClass () { return new MyClass(); }
}
myLib1.h
#pragma once
#ifdef __cplusplus
extern "C" {
#endif
void foo ();
#ifdef __cplusplus
}
#endif
myLib1.cpp
#include "myLib1.h"
#include "myLib.h"
#include <iostream>
#include <dlfcn.h>
void foo () {
void *h = dlopen("./myLib.so", RTLD_GLOBAL | RTLD_NOW);
MyNamespace::MyClass *p = MyNamespace::getClass();
try {
p->function1();
} catch (MyNamespace::Exception1 e) {
std::cout << e.what() << std::endl;
}
delete p;
dlclose(h);
}
Makefile
all : myLib.so myLib1.so myTest
clean :
rm -f *.o *.so myTest
%.so : %.o
g++ -shared -o $@ $<
%.o : %.cpp
g++ -std=c++03 -W -Wall -Werror -fPIC -rdynamic -O3 -g -c $<
myLib.so : myLib.h
myLib1.so : myLib1.h myLib.h
myTest : myTest.cpp myLib1.h
g++ -g $< $(MYLIB) -ldl -o $@
objdump -TC mylib1.so | grep Exception1withobjdump -TC mylib2.so | grep Exception1? sizes of typeinfos should be equal