1

我的项目中有以下编组代码。我对此有几个问题。

[DllImport=(Core.dll, SetLastError=true, EntryPoint="CoreCreate", CharSet="CharSet.Ansi", CallingConvention="CallingConvention.Cdecl")]
internal static extern uint CoreCreate(ref IntPtr core);
  1. 为什么需要“内部静态外部”?这是强制性的吗?为什么使用这个?
  2. 什么是SetLastError
[StructLayout(LayoutKind.Sequential,CharSet=CharSet.Ansi)]
internal struct Channel
{
internal byte LogicalChannel;
}

为什么是 LayoutKind.Sequential

4

2 回答 2

4

为什么需要“内部静态外部”?

internal修饰符只是设置方法的可见性。它不是必需的,internal因此您可以声明该方法privatepublic根据需要声明该方法,并且可以像使用任何其他标准方法一样。

修饰符是必需的static,因为它不是实例方法并且该方法不知道任何类(它没有this指针)。

最后extern需要通知编译器该方法没有在此处实现,而是在另一个地方实现(您将指定使用属性的位置)。Eveyextern方法也必须声明static(因为它是一个简单的函数调用,没有任何关于对象的知识)。

什么是 SetLastError?

它表示该方法可能会更改线程的最后一个错误代码值。有关此GetLastError()功能的详细信息,请参见函数。SetLastError如果被调用的函数会改变这个值,那么设置为是一件好事true,来自 MSDN:

运行时封送处理程序调用 GetLastError 并缓存返回的值以防止它被其他 API 调用覆盖。您可以通过调用 GetLastWin32Error 来检索错误代码。

简而言之,它将 GetLastError() 返回的值保存到内部缓存中,因此对系统 API 的任何其他调用(甚至是其他框架函数的内部)都不会覆盖该值。

为什么是 LayoutKind.Sequential?

.NET 中的类布局不需要在内存中是顺序的(顺序 = ifA在之前声明,B然后内存布局在A之前B)。在声明顺序很重要的 C 中,情况并非如此(编译器使用声明来理解原始数据在内存中的布局)。如果您必须与 C 函数进行互操作,那么您必须确定传递给它们的数据的布局。这就是LayoutKind.Sequential工作原理:它指示编译器尊重struct. 这不是与非托管世界互操作的唯一选项,您甚至可以显式设置每个字段的偏移量(从结构开始)(请参阅 LayoutKind.Explicit)。

于 2012-10-10T09:26:33.870 回答
1

这不是一个答案,只是一些评论:“内部静态”是一回事,“外部”是调用外部 dll 时需要的另一件事。SetLastError 或 GetLastError 是我们在“旧”时代经常使用的方法,用于从 Windows 获取有关最新处理的错误消息。LayoutKind.Sequential 是一种通知编译器以指定方式布局结构的方法 - 如果向其他系统行进,您可能需要这样做。

于 2012-10-10T09:25:26.743 回答