簡體   English   中英

用於非托管互操作的C#對象的指針

[英]Pointer of a C# object for unmanaged interop

我目前正在為PhysFS庫編寫包裝器,但偶然發現了有關管理對象編組的一些麻煩。 PHYSFS_enumerateFilesCallback方法為例,該方法將函數指針和用戶定義的指針作為其參數。 如何將托管對象傳遞給此方法? 這是我目前正在做的:

// This is the delegate signature
public delegate void EnumFilesCallback(IntPtr data, string origdir, string fname);

// This is the method signature
[DllImport(DLL_NAME, CallingConvention = CallingConvention.Cdecl)]
public static extern void PHYSFS_enumerateFilesCallback(string dir, EnumFilesCallback c, IntPtr d);

最后,這就是將任意對象傳遞給方法的工作:

// I use the unsafe keyword because the whole Interop class is declared so.
// This code was taken from https://msdn.microsoft.com/en-us/library/system.runtime.interopservices.gchandle(VS.71).aspx
public static void EnumerateFilesCallback(string dir, EnumFilesCallback c, object data)
{
  unsafe
  {
    GCHandle objHandle = GCHandle.Alloc(data);
    Interop.PHYSFS_enumerateFilesCallback(dir, c, (IntPtr)objHandle);
    objHandle.Free();
  }
}

當我運行此代碼時:

static void Enum(IntPtr d, string origdir, string fname )
{
  System.Runtime.InteropServices.GCHandle handle = (System.Runtime.InteropServices.GCHandle)d;
  TestClass c = (TestClass)handle.Target;
  Console.WriteLine("{0} {1}", origdir, fname);
}

static void Main(string[] args)
{
  PhysFS.Init("");
  PhysFS.Mount("D:\\", "/hello", true);

  TestClass x = new TestClass() { a = 3, b = 4 }; // This can be any gibberish object

  PhysFS.EnumerateFilesCallback("/hello/", Enum, x);
}

代表被合法數據調用4次,第五次包含垃圾數據,然后拋出AccessViolationException我懷疑這是因為對象在調用調用之間被GC了。 誰能闡明這一點?

更新:更改掛載的目錄消除了垃圾數據,但仍引發異常,並且仍在使用所有數據之前

您是否嘗試過創建回調並將其存儲為類靜態字段?

private static EnumFilesCallback callback = new EnumFilesCallback(Enum);

在您的主要方法中:

PhysFS.EnumerateFilesCallback("/hello/", callback, x);

這可能應該避免GC收集保存委托對象的局部變量。

感謝所有花費時間嘗試提供答案的人! 我終於找到了問題的根源並解決了!

問題是……我對此感到as愧…… 稱慣例 所有PInvoked方法都聲明為cdecl,而我忘了這樣聲明委托,因此它創建了不平衡的堆棧,混亂和其他...

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM