2010-05-29 57 views
8

有沒有什麼辦法可以在編譯時檢查給定的函數是否用C-linkage(也就是extern "C")聲明?在編譯時檢查一個函數是否具有C-linkage [不可解]

我正在開發一個插件系統。每個插件都可以爲插件加載代碼提供工廠函數。但是,這必須通過名稱(以及隨後使用GetProcAddressdlsym)完成。這要求使用C-linkage來聲明函數,以防止名稱混亂。如果引用的函數是用C++連接聲明的(而不是在運行時找到具有該名稱的函數不存在),那麼能夠拋出編譯器錯誤會很好。

這裏是我的意思一個簡單的例子:

extern "C" void my_func() 
{ 
} 

void my_other_func() 
{ 
} 

// Replace this struct with one that actually works 
template<typename T> 
struct is_c_linkage 
{ 
    static const bool value = true; 
}; 

template<typename T> 
void assertCLinkage(T *func) 
{ 
    static_assert(is_c_linkage<T>::value, "Supplied function does not have C-linkage"); 
} 

int main() 
{ 
    assertCLinkage(my_func); // Should compile 
    assertCLinkage(my_other_func); // Should NOT compile 
} 

是否有可能實現的is_c_linkage會拋出一個編譯器錯誤的第二個功能,但不是第一?我不確定這是否可能(儘管它可能作爲編譯器擴展存在,我仍然想知道)。謝謝。

+6

我強烈懷疑這是無法完成的 - 特別是沒有以標準的方式。有趣的問題,雖然。 – 2010-05-29 19:51:06

+2

我不太確定。但即使可以完成,GCC很可能不支持它,因爲它不知道外部「C」和外部「C++」函數類型的區別。因此,它將這兩種類型視爲相同。 – 2010-05-29 20:13:33

+0

如果你要實現特定的知識,你可能會使它爲該實現工作,而不是拋出錯誤 – 2010-05-29 21:03:09

回答

2

我同意Jonathan Leffler所說的,這可能不是標準的方式。根據編譯器甚至是編譯器的版本,這可能會有所不同,但是您必須嘗試確定可能的方法,並接受編譯器行爲可能無意的並可能在更高版本中「修復」的事實。

隨着g++ Debian的擠壓版本4.4.4,例如,您可能能夠提出一個編譯器錯誤對於不stdcall這種方法的功能:

void my_func() __attribute__((stdcall)); 
void my_func() { } 

void my_other_func() { } 

template <typename ret_, typename... args_> 
struct stdcall_fun_t 
{ 
    typedef ret_ (*type)(args_...) __attribute__((stdcall)); 
}; 

int main() 
{ 
    stdcall_fun_t<void>::type pFn(&my_func), 
     pFn2(&my_other_func); 
} 

g++ -std=c++0x無法編譯這個代碼,因爲:

SO2936360.cpp:17: error: invalid conversion from ‘void ()()’ to ‘void ()()’

第17行是pFn2的聲明。如果我擺脫這個聲明,那麼編譯成功。

不幸的是,這種技術不適用於cdecl

0

對於Unix/Linux,如何分析帶有'nm'的結果二進制文件並尋找符號名稱?我想這不是你的意思,但仍然是編譯時間。

相關問題