2017-03-14 48 views
17

在ELF目標上,如果我有class Foo,並且我通過class __attribute__((visibiility("default"))) Foo等聲明提供了default可見性,那麼我可以通過使用__attribute__((visibility("hidden"))明確註釋它們來有選擇地豁免該類別的某些成員具有default可見性。這可以是內聯方法不應該形成ABI的一部分,因此,如果他們正在構建限定class Foo庫時發出的,它們不會被導出,或用於private成員或類型內class Foo也不應該形成的部分有用的其ABI。如何在每個成員的基礎上覆蓋類作用域__declspec(dllexport)註釋?

然而,在Windows上,似乎沒有手段來實現這一目標。雖然沒有修改過的class Foo對DLL自動是私有的,但一旦裝飾爲class __declspec(dllexport) Foo,整個類現在爲dllexport,並且似乎沒有關聯的註釋可以選擇性地覆蓋特定成員的__dllexport狀態。標記選擇「不適用於出口」的成員爲__declspec(dllimport)顯然是錯誤的。

有一些其他的方式,以防止類範圍__dllexport從適用於某一類成員和/或類型?

爲了使這更具體,我想該說些什麼了,可以說,使用ELF註釋時,是:

class __attribute__((visibility("default"))) Foo { 
public: 
    Foo(); // OK, default visibility 

    // Don't let inlines join the ABI 
    __attribute__((visibility("hidden")) inline void something() { ... } 

private: 
    // Don't let private members join the ABI 
    __attribute__((visibility("hidden")) void _internal(); 

    // Our pImpl type is also not part of the ABI. 
    struct __attribute__((visibility("hidden")) pimpl; 
}; 

但我不能形成使用MSVC同樣的事情屬性:

class __declspec(dllexport) Foo { 
public: 
    Foo(); // OK, dllexport'ed 

    // Don't let inlines join the ABI, but how to say it? 
    __declspec(???) inline void something() { ... } 

private: 
    // Don't let private members join the ABI, but how? 
    __declspec(???) void _internal(); 

    // Our pImpl type is also not part of the ABI, but how? 
    struct __declspec(???) pimpl; 
}; 

在現實世界中實現,我期望它們之間的差異,以宏背後隱藏。

是否有一些__declspec,我忽略了具有__attribute__((visibility("hidden")))的語義,並且可以覆蓋__declspec(dllexport)的類範圍應用程序?

+0

僅供參考_「內聯方法是不應構成ABI的一部分,「_內聯並不意味着內聯(除非使用編譯器特定的內聯擴展)。所以它們是ABI的一部分,內聯甚至不是大多數現代編譯器的暗示。 –

+0

另外,如果該類的公共方法調用私有方法(同一類)並且公共方法在客戶端應用程序中內聯;那麼私有方法需要是鏈接器可見的並且構成ABI的一部分。 –

+0

@Richard Critten對於你的第二個評論,完全同意,但這很容易理解 - 只是不要內聯那些必須要求私人成員的公共方法,而且在實踐中還沒有出現。對於你的第一條評論,我同意inline對於編譯器來說「甚至不是提示」,但它確實對鏈接有影響。考慮'-fvisibility-inlines-hidden'對ELF平臺的影響。我關於內聯不構成ABI一部分的論點取決於這樣一個觀點,即只要內聯方法簡單地委託給ABI方法,客戶端和庫的意義是否分歧並不重要。 – acm

回答

0

我從來沒有這樣的事,但是下面the MSDN documentation它應該是可能的。

您不應在課程級別指定任何__declspec,並且只爲您想要的成員指定__declspec(dllexport)

希望得到這個幫助。

1

MSDN documentation給出了它是如何做的想法。這是一個示例。

DLL_declspec.h:

#elif defined(BUILD_DLL) 
    #define DLL_DECLSPEC __declspec(dllexport) 
#else 
    #define DLL_DECLSPEC __declspec(dllimport) 
#endif 

導出整個類:

#include "DLL_declspec.h" 

class DLL_DECLSPEC TestExport 
{ 
    public: 

     TestExport(); 

     ~TestExport(); 

     std::string getName(); 

     int getID(); 
}; 

只導出類的精心挑選成員:

#include "DLL_declspec.h" 

class TestExport 
{ 
    public: 

     DLL_DECLSPEC TestExport(); 

     DLL_DECLSPEC ~TestExport(); 

     DLL_DECLSPEC std::string getName(); 

     int getID(); 
};