一般規則和限制

Microsoft 特定的

  • 如果您宣告沒有 或 dllexport 屬性的 dllimport 函式或物件,則函式或物件不會被視為 DLL 介面的一部分。 因此,函式或物件的定義必須存在該模組中,或是相同程式的另一個模組中。 若要使 DLL 介面的函式或物件部分成為 ,您必須將另一個模組中函式或物件的定義宣告為 dllexport 。 否則會產生連結器錯誤。

    如果您使用 屬性宣告函式或物件 dllexport ,其定義必須出現在相同程式的某個模組中。 否則會產生連結器錯誤。

  • 如果程式中的單一模組同時包含 dllimport 相同函式或物件的 和 dllexport 宣告,則 dllexport 屬性會優先于 dllimport 屬性。 不過,這樣會產生編譯器警告。 例如:

    __declspec( dllimport ) int i;
    __declspec( dllexport ) int i;   // Warning; inconsistent;
                                     // dllexport takes precedence.
    
  • 在 C++ 中,您可以初始化全域宣告或靜態本機資料指標,或是使用 屬性所宣告 dllimport 之資料物件的位址,以在 C 中產生錯誤。此外,您可以使用以 屬性宣告 dllimport 之函式的位址,初始化靜態區域函式指標。 在 C 中,此類指派會將指標設定為 DLL 匯入 Thunk (將控制權傳送至函式的程式碼 Stub) 的位址,而不是設定為函式的位址。 在 C++ 中,它會將指標設定為函式的位址。 例如:

    __declspec( dllimport ) void func1( void );
    __declspec( dllimport ) int i;
    
    int *pi = &i;                             // Error in C
    static void ( *pf )( void ) = &func1;     // Address of thunk in C,
                                              // function in C++
    
    void func2()
    {
       static int *pi = &i;                  // Error in C
       static void ( *pf )( void ) = &func1; // Address of thunk in C,
                                             // function in C++
    }
    

    不過,由於在 dllexport 物件的宣告中包含 屬性的程式必須提供程式中該物件的定義,因此您可以使用函式的 dllexport 位址來初始化全域或本機靜態函式指標。 同樣地,您可以使用 dllexport 資料物件的位址初始化全域或區域靜態資料指標。 例如,下列程式碼不會在 C 或 C++ 中產生錯誤:

    __declspec( dllexport ) void func1( void );
    __declspec( dllexport ) int i;
    
    int *pi = &i;                              // Okay
    static void ( *pf )( void ) = &func1;      // Okay
    
    void func2()
    {
        static int *pi = &i;                   // Okay
        static void ( *pf )( void ) = &func1;  // Okay
    }
    
  • 如果您套用 dllexport 至基類未標示 dllexport 為 的一般類別,編譯器將會產生 C4275。

    如果基底類別是類別樣板的特製化,則編譯器會產生相同的警告。 若要解決此問題,請使用 標記基類 dllexport 。 類別範本的特製化問題在於放置 __declspec(dllexport) 的位置;您不允許標記類別範本。 相反地,請明確具現化類別範本,並以 標記這個明確的具現化 dllexport 。 例如:

    template class __declspec(dllexport) B<int>;
    class __declspec(dllexport) D : public B<int> {
    // ...
    

    如果樣板引數為衍生類別,則這個解決方法會失敗。 例如:

    class __declspec(dllexport) D : public B<D> {
    // ...
    

    由於這是範本的常見模式,因此編譯器在套用至具有一或多個基類的類別時,以及當一或多個基類是類別範本的特製化時,會變更 dllexport 的語意。 在此情況下,編譯器會隱含地套用 dllexport 至類別範本的特製化。 您可以執行下列動作,而不會收到警告:

    class __declspec(dllexport) D : public B<D> {
    // ...
    

END Microsoft 特定

另請參閱

dllexport、dllimport