我正在尝试为P / Invoking执行此辅助函数,目的是帮助确定哪个应该是最适合的托管类型,以声明Windows API定义的特定编组。
我从这里获取了信息: UnmanagedType Enumeration
在C#或Vb.Net中,我请求帮助填补空白案例并修复我当前的错误(如果有的话)。
(另外,作为一个可选和定向的问题回答与否:你认为编写相反的东西是可靠的吗?是一种ManagedTypeToUnmanagedTypeEnum
函数。)
Public Shared Function UnmanagedTypeToManagedType(ByVal [type] As UnmanagedType) As Type
Select Case [type]
Case UnmanagedType.AnsiBStr
Return GetType(String)
Case UnmanagedType.AsAny
Return GetType(Object)
Case UnmanagedType.BStr
Return GetType(String)
Case UnmanagedType.Bool
Return GetType(Boolean)
Case UnmanagedType.ByValArray
Case UnmanagedType.ByValTStr
Case UnmanagedType.Currency
Return GetType(Decimal)
Case UnmanagedType.CustomMarshaler
Return GetType(Object)
Case UnmanagedType.Error
Return GetType(IntPtr)
Case UnmanagedType.FunctionPtr
Return GetType([Delegate])
Case UnmanagedType.I1
Return GetType(SByte)
Case UnmanagedType.I2
Return GetType(Short)
Case UnmanagedType.I4
Return GetType(Integer)
Case UnmanagedType.I8
Return GetType(Long)
Case UnmanagedType.IDispatch
Return GetType(IntPtr)
Case UnmanagedType.Interface
Return GetType(IntPtr)
Case UnmanagedType.IUnknown
Return GetType(IntPtr)
Case UnmanagedType.LPArray
Return GetType(IntPtr)
Case UnmanagedType.LPStr
Return GetType(StringBuilder)
Case UnmanagedType.LPStruct
Return GetType(IntPtr)
Case UnmanagedType.LPTStr
Return GetType(String)
Case UnmanagedType.LPWStr
Return GetType(String)
Case UnmanagedType.R4
Case UnmanagedType.R8
Case UnmanagedType.SafeArray
Case UnmanagedType.Struct
Case UnmanagedType.SysInt
Return GetType(IntPtr)
Case UnmanagedType.SysUInt
Return GetType(UIntPtr)
Case UnmanagedType.TBStr
Return GetType(String)
Case UnmanagedType.U1
Return GetType(Byte)
Case UnmanagedType.U2
Return GetType(UShort)
Case UnmanagedType.U4
Return GetType(UInteger)
Case UnmanagedType.U8
Return GetType(ULong)
Case UnmanagedType.VariantBool
Return GetType(Boolean)
Case UnmanagedType.VBByRefStr
Return GetType(String)
Case Else
Throw New InvalidEnumArgumentException(argumentName:="type", invalidValue:=[type],
enumClass:=GetType(UnmanagedType))
Return Nothing
End Select
End Function
答案 0 :(得分:3)
Case UnmanagedType.Error
Return GetType(IntPtr)
没有。 IntPtr表示一个虚拟地址,在32位平台上为32位,在64位平台上为64位。但是UnmanagedType.Error
具有固定的大小。它是一个32位有符号整数,主要用于表示操作的编码结果。这是一个用词不当,因为它not always indicate an error。
Case UnmanagedType.IDispatch
Return GetType(IntPtr)
Case UnmanagedType.Interface
Return GetType(IntPtr)
Case UnmanagedType.IUnknown
Return GetType(IntPtr)
您应该使用System.Object
。 UnmanagedType.Struct
也是如此。
Case UnmanagedType.LPStr
Return GetType(StringBuilder)
好吧,你可以使用StringBuilder或String,它取决于被调用的函数。如果您正在进行常规转换,则应该使用String。
Case UnmanagedType.R4
Case UnmanagedType.R8
这些分别对应System.Single
和System.Double
。
Case UnmanagedType.VariantBool
Return GetType(Boolean)
VariantBool
是一个2字节的布尔类型,但VB布尔类型是4字节。您需要使用有符号或无符号的2字节整数类型。
Case UnmanagedType.VBByRefStr
Return GetType(String)
没有。 VBByRefStr
表示通过引用传递字符串。 That is, the address of the reference of the string.因此,您应该返回Object
或IntPtr
。该网页还说明UnmanagedType.ByValTStr
是String
。
UnmanagedType.ByValArray
,UnmanagedType.LPArray
和UnmanagedType.SafeArray
全部对应System.Array
。我强烈建议您阅读this文章,以便更好地了解这些类型。此外,如果可能,您应该使用this技术创建更专业的数组类型。
最后,我想您或忘记或遗忘UnmanagedType.HString
和UnmanagedType.IInspectable
,分别对应String
和Object
。
我建议按如下方式对switch开关案例进行分组:数组类型,字符串类型,基本类型,其他指针类型和其他整数类型。
答案 1 :(得分:2)
对于此类直接类似功能的翻译/映射(即每个唯一X
只有Y
的一个值),我建议使用{{1而不是Dictionary
case
<强> VB.Net/C#强>
switch
Dim unToManagedDict As New Dictionary(Of UnmanagedType, Type) 'VB.Net
然后在您的应用首次加载中列出您的Dictionary<UnmanagedType, Type> unToManagedDict = new Dictionary<UnmanagedType, Type>(); //C#
UnmanagedType
,如下所示:
<强> VB.Net/C#强>
enum
unToManagedDict.Add(UnmanagedType.AnsiBStr,typeof(string)); //C# unToManagedDict.Add(UnmanagedType.AsAny,typeof(object)); //C# //等等......
因此,要检查托管对方的存在,您只需使用字典:
<强> VB.Net/C#强>
unToManagedDict.Add(UnmanagedType.AnsiBStr, GetType(String)) 'VB.Net
unToManagedDict.Add(UnmanagedType.AsAny, GetType(Object)) 'VB.Net
'and so on... or,
Dim type As Type = unToManagedDict(UnmanagedType.AnsiBStr) 'VB.Net
如果找不到非托管输入类型,那将抛出异常错误,类似于您在
中所做的操作Type type = unToManagedDict[UnmanagedType.AnsiBStr]; //C#
这样,您无需使用新函数来处理映射。此外,您不需要每次都添加新的Case Else
Throw New InvalidEnumArgumentException(argumentName:="type", invalidValue:=[type],
enumClass:=GetType(UnmanagedType))
。
现在,除了样式之外,你的“填空”的请求有点难度,因为并非所有Case
都在unmanaged
中具有直接等效性。 (使用对比词managed
vs unmanaged
本身就意味着什么!)
然而,鉴于空案例,我可能会这样做:
managed
您的可选问题询问反向是否安全。要做到相反并完全等效,必须有一对一关系。
也就是说,借用数学,f(x)只有f'(x),如果x和f(x)之间的关系是bijection。由于从Case UnmanagedType.ByValArray -> Array (no best equivalent, but Array is the closest)
Case UnmanagedType.ByValTStr -> String (no best equivalent, but String could be used)
Case UnmanagedType.R4 -> Single
Case UnmanagedType.R8 -> Double
Case UnmanagedType.SafeArray -> Array (no best equivalent, but Array is the closest)
Case UnmanagedType.Struct -> some Structure (no equivalent, each struct is unique, best is to use Structure to wrap Struct)
到UnmanagedType
的当前映射是非双向投影,Managed
的成员超过UnmanagedType
- &gt;结论:反向并不安全。