编组C和C#

时间:2012-10-10 09:15:47

标签: c# marshalling unmarshalling

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

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

    为什么 LayoutKind.Sequential

2 个答案:

答案 0 :(得分:4)

  

为什么需要'内部静态外部'?

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

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是一种通知编译器以指定方式布局结构的方法 - 如果将其转换为其他系统,则可能需要执行此操作。