.net - 組件名稱 - 如何在VS版本中製作一致的dll二進製文件?




強式名稱驗證失敗 (2)

例如,winsock庫在所有版本的Visual Studio中都很有用。 但是,在所有版本中提供一致的二進製文件是非常麻煩的。 與VS 2005編譯的DLL在鏈接到2008年編寫的應用程序時將不起作用。我將2k5和2k8都升級到了SP1,但結果並沒有太大改變。 它工作一些什麼好的。 但是,當他們將這個包含在C#應用程序中時,C#應用程序會發生訪問衝突錯誤,但是對於經典的C ++應用程序來說,它工作正常。

當我提供dll時,是否有一個我應該知道的策略?


關於通過一個結構的問題,這個東西是安全的,只要你對齊你的結構如:


#pragma pack(push,4)
typedef myStruct {
  int a;
  char b;
  float c;
}myStruct;
#pragma pack(pop)

你可以把這個聲明放在一個頭文件中,並將其包含在兩個項目中。 這樣,你在傳遞結構時就不會有任何問題。

此外,請確保與運行時庫靜態鏈接,並且不要嘗試在模塊中分配內存(ptr = malloc(1024))等內容,然後在另一個模塊(free(ptr))中釋放該內存。


首先,除了DLL邊界之外的普通舊數據之外,不要傳遞任何東西。 即結構很好。 班級不是。 其次,確保所有權不被轉移 - 即任何通過dll邊界的結構都不會在dll外部釋放。 因此,如果您將導出一個X * GetX()函數,則會有一個對應的FreeX(X *)類型函數,以確保分配的相同運行時負責解除分配。

下一步:讓你的DLL鏈接到靜態運行時。 把幾個第三方的dls整合在一起,每個鏈接和期望不同的運行時間,可能不同於應用程序所期望的運行時間,這是一個痛苦,可能迫使安裝程序軟件安裝7.0,7.1,8.0和9.0的運行時間 - 其中幾個存在於不同的服務包中,這可能會或可能不會引起問題。 善待 - 靜態鏈接你的dll項目。

- 編輯:你不能直接用這種方法導出一個c ++類。 在模塊之間共享類定義意味著你必須有一個同類的運行時環境,因為不同的編譯器或版本的編譯器會產生不同的裝飾名稱。

可以通過導出你的類而不是以COM風格的接口繞過這個限制...也就是說,當你不能以獨立於運行時的方式導出類的時候,你可以導出一個“接口”,你可以通過聲明一個只包含純虛函數的類

  struct IExportedMethods {
    virtual long __stdcall AMethod(void)=0;
  };
  // with the win32 macros:
  interface IExportedMethods {
    STDMETHOD_(long,AMethod)(THIS)PURE;
  };

在你的類定義中,你從這個接口繼承:

  class CMyObject: public IExportedMethods { ...

你可以通過C工廠方法導出這樣的接口:

  extern "C" __declspec(dllexport) IExportedClass* WINAPI CreateMyExportedObject(){
    return new CMyObject; 
  }

這是導出編譯器版本和運行時獨立類版本的一種非常輕量級的方式。 請注意,您仍然無法刪除其中的一個。 您必須包含釋放函數作為dll或界面的成員。 作為接口的成員,它可能看起來像這樣:

  interface IExportedMethods {
    STDMETHOD_(void) Release(THIS) PURE; };
  class CMyObject : public IExportedMethods {
    STDMETHODIMP_(void) Release(){
      delete this;
    }
  };

你可以採取這個想法,並進一步運行它 - 從IUnknown繼承你的接口,實現ref counting AddRef和Release方法,以及QueryInterface for v2接口或其他功能的能力。 最後,使用DllCreateClassObject作為創建對象的手段,並獲得必要的COM註冊。 所有這些都是可選的,但是你可以輕鬆地通過一個C函數訪問一個簡單的接口定義。





dll