当动态库使用静态库的符号时,从静态库打开动态库

dlopen a dynamic library from a static library, when the dynamic library uses symbols of the static one

本文关键字:动态 静态 符号      更新时间:2023-10-16

这个问题与从静态库linux C++中dlopen动态库密切相关,但包含了一个更复杂的问题(使用C++而不是C):

我有一个链接到静态库(.a)的应用程序,该库使用dlopen函数加载动态库(.so)。此外,动态库调用静态库中定义的函数。

有没有一种方法可以在不将动态库与静态库链接的情况下编译它,反之亦然?

以下是我迄今为止尝试的内容,对相关问题的示例进行了轻微修改:

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();
}

staticb2.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;
}

和构建:

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

当我用./app运行它时,我得到

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

来自dlopen手册页面:

如果可执行文件与标志"-rdynamic"(或同义词"-export-dynamic")链接,则可执行文件中的全局符号也将用于解析动态加载库中的引用。

这意味着应用程序要导出其符号以在动态库中使用,必须使用-rdynamic标志链接应用程序。


除了上述问题之外,还有另一个问题与静态库有关:问题是,由于主程序中没有调用doSomethingBoring函数,因此静态库中的对象文件staticlib2.o没有链接。

答案可以在这个老问题中找到,它告诉您添加--whole-archive链接器标志:

g++ -rdynamic -o app app.cpp -L. 
    -Wl,--whole-archive -lstaticlib 
    -Wl,--no-whole-archive -ldl