Bri*_*ett 22 c++ linux linker static-libraries
我有一个C++项目,由于其目录结构被设置为静态库A,它链接到共享库B,它链接到可执行文件C.(这是使用CMake的一个跨平台的项目,所以在Windows上我们得到的A.lib,B.dll和C.exe,和在Linux上我们得到的libA.a,libB.so和C).图书馆A有一个初始化函数(A_init在定义A/initA.cpp),即从库调用B的初始化函数(B_init,定义于B/initB.cpp),从C主要调用.因此,当链接时B,A_init(和所有符号中定义的initA.cpp)被链接到B(这是我们期望的行为).
问题在于,A库还定义了一个动态加载的函数(Af,在A/Afort.f其中定义)(即LoadLibrary/ GetProcAddress在Windows上和dlopen/ dlsym在Linux上).由于没有Af来自库的引用B,A/Afort.o因此不包括符号B.在Windows上,我们可以通过使用pragma人工创建引用:
#pragma comment (linker, "/export:_Af")
Run Code Online (Sandbox Code Playgroud)
由于这是一个pragma,它只适用于Windows(使用Visual Studio 2008).为了让它在Linux上运行,我们尝试将以下内容添加到A/initA.cpp:
extern void Af(void);
static void (*Af_fp)(void) = &Af;
Run Code Online (Sandbox Code Playgroud)
这不会导致符号Af包含在最终链接中B.我们如何强制将符号Af链接到B?
Bri*_*ett 13
事实证明我最初的尝试主要在那里.以下作品:
extern "C" void Af(void);
void (*Af_fp)(void) = &Af;
Run Code Online (Sandbox Code Playgroud)
对于那些想要一个自包含的预处理器宏来封装它的人:
#if defined(_WIN32)
# if defined(_WIN64)
# define FORCE_UNDEFINED_SYMBOL(x) __pragma(comment (linker, "/export:" #x))
# else
# define FORCE_UNDEFINED_SYMBOL(x) __pragma(comment (linker, "/export:_" #x))
# endif
#else
# define FORCE_UNDEFINED_SYMBOL(x) extern "C" void x(void); void (*__ ## x ## _fp)(void)=&x;
#endif
Run Code Online (Sandbox Code Playgroud)
因此使用的是:
FORCE_UNDEFINED_SYMBOL(Af)
Run Code Online (Sandbox Code Playgroud)
有一种更好的方法来编写 FORCE_UNDEFINED_SYMBOL 宏。只需将该函数指针转换为 void* 即可。然后它可以与任何函数或数据一起使用。另外,当宏的 gcc 部分也适用于 MSVC 时,为什么还要费心使用 MSVC 编译指示呢?所以我的简化版本是:
#define FORCE_UNDEFINED_SYMBOL(x) void* __ ## x ## _fp =(void*)&x;
Run Code Online (Sandbox Code Playgroud)
其用法如下:
FORCE_UNDEFINED_SYMBOL(Af)
Run Code Online (Sandbox Code Playgroud)
但它必须在包含已删除其符号的库的程序中使用。