带有 void * 的 PInvoke 与带有 IntPtr 的结构

PInvoke with a void * versus a struct with an IntPtr

假设我有一个函数叫做

Myfunction(const void * x);

我的 C# 声明可以是

MyFunction(IntPtr x);

这在功能和技术上等同于

struct MyStruct { IntPtr P; }

MyFunction(MyStruct x);

或者它们的编组方式会有所不同。

我问这个是因为我正在调用的库都是 void *,类型定义为其他名称,并且在 C# 中我想获得类型安全,这是值得的。

如果你的 StructLayout 是 Sequential,那么它确实是相同的。

最简单的验证方法当然是亲自尝试一下:

创建一个 C++ Win32 DLL 项目:

extern "C"
{
    __declspec(dllexport) void MyFunction(const void* ptr)
    {
       // put a breakpoint and inspect
    }
}

创建一个 C# 项目:

    public struct Foo
    {
        public IntPtr x;
    }

    [DllImport(@"Win32Project1.dll", EntryPoint = "MyFunction", CallingConvention = CallingConvention.Cdecl)]
    public static extern void MyFunctionWithIntPtr(IntPtr x);

    [DllImport(@"Win32Project1.dll", EntryPoint = "MyFunction", CallingConvention = CallingConvention.Cdecl)]
    public static extern void MyFunctionWithStruct(Foo x);

    static void Main(string[] args)
    {
        IntPtr j = new IntPtr(10);
        var s = new Foo();
        s.x = new IntPtr(10);
        MyFunctionWithIntPtr(j);
        MyFunctionWithStruct(s);
    }

在您的调试设置中,确保您 select 启用本机调试。

您会看到这两个值都是 0xA。

但是请注意,如果您对 IntPtr 和 Struct 使用 out/ref 参数,它们将是不同的值。