当动态库使用静态库的符号时,请从静态库中打开一个动态库
此问题与 dlopen动态相关静态库linux C ++中的库,但是包含了进一步的复杂性(并且使用C ++而不是C):
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):
我有一个链接到静态库(.a)的应用程序,该库使用dlopen函数加载动态库(.so).另外,动态库调用在静态库中定义的函数.
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:
staticlib.hpp:
#ifndef __STATICLIB_H__
#define __STATICLIB_H__
int doSomethingDynamicish();
int doSomethingBoring();
#endif
staticlib.cpp:
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:
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:
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
运行它时,我得到了
When I run it with ./app
I get
could not dlopen: ./libdynlib.so: undefined symbol: _Z17doSomethingBoringv
and the magic number is: 0
来自 如果可执行文件与标志"-rdynamic"(或同义为"--export-dynamic")链接,则可执行文件中的全局符号也将用于解析动态加载的库中的引用./p>
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 除了上述问题外,还有另一个问题与静态库有关:问题在于,由于在主程序中未调用 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 答案可以在例如这个旧问题,它告诉您添加 The answer can be found in e.g. this old question, which tells you to add the
-rdynamic
标志链接.-rdynamic
flag. doSomethingBoring
函数,因此目标文件静态库中的 staticlib2.o
未链接.doSomethingBoring
function is not called in your main program, the object file staticlib2.o
from the static library is not linked.-whole-archive
链接器标志:--whole-archive
linker flag:g++ -rdynamic -o app app.cpp -L. \
-Wl,--whole-archive -lstaticlib \
-Wl,--no-whole-archive -ldl