2010-06-07 60 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) 

但必須在包括是有它的符號剝離該庫的程序中使用。

相關問題