[英]marshalling C and C#
我的项目中有以下编组代码。 我对此几乎没有疑问。
[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 ?
为什么需要“内部静态外部”?
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
之前声明,则内存布局在B
之前具有A
)。 这在声明顺序很重要的C语言中是不正确的(声明由编译器用来理解内存中原始数据的布局)。 如果必须与C函数互操作,则必须确定传递它们的数据的布局。 这就是LayoutKind.Sequential
工作方式:它指示编译器遵守struct
数据的声明顺序。 这不是与非托管环境互操作的唯一选项,您甚至可以显式设置每个字段的偏移量(从结构开始)(请参见LayoutKind.Explicit)。
这不是一个答案,只有几点评论:调用外部dll时,“内部静态”是一回事,而“外部”则是另一回事。 SetLastError或GetLastError是我们在过去的日子中经常使用的方法,用于从Windows获取有关最新处理的错误消息。 LayoutKind.Sequential是一种通知编译器以指定方式布局结构的方法-如果进入其他系统,则可能需要这样做。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.