I'm learning C++, I come from Java and I want to write some program that loads plugins. Basically what I want to do is :
- Run the program
- Load the shared libs (plugins)
- Register one function from the shared library inside a list in the main program
- Run those functions inside the main program
- Be able to use some functions written in the main program from the libs
As I said, I come from Java, and all I would've done is import somestuff;
to be able to use that. So I'm trying to figure that out for C++. I've read that dlopen/dlsym can be a solution, so I read those manual pages, and some examples, and here's what I've done :
main.h
#ifndef MAIN_H
#define MAIN_H
#include <functional>
#include <vector>
class Test{
public :
static std::vector <std::function<void()>> initFuncList;
static bool registerInitFunc(std::function<void()> Func);
};
#endif // MAIN_H
main.cpp
#include <dlfcn.h>
#include "main.h"
std::vector <std::function<void()>> Test::initFuncList;
bool Test::registerInitFunc(std::function<void()> Func)
{
initFuncList.push_back(Func);
return true;
}
int main()
{
static bool (*dlinit)(void);
printf("opening library.\n");
void* dlh = dlopen("./libtest.so", RTLD_NOW);
if (!dlh)
{
fprintf(stderr, "dlopen failed: %s\n", dlerror());
exit(EXIT_FAILURE);
}
printf("Library opened.\n Reading init function address.\n");
*(void **) (&dlinit) = dlsym(dlh, "init");
printf("Function address is %p.\n", dlinit);
if(!dlinit())
{
exit(EXIT_FAILURE);
}
printf("Library initialized, function registered.\n");
for(auto func : Test::initFuncList)
{
printf("Looping through registered functions.\n");
func();
}
return EXIT_SUCCESS;
}
exportlib.h
#ifndef LIB_H
#define LIB_H
class Lib
{
public:
Lib();
static void func(void);
static bool init(void);
};
#endif // LIB_H
exportlib.cpp
#include "exportlib.h"
#include "main.h"
Lib::Lib(){}
bool Lib::init()
{
printf("Initializing library.\n");
return (Test::registerInitFunc(func));
}
void Lib::func()
{
printf("This is the library function called after initialization.\n");
}
I'm using QtCreator as an IDE, to parse a CMake project, and I'm using CLang 7.0.0 to build it. The project builds, but when I run it, it crashes with segfault on the dlinit()
call.
I'm stumbling upon my general lack of knowledge about C/C++ here, and I have a hard time understanding what happens in GDB around the dlsym()
stuff. So if I understand things correctly (tell me if I'm wrong), I've declared dlinit
as a function pointer, and when I call dlsym
, the return value gets in dlinit
so dlinit
should point to the function I'm looking for inside my library and I should be able to use it. I would expect the value of dlinit
to be an address, but after dlsym()
its value is still 0.
I've read a lot of interesting things, such as this answer, or things about the visibility attribute to export symbols (here), but I found lots of examples for gcc, and failed to find the equivalent for clang. Finally I've read about things about the way I should build my project to make the magic happen (there), but again, I failed to find clang equivalent.
So what I am missing here? I can provide the CMakeLists.txt file if needed.