繁体   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