我的项目中有以下编组代码。我对此几乎没有问题。
[DllImport=(Core.dll, SetLastError=true, EntryPoint="CoreCreate", CharSet="CharSet.Ansi", CallingConvention="CallingConvention.Cdecl")]
internal static extern uint CoreCreate(ref IntPtr core);
[StructLayout(LayoutKind.Sequential,CharSet=CharSet.Ansi)] internal struct Channel { internal byte LogicalChannel; }
为什么 LayoutKind.Sequential ?
答案 0 :(得分:4)
为什么需要'内部静态外部'?
internal
修饰符只是设置方法的可见性。它不一定是internal
,因此您可以根据需要声明方法private
或public
,也可以像使用任何其他标准方法一样。
static
修饰符是必需的,因为它不是实例方法,并且该方法不知道任何类(它没有this
指针)。
最后需要extern
通知编译器该方法不是在这里实现的,而是在另一个地方实现的(并且您将指定使用属性的位置)。 Evey extern
方法也必须声明为static
(因为它是一个简单的函数调用,不需要任何关于对象的知识)。
什么是SetLastError?
它表示该方法可能会更改线程的最后错误代码值。有关详细信息,请参阅GetLastError()
功能。如果被调用函数将更改此值,那么从MSDN将SetLastError
设置为true
是一件好事:
运行时封送程序调用GetLastError,缓存返回的值,以防止其被其他API调用覆盖。您可以通过调用GetLastWin32Error来检索错误代码。
简而言之,它将GetLastError()返回的值保存到内部缓存中,因此对系统API的任何其他调用(甚至是其他框架函数的内部调用)都不会覆盖该值。
为什么选择LayoutKind.Sequential?
.NET中的类布局不需要在内存中是顺序的(顺序=如果在A
之前声明B
,那么内存布局在A
之前有B
) 。这在声明顺序很重要的C中是不正确的(编译器使用声明来理解原始数据的内存布局)。如果必须与C函数互操作,则必须确保传递它们的数据的布局。这就是LayoutKind.Sequential
的工作原理:它指示编译器遵守struct
中数据的声明顺序。这不是与非托管世界互操作的唯一选项,您甚至可以显式设置每个字段的偏移量(从结构开始)(参见LayoutKind.Explicit)。
答案 1 :(得分:1)
这不是答案,只是一些评论: “内部静态”是一回事,“外部”是调用外部dll时需要的另一个东西。 SetLastError或GetLastError是我们在“旧”时代大量使用的方法,用于从Windows获取有关最新处理的错误消息。 LayoutKind.Sequential是一种通知编译器以指定方式布局结构的方法 - 如果将其转换为其他系统,则可能需要执行此操作。