我非常兴奋的宣布我们最近发布了一个工具,这个工具对我们在托管代码中使用PInvoke非常有用。这个工具的名 字是“PInvoke Interop Assistant”,“PInvoke Interop Assistant”作为PInvoke和Reverse PInvoke场景的一部分已经被包含在MSDN文章中。
下面的链接是文章和工具
开发这个工具背后的动力是写PInvoke是一个艰难并且乏味的任务。有很多规则必须遵守,很多异常必须要考虑到。所有在简单的数据结构之外的东西必须专心的做,C当中微妙的语义会很大程度上改变所需的签名。不正确的翻译经常会导致不明确的异常或者崩溃。
简而言之,这个差事没有什么乐趣。
这个工具可以用很多方式让PInvoke产生更简单的进程。目标是为struct,unions,enums,constants,functions,typedefs等等产生尽可能简单的托管代码。这些代码可以在VB和C# 中生成。
工具中三个选项卡的GUI版本:
1. Siglmp Search: 搜索常用的方法,然后翻译成托管代码。
2. Siglmp Translate Snippet:直接翻译C代码到托管的PInvoke签名中去。
3. SigExp:转换托管的二进制代码到C++ Reverse PInvoke 场景中。
前面两个是我的工作部分,也是代表PInvoke的场景。第三个是Ladi Prosek写的,这部分另外一篇文章会讲到。我们选择Siglmp和SigExp这两个名字来反映工具tblimp/tlbexp,因为他们有差不多的方法。
直接翻译C代码到PInvoke签名中
在PInvoke中大部分的冒险是,开发者想用托管代码中的一小部分C代码。典型的是一两个有C结构体的方法。以前,所有这样的情况需要从一开始就翻译进托管代码中。用这个工具,你只需要把代码粘贴到这个工具里面,然后它就会生成相应的签名。
例如假设你想翻译下面的C代码到VB。
struct S1
{
int a;
char[10] b;
};
float CalculateData(S1* p);
把工具打开,转换到“Siglmp Translate Snippet”选项。粘贴这些代码,然后按Generate按钮。
你也可以按“Auto Generate“,然后看着你键入的代码更新。
搜索常用的方法
通常开发者想在托管代码中用他们熟悉的C函数。这也是一个乏味的任务,因为如果这个签名现在还不是可以得到的,那么你就要从头编码。如果你不知道到哪个头文件里面去查的话,加一个常量是不易处理的。
这个工具提供了一个有常用的方法,结构体,常量等的数据库。基本上windows.h包含了所有的东西。转换到Siglmp的搜索键,键入你想搜索的名字,然后敲generate。例如你想看WM_PAINT的值。
另外,工具的这部分还会做附属的分析。例如,选择一个有C结构的方法,它会自动生成方法的结构。例如,你选择FindFirstFile,它会知道这个方法依赖于WIN32_FIND_DATA这个结构。另外,它还会注意到WIN32_FIND_DATA依赖于FILETIME然后会生成这两个到方法里面去。
<System.Runtime.InteropServices.StructLayoutAttribute( _System.Runtime.InteropServices.LayoutKind.Sequential, _CharSet:=System.Runtime.InteropServices.CharSet.[Unicode])> _Public Structure WIN32_FIND_DATAW'''DWORD->unsigned intPublic dwFileAttributes As UInteger'''FILETIME->_FILETIMEPublic ftCreationTime As FILETIME'''FILETIME->_FILETIMEPublic ftLastAccessTime As FILETIME'''FILETIME->_FILETIMEPublic ftLastWriteTime As FILETIME'''DWORD->unsigned intPublic nFileSizeHigh As UInteger'''DWORD->unsigned intPublic nFileSizeLow As UInteger'''DWORD->unsigned intPublic dwReserved0 As UInteger'''DWORD->unsigned intPublic dwReserved1 As UInteger'''WCHAR[260]<System.Runtime.InteropServices.MarshalAsAttribute( _System.Runtime.InteropServices.UnmanagedType.ByValTStr, SizeConst:=260)> _Public cFileName As String'''WCHAR[14]<System.Runtime.InteropServices.MarshalAsAttribute( _System.Runtime.InteropServices.UnmanagedType.ByValTStr, SizeConst:=14)> _Public cAlternateFileName As StringEnd Structure<System.Runtime.InteropServices.StructLayoutAttribute( _System.Runtime.InteropServices.LayoutKind.Sequential)> _Public Structure FILETIME'''DWORD->unsigned intPublic dwLowDateTime As UInteger'''DWORD->unsigned intPublic dwHighDateTime As UIntegerEnd StructurePartial Public Class NativeMethods'''Return Type: HANDLE->void*'''lpFileName: LPCWSTR->WCHAR*'''lpFindFileData: LPWIN32_FIND_DATAW->_WIN32_FIND_DATAW*<System.Runtime.InteropServices.DllImportAttribute("kernel32.dll", EntryPoint:="FindFirstFileW")> _Public Shared Function FindFirstFileW( _<System.Runtime.InteropServices.InAttribute(), _System.Runtime.InteropServices.MarshalAsAttribute(System.Runtime.InteropServices.UnmanagedType.LPWStr)> _ByVal lpFileName As String, _<System.Runtime.InteropServices.OutAttribute()> _ByRef lpFindFileData As WIN32_FIND_DATAW) As System.IntPtrEnd FunctionEnd Class
翻译大量的代码
小的翻译器适合翻译小的代码段。如果你想要翻译大量的代码,像彼此依赖的头文件的话,小的翻译器就不会工作得很好了。你应该用这个工具的命令行的版本来翻译大量的代码。sigimp.exe。它是被设计用来进行很多头文件的翻译工作,然后产生大量的输出。
结语
以前这个工具就像是我项目的宠物。我十分的兴奋,现在客户可以利用它的优点,我也期待你们给我回馈。稍后,我会帖更多关于这个工具是怎么工作的文章。
打印 | 张贴于 2008-10-28 14:23:20 | Tag:VB Team Blog Did you know?
留言反馈