简体   繁体   中英

Linux, Clang, Cmake, QtCreator : Using shared libraries

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.

You should check the value of dlinit pointer prior to calling the function it points to:

if(not dlinit)
{
    auto const psz_error{::dlerror()};
    fprintf(stderr, "dlsym failed to fetch init: %s\n", (psz_error ? psz_error : "unknown"));
    exit(EXIT_FAILURE);
}

Right now most likely dlsym(dlh, "init"); returned null because export lib does not have a symbol named init , instead it has a mangled C++ symbol for bool ::Lib::init(void) . If you want to get symbols with dlsyn you should provide a C interface for you library. That is export

extern "C" int init(void);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM