传递指向本机函数的指针时出现AccessViolationException

时间:2019-07-17 12:54:55

标签: c# interop

我试图将结构的指针从C#代码传递给本机函数。我试图固定结构的内存,但是在运行程序的大约25%的时间里,我得到了AccessViolationException。

以下是无需编组/固定的基本代码:


结构:

public struct Foo
{
  private uint x;
  private uint y;
}

本地功能签名:

[DllImport(LibraryName, EntryPoint = "FooBar", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.StdCall)]
public static extern unsafe void Bar(Foo* data);

调用函数:

public void CallingFunction()
{
  unsafe
  {
    Foo data = new Foo();
    Bar(&data);
  }
}

到目前为止,我已经尝试过:

选项1(GCHandle.Alloc):

// In CallingFunction:
Foo data = new Foo();
GCHandle handle = GCHandle.Alloc(data, GCHandleType.Pinned);
IntPtr ptr = handle.AddrOfPinnedObject();
Foo* fooPtr = (Foo*)ptr.ToPointer();
Bar(fooPtr);
handle.Free();

选项2(本机函数签名中的MarshalAs):

public static extern unsafe void Bar([MarshalAs(UnmanagedType.LPArray)] Foo* data);

选项3(Marshal.AllocHGlobal):

// In CallingFunction:
Foo* data = (Foo*)Marshal.AllocHGlobal(sizeof(Foo));
Bar(data);
Marshal.FreeHGlobal((IntPtr)data);

选项4(KeepAlive):

// At the end of CallingFunction():
GC.KeepAlive(data);

使用每个选项,我仍然会收到AccessViolationException。我究竟做错了什么?

谢谢!

1 个答案:

答案 0 :(得分:-1)

尝试以下操作:

        [DllImport(LibraryName, EntryPoint = "FooBar", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.StdCall)]
        public static extern void Bar(IntPtr data);
        static void Main(string[] args)
        {

            Foo data = new Foo();
            IntPtr ptr = Marshal.AllocHGlobal(Marshal.SizeOf(data));
            Marshal.StructureToPtr(data, ptr, true);

            Bar(ptr);
        }

        public struct Foo
        {
            private uint x;
            private uint y;
        }