我的项目中有以下编组代码。我对此几乎没有疑问。
[DllImport=(Core.dll, SetLastError=true, EntryPoint="CoreCreate", CharSet="CharSet.Ansi", CallingConvention="CallingConvention.Cdecl")]
internal static extern uint CoreCreate(ref IntPtr core);
为什么需要“内部静态外部”?这是强制性的吗?为什么要使用它?
什么是SetLastError?
[StructLayout(LayoutKind.Sequential,CharSet=CharSet.Ansi)]
internal struct Channel
{
internal byte LogicalChannel;
}
为什么选择LayoutKind.Sequential?
最佳答案
为什么需要“内部静态外部”?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)。