链接到可执行文件时,如何强制在静态库中包含对象文件? 我有一个C++项目,因为它的目录结构被设置为静态库 A/COD>,它被链接到共享库 B/COD>,它被链接到可执行代码代码>代码>。(这是一个使用CMake的跨平台项目,因此在Windows上我们得到a.lib,B.dll和C.exe,在Linux上我们得到libA.a,libB.so,和C)库a有一个init函数(a_init code>,在a/initA.cpp中定义),这是从库B的init函数(B_init,在B/initB.cpp中定义)调用的,它是从C的main调用的。因此,当链接B时,A_init(以及initA.cpp中定义的所有符号)链接到B(这是我们想要的行为)
问题在于链接到可执行文件时,如何强制在静态库中包含对象文件? 我有一个C++项目,因为它的目录结构被设置为静态库 A/COD>,它被链接到共享库 B/COD>,它被链接到可执行代码代码>代码>。(这是一个使用CMake的跨平台项目,因此在Windows上我们得到a.lib,B.dll和C.exe,在Linux上我们得到libA.a,libB.so,和C)库a有一个init函数(a_init code>,在a/initA.cpp中定义),这是从库B的init函数(B_init,在B/initB.cpp中定义)调用的,它是从C的main调用的。因此,当链接B时,A_init(以及initA.cpp中定义的所有符号)链接到B(这是我们想要的行为),c++,linux,linker,static-libraries,C++,Linux,Linker,Static Libraries,问题在于A库还定义了一个函数(Af,在A/Afort.f中定义),该函数旨在通过动态加载(即Windows上的LoadLibrary/GetProcAddress和Linux上的dlopen/dlsym)。由于库B中没有对Af的引用,因此A/Afort.o中的符号不包括在B中。在Windows上,我们可以使用pragma人工创建引用: #pragma comment (linker, "/export:_Af") 因为这是一个pragma,所以它只能在Windows上工作(使用VisualSt
A
库还定义了一个函数(Af
,在A/Afort.f
中定义),该函数旨在通过动态加载(即Windows上的LoadLibrary
/GetProcAddress
和Linux上的dlopen
/dlsym
)。由于库B
中没有对Af
的引用,因此A/Afort.o
中的符号不包括在B
中。在Windows上,我们可以使用pragma人工创建引用:
#pragma comment (linker, "/export:_Af")
因为这是一个pragma,所以它只能在Windows上工作(使用VisualStudio2008)。为了让它在Linux上工作,我们尝试将以下内容添加到A/initA.cpp
:
extern void Af(void);
static void (*Af_fp)(void) = &Af;
这不会导致符号Af
包含在B
的最终链接中。如何强制将符号Af
链接到B
?您可以在构建B时使用--undefined
选项:
g++ -Wl,--undefined,Af -o libB.so ...
尝试将这些行放入
B/initB.cpp
,以便(希望)在链接时强制它们进入libB.so
库
但你为什么要这样做呢?您不能设置它,使可执行文件引用该函数(或它的调用方),从而使链接器自动执行正确的操作吗?如果您可以使用gcc(-std=C++0x)的C++0x功能,那么函数默认模板参数可能会起作用。在当前C++标准中,函数模板不允许使用默认参数。在c++0x中启用这些功能后,您可以执行以下操作:- 在静态库的某些头文件中
template< class T = int >
void Af()
{
}
这将为函数Af
生成符号,尽管它尚未被调用/引用。
这不会影响调用者,因为由于默认的模板参数,您不需要指定类型。只需在函数声明之前添加模板
,并在其实现文件中显式实例化它
嗯,原来我最初的尝试主要是在那里。以下工作:
extern "C" void Af(void);
void (*Af_fp)(void) = &Af;
对于那些想要一个自包含的预处理器宏来封装它的用户:
#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
这是如此使用的:
FORCE_UNDEFINED_SYMBOL(Af)
FORCE_UNDEFINED_SYMBOL(Af)
#pragma注释(链接器,“/include:uu mySymbol”)
-u symbol
有一种更好的方法来编写FORCE\u UNDEFINED\u symbol宏。只需将该函数指针转换为void*。然后它与任何函数或数据一起工作。此外,当宏的gcc部分也适用于MSVC时,为什么还要使用MSVC pragmas呢。因此,我的简化版本是:
#define FORCE_UNDEFINED_SYMBOL(x) void* __ ## x ## _fp =(void*)&x;
这是如此使用的:
FORCE_UNDEFINED_SYMBOL(Af)
FORCE_UNDEFINED_SYMBOL(Af)
但它必须用于包含正在剥离符号的库的程序。C实际上是一种脚本语言前端,B是语言引擎,a是引擎要使用的一组本机代码方法。我们正在实现一种预先存在的语言,它有一个定义良好的外部函数接口。A和B由不同的团队制作;我们更愿意将A-team编写的所有内容都保存在A目录中。不幸的是,这不起作用,因为Af实际上是一个Fortran过程。那么,制作一个调用Af_(…)的“C”包装器(u可以从C’调用FORTRAN函数,即用下划线附加函数名;谷歌的TITY GRITY细节用于参数,我不ABT C++调用FORTRAN)把这个“C”包装从C++中调用。BTW,这就是我为之工作的一个主要金融公司,管理它的古董/蹩脚代码:-这是一个非常不明显的代码,2年后可能会被新手维护者删除。至少宏足够清楚。@ XRYL69,这就是为什么你希望包含评论的原因。在这样的定义之前/之后(希望新手也能阅读评论)。使用C++11,您可能可以使用
auto
和no cast!