dlopen a dynamic library from a static library, wh

2019-04-09 09:29发布

This question is closely related to dlopen a dynamic library from a static library linux C++, but contains a further complication (and uses C++ instead of C):

I have an application that links against a static library (.a) and that library uses the dlopen function to load dynamic libraries (.so). In addition, the dynamic libraries call functions defined in the static one.

Is there a way to compile this without linking the dynamic libraries against the static one or vice versa?

Here comes what I tried so far, slightly modifying the example from the related question:

app.cpp:

#include "staticlib.hpp"
#include <iostream>
int main()
{
    std::cout << "and the magic number is: " << doSomethingDynamicish() << std::endl;
    return 0;
}

staticlib.hpp:

#ifndef __STATICLIB_H__
#define __STATICLIB_H__

int doSomethingDynamicish();
int doSomethingBoring();
#endif

staticlib.cpp:

#include "staticlib.hpp"
#include "dlfcn.h"
#include <iostream>
int doSomethingDynamicish()
{
    void* handle = dlopen("./libdynlib.so",RTLD_NOW);
    if(!handle)
    {
        std::cout << "could not dlopen: " << dlerror() << std::endl;
        return 0;
    }

    typedef int(*dynamicfnc)();
    dynamicfnc func = (dynamicfnc)dlsym(handle,"GetMeANumber");
    const char* err = dlerror();
    if(err)
    {
        std::cout << "could not dlsym: " <<err << std::endl;
        return 0;
    }
    return func();
}

staticlib2.cpp:

#include "staticlib.hpp"
#include "dlfcn.h"
#include <iostream>

int doSomethingBoring()

{
    std::cout << "This function is so boring." << std::endl;
    return 0;

}

dynlib.cpp:

#include "staticlib.hpp"

extern "C" int GetMeANumber()
{
    doSomethingBoring();
    return 1337;
}

and build:

g++ -c -o staticlib.o staticlib.cpp
g++ -c -o staticlib2.o staticlib2.cpp
ar rv libstaticlib.a staticlib.o staticlib2.o
ranlib libstaticlib.a
g++ -rdynamic -o app app.cpp libstaticlib.a -ldl 
g++ -fPIC -shared -o libdynlib.so dynlib.cpp

When I run it with ./app I get

could not dlopen: ./libdynlib.so: undefined symbol: _Z17doSomethingBoringv
and the magic number is: 0

1条回答
仙女界的扛把子
2楼-- · 2019-04-09 10:18

From the dlopen manual page:

If the executable was linked with the flag "-rdynamic" (or, synonymously, "--export-dynamic"), then the global symbols in the executable will also be used to resolve references in a dynamically loaded library.

That means that for the application to export its symbols for use in the dynamic library, you have to link your application with the -rdynamic flag.


Besides the problem described above, there is another problem and that has to do with the static library: The problem is namely that since the doSomethingBoring function is not called in your main program, the object file staticlib2.o from the static library is not linked.

The answer can be found in e.g. this old question, which tells you to add the --whole-archive linker flag:

g++ -rdynamic -o app app.cpp -L. \
    -Wl,--whole-archive -lstaticlib \
    -Wl,--no-whole-archive -ldl
查看更多
登录 后发表回答