天天看點

在ObjectARX的類定義中使用__declspec(dllimport)的危險

在一個準備導出到其它應用中的類(Class)上使用

__declspec(dllimport)

指令時,會導緻虛函數表(vtables)駐留在所有執行個體化過該類的dll中。

如果任何一個執行個體化過該類的dll被解除安裝,所有在該dll中建立的執行個體都會失效。随後通路這些失效執行個體的虛函數時就會導緻記憶體錯誤。

是以,唯一安全地使用這個指令的辦法,就是強制要求任何執行個體化過該類的應用都不允許解除安裝。

為了確定這一要求,你必須要麼在文檔中明确說明,或者提供一個僞構造函數駐留在無法被解除安裝的dll中。

最好的方法就是避免使用這個指令。

唯一的例外就是如果這個類(Class)導出了一個靜态成員變量。

在這種情況下你應該隻在這個變量上使用

__declspec(dllimport)

,但是你應該避免把它應用到整個class。但是我們不推薦導出靜态成員變量。

本警告僅限于

__declspec(dllimport)

,它并不适用于

__declspec(dllexport)

.

建議的用法如下所示:

#pragma warning( disable: 4275 4251 )
#ifdef POLYSAMP
#define DLLIMPEXP __declspec( dllexport )
#else
#define DLLIMPEXP
#endif

// The "DLLIMPEXP" is only required for exporting a poly API or using
// the exported API.  It is not necessary for any custom classes that
// are not exporting an API of their own.
//
class DLLIMPEXP AsdkPoly: public  AcDbCurve
{
public:
    ACRX_DECLARE_MEMBERS(AsdkPoly);
//*****************************************************************
// Constructors and destructor
//*****************************************************************
           

實際應用中,除非不使用該Class,否則無法隻對靜态成員變量使用

__declspec(dllimport)

附:

__declspec(dllimport)

的主要用法:

1. 在導入動态連結庫中的全局變量

2. 導出類的靜态成員

3.隐式使用dll時,在生成的二進制代碼上效率有所提高,可以節省一個跳轉指令。

MSDN裡的解釋:

不使用 __declspec(dllimport) 也能正确編譯代碼,但使用

__declspec(dllimport)

使編譯器可以生成更好的代碼。編譯器之是以能夠生成更好的代碼,是因為它可以确定函數是否存在于 DLL中,這使得編譯器可以生成跳過間接尋址級别的代碼,而這些代碼通常會出現在跨 DLL 邊界的函數調用中。但是,必須使用__declspec(dllimport) 才能導入 DLL 中使用的變量。

參考資料:

http://blog.csdn.net/mniwc/article/details/7993361

http://blog.csdn.net/Repeaterbin/article/details/4269666