2011-09-11 65 views
5

我有一個非託管庫暴露了一些接口。用戶可以使用自定義實現來實現接口並將其粘貼到庫中。使用非託管接口管理包裝

我想爲這個庫提供一個託管包裝。 使用託管界面包裝非託管界面非常簡單。但在我的情況下,我想支持各種接口的用戶實現,這意味着我需要接受一個接口的託管實現,並在將它發送到庫的非託管部分的深處之前,使用其非託管對象進行包裝。

我想是這樣的:

class UnmanagedWrapper { 
DoSomething() {m_clr.DoSomething();} 
IManaged^ m_clr; 
} 

但非託管類中我不能有管理成員時,編譯器理所當然地聲稱。

我可以在這裏做任何事嗎?

+1

沒有足夠的上下文。使用gcroot <>或Marshal :: GetFunctionPointerForDelegate()。 –

回答

0

以下是一些相關信息,用於解決一個庫不受管理且託管語言使用這些庫時的變通方法。

該信息的情況下是使用GoogleTest在Visual Studio的方式:如果你把你的測試到 庫

Getting started with Google C++ Testing Framework

重要提示適用於Visual C++的用戶和您的main()函數位於不同的庫中或您的 .exe文件中,那些測試將不會運行。原因是Visual C++中的一個錯誤。當您定義測試時,Google Test會創建一些靜態的 對象來註冊它們。這些對象在其他地方不是從 引用的,但它們的構造函數仍然應該運行。當 Visual C++鏈接器發現庫中沒有任何內容從 引用到其他位置時,它將庫引出。您必須引用您的 庫與您的主程序的測試,以保持鏈接從 丟棄它。這是如何做到這一點。在某處,庫代碼 聲明函數:

__declspec (dllexport) int PullInMyLibrary() { return 0; }

如果你把你的測試靜態庫(DLL沒有),那麼__declspec(dllexport)的是不需要

。現在,在你的主程序,編寫調用 一個代碼,功能:

int PullInMyLibrary(); 
    static int dummy = PullInMyLibrary(); 

這將 保持你的測試引用,會讓他們在 啓動註冊自己。此外,如果您在靜態庫中定義測試,請將 /OPT:NOREF添加到主程序鏈接器選項中。如果您使用MSVC++ IDE, 轉到您的.exe項目屬性/配置 屬性/鏈接器/優化,並將參考設置設置爲保留 未引用數據(/ OPT:NOREF)。這將保持來自 的Visual C++鏈接器從最終的 可執行文件中丟棄由測試生成的單個符號。

但還有一個缺陷。如果您使用Google Test作爲靜態庫 (這是gtest.vcproj中定義的方式),那麼測試必須 也駐留在靜態庫中。如果您必須將它們放入DLL中,您必須將Google Test更改爲DLL。否則, 您的測試將無法正常運行或根本無法運行。一般的 這裏的結論是:讓你的生活更輕鬆 - 不要在 圖書館寫你的測試!

0

也許gcroot<>是你想要什麼:

class UnmanagedWrapper { 
    DoSomething() {m_clr.DoSomething();} 
    gcroot<IManaged^> m_clr; 
} 
0

您需要導入非託管的DLL到C#.NET應用程序。我的例子返回一個指向結構的指針,但你可以提供你的應用需要的任何其他返回類型。一定要使用dumpbin.exe/EXPORTS從dll中獲取整個函數/ EntryPoint名稱。這裏是我的全班同學:

using System; 
using System.Runtime.InteropServices; 

namespace aviationLib 
{ 
    public struct MAGtype_GeoMagneticElements 
    { 
     public double Decl; /* 1. Angle between the magnetic field vector and true north, positive east*/ 
     public double Incl; /*2. Angle between the magnetic field vector and the horizontal plane, positive down*/ 
     public double F; /*3. Magnetic Field Strength*/ 
     public double H; /*4. Horizontal Magnetic Field Strength*/ 
     public double X; /*5. Northern component of the magnetic field vector*/ 
     public double Y; /*6. Eastern component of the magnetic field vector*/ 
     public double Z; /*7. Downward component of the magnetic field vector*/ 
     public double GV; /*8. The Grid Variation*/ 
     public double Decldot; /*9. Yearly Rate of change in declination*/ 
     public double Incldot; /*10. Yearly Rate of change in inclination*/ 
     public double Fdot; /*11. Yearly rate of change in Magnetic field strength*/ 
     public double Hdot; /*12. Yearly rate of change in horizontal field strength*/ 
     public double Xdot; /*13. Yearly rate of change in the northern component*/ 
     public double Ydot; /*14. Yearly rate of change in the eastern component*/ 
     public double Zdot; /*15. Yearly rate of change in the downward component*/ 
     public double GVdot; /*16. Yearly rate of change in grid variation*/ 
    }; 

    public class Declination 
    { 
     [DllImport("wmm.dll", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Unicode, EntryPoint = "[email protected]@[email protected]@[email protected]")] 
     public static extern IntPtr GeoMagneticElements(float sdate, int igdgc, int units, float alt, float latitude, float longitude); 

     public MAGtype_GeoMagneticElements e; 

     public MAGtype_GeoMagneticElements MagDeclination(float decimalLat, float decimalLon) 
     { 

      try 
      { 
       String d = DateTime.Now.Year.ToString("D4") + '.' + DateTime.Now.Day.ToString("D1"); 
       IntPtr pnt = GeoMagneticElements((float)Convert.ToDouble(d), 1, 3, 3000.0f, decimalLat, decimalLon); 
       e = Marshal.PtrToStructure<MAGtype_GeoMagneticElements>(pnt); 
      } 
      catch (System.EntryPointNotFoundException se) 
      { 
       Console.WriteLine(se.Message); 
      } 

      return e; 
     } 
    } 
} 

Word設置必須爲同一兩個託管和非託管所以如果DLL是32位的,則.NET必須爲好。