2010-06-07 77 views
20

我有一个C++项目,由于其目录结构设置为一个静态库A,它链接到共享库B,链接到可执行文件C。 (这是使用CMake的一个跨平台的项目,所以在Windows上,我们得到A.libB.dllC.exe,并在Linux上,我们得到libA.alibB.soC)图书馆A有一个初始化函数(A_init,在A/initA.cpp定义)从库B的初始化函数(B_init,在B/initB.cpp中定义)中调用该函数,该函数从C的主函数中调用。因此,链接B,A_init(和initA.cpp中定义的所有符号)链接到B(这是我们所需的行为)。如何在链接到可执行文件时强制在静态库中包含对象文件?

,问题就在于该A库还定义了旨在由动态加载的函数(Af,在A/Afort.f定义)(在Windows即LoadLibrary/GetProcAddress和Linux上dlopen/dlsym)。由于没有提及来自库BAf,所以来自A/Afort.o的符号不包括在B中。在Windows中,我们可以人为地通过编译创建一个参考:

#pragma comment (linker, "/export:_Af") 

因为这是一个编译,它只能在Windows上(使用Visual Studio 2008)。得到它的工作在Linux上,我们尝试加入以下A/initA.cpp

extern void Af(void); 
static void (*Af_fp)(void) = &Af; 

这不会导致符号Af被列入B的最后一个环节。我们如何强制将符号Af链接到B

回答

12

事实证明,我原来的尝试主要是在那里。以下作品:

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) 
3

当你建立B可以使用--undefined选项:

g++ -Wl,--undefined,Af -o libB.so ... 
0

尝试把这些线路到B/initB.cpp让他们(希望)被迫在链接时libB.so库。

但是,为什么你必须这样做呢?难道你不能设置它,使可执行引用的功能(或它的调用者),导致链接器自动做正确的事情?

+0

C实际上是一种脚本语言前端,B是语言引擎,A是引擎使用的一组本机代码方法。我们正在实现一个预先存在的语言,该语言具有定义良好的外部函数接口。 A和B由分开的小组生产;我们希望保留A-team在A目录中写入的所有内容。 – 2010-06-07 20:02:09

0

如果你可以用gcc的的C++ 0x功能(-std =的C++ 0x),那么功能默认模板参数可以做的伎俩。截至目前的C++标准,函数模板不允许使用默认参数。有了这些在C++中启用0X,你可以这样做: -

在静态库的某些头文件...

template< class T = int > 
void Af() 
{ 
} 

然后在其相应的cpp文件使用显式模板实例...

template void Af(); 

这将生成函数Af虽然它没有叫/引用的符号。 这不会影响调用者,因为由于默认的模板参数,您不需要指定类型。只需在函数声明前添加template <class T = int >,并在其实现文件中显式实例化它。

HTH,

+1

不幸的是,这是行不通的,因为Af实际上是Fortran程序。 – 2010-06-07 20:16:34

+0

那么,制作一个调用Af _(...)的'C'包装器[你可以从'C'调用fortran函数,即通过下划线附加函数名称;谷歌nitty砂砾细节的参数,我donno abt C++调用fortran]。从C++调用这个'C'包装器。顺便说一句,多数民众赞成在我的工作如何领先的金融公司之一,管理其古董/蹩脚的代码:-) – Abhay 2010-06-07 20:23:00

+0

这是一个非常明显的代码,可能会被一个菜鸟维护者,两年后删除。至少这个宏是足够清晰的。 – xryl669 2014-02-04 18:16:50

5

MSVC#pragma comment(linker, "/include:__mySymbol")

gcc-u symbol

2

有一个更好的方法来编写FORCE_UNDEFINED_SYMBOL宏。只需将该函数指针转换为void *即可。然后它适用于任何功能 - 或者这个问题的数据。另外,当你的宏的gcc部分也适用于MSVC时,为什么还要打扰MSVC编译指示。所以,我的简化版将是:

#define FORCE_UNDEFINED_SYMBOL(x) void* __ ## x ## _fp =(void*)&x; 

这也是正是如此使用:

FORCE_UNDEFINED_SYMBOL(Af) 

但必须在包括是有它的符号剥离该库的程序中使用。