带有 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 参数,它们将是不同的值。
假设我有一个函数叫做
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 参数,它们将是不同的值。