2012-10-10 37 views
1

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

[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

+2

我认为这篇文章会帮助http://msdn.microsoft.com/en-us/library/aa288468(v=vs.71).aspx – Prasad

+0

这似乎是多个问题,应该可能创建为单独的帖子 – musefan

回答

4

为什么'内部静态外部'是必需的?

internal修饰符只是设置您的方法的可见性。并非必须为internal,因此您可以根据需要声明方法privatepublic,如同使用任何其他标准方法一样。

static修改是必需的,因为它不是一个实例方法和方法不知道任何类(它不是一个this指针)。

最后extern需要通知编译器该方法没有在这里实现,但在另一个地方(你会指定使用属性的地方)。 Evey extern方法也必须声明为static(因为它是一个简单的函数调用,没有任何有关对象的知识)。

什么是SetLastError?

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

封送调用GetLastError函数和缓存返回值,以防止它通过被覆盖的运行时的其它API调用 。您可以通过调用GetLastWin32Error来检索错误代码。

总之它可以节省由GetLastError()可内部缓存,因此任何其他调用系统API(甚至内部别人框架功能)将不会覆盖该值返回的值。

为什么LayoutKind.Sequential?在.NET

类布局不需要在存储器中的顺序(顺序=如果AB然后存储器布局具有AB之前之前被声明)。在声明顺序非常重要的C中,这是不正确的(编译器使用声明来理解原始数据在内存中的布局)。如果您必须与C函数进行互操作,那么您必须确定所传递数据的布局。这就是LayoutKind.Sequential的工作原理:它指示编译器遵守struct中数据的声明连续顺序。这不是与非托管世界互操作的唯一选项,您甚至可以明确设置每个字段的偏移量(参见LayoutKind.Explicit)。

1

这不是一个答案,只是几个意见: “内部静态”是一回事,“外部”是调用外部DLL时需要的另一件事情。 SetLastError或GetLastError是我们在“旧时代”使用很多方法从窗口获取有关最新处理的错误消息。 LayoutKind.Sequential是一种通知编译器以指定的方式布局结构的方法 - 如果交给其他系统,则可能需要执行此操作。

+0

也许把它作为评论而不是答案呢? – musefan

+0

所以,它必须是一个评论。此外,一对'static extern'是'DllImport'的必备条件。因此,“内部”是一回事,“静态外部”是另一回事。 – Dennis

+0

容易的家伙 - 看来我不允许在问题中添加评论! –