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
即表示在push
與pop
之間宣告的所有方法,其可見性都按照指定的進行編譯。
private_extern
這個關鍵字也有static相同的作用
總述
通過上述提供的幾種手段,在一些複雜模組化的大中型專案中,我們可以更加靈活地對不同模組進行可行性的控制,能夠更精細對專案進行模組化,並且減少符號被覆蓋的風險。
還有一些有趣的attribute,以後再寫
objc_root_class
objc_designated_initializer
naked
原作寫於segmentfault 連結