Playing with __attributes__ (三)

canopus4u發表於2015-12-06

visibility

__attribute__((visibility("visibility_type")))
當我們並不希望暴露一個方法時,一般情況使用static關鍵字來修飾函式。這樣編譯時該方法就不會被輸出到符號表裡。詳細可參見這篇博文

LLVM和GCC其實也提供了類似的attribute

使用示例:

__attribute__((visibility("default"))) void foo1(int x, int y);
__attribute__((visibility("hidden"))) int foo2(int x);
__attribute__((visibility("protected"))) void foo3(int x, int y);
  • default意味著該方法對其他模組是可見的。

  • hidden表明該方法符號不會被放到動態符號表裡,所以其他模組(可執行檔案或者動態庫)不可以通過符號表訪問該方法。(但在執行時使用函式指標可對其進行呼叫,visibility是個編譯時的特性,正如你在執行時可以修改const修飾的變數一樣)

  • protected則表示該方法將會被放置到動態符號表,對其他模組可見。但該符號對其所在模組是繫結的,即其他模組不可過載該符號。

  • internal,跟hidden相似。除非特別指定,否則意味著不能從模組呼叫該方法。

-fvisibility

既然說到了visibility,那順帶說一下這個flag,這個flag在呼叫gcc或者llvm時指定。表示編譯時的對所有方法的預設visibility的選擇(除非顯式指定方法的visibility)。

-fvisibility=default|internal|hidden|protected

一般來說隱藏方法使用static就夠了。但此attribute為大型工程專案提供了一種可能性,即可以使某些模組整體隱藏所有介面,只暴露特別指定的方法。

其他

此外gcc的編譯器還可以像如下這樣使用:

#pragma GCC visibility push(hidden)
void method1() {...}
void method2() {...}
...
#pragma GCC visibility pop

即表示在pushpop之間宣告的所有方法,其可見性都按照指定的進行編譯。

private_extern

這個關鍵字也有static相同的作用

總述

通過上述提供的幾種手段,在一些複雜模組化的大中型專案中,我們可以更加靈活地對不同模組進行可行性的控制,能夠更精細對專案進行模組化,並且減少符號被覆蓋的風險。

llvm參考文件

還有一些有趣的attribute,以後再寫

  • objc_root_class

  • objc_designated_initializer

  • naked

原作寫於segmentfault 連結

相關文章