将代码从vb6转换为c#-System.Variant.Marshal Helper将对象转换为变量'
本文关键字:转换 对象 变量 Helper Variant 代码 vb6 c#-System Marshal | 更新日期: 2023-09-27 17:50:28
我有一个c++调用像这样的一个dll,
public static extern bool RecognizeEvent(int Id ,long DataLength ,ref object EventData);
,我试着这样调用这个函数…
Status = oStatus(parameters);
object oiStatus = (object)Status;
bValue = RecognizeEvent(ID, DataLength, ref oiStatus);
,其中Status
为struct
。当我试图通过代码步进时,我得到以下错误
Step into: Stepping over method without symbols 'System.Variant.MarshalHelperConvertObjectToVariant'
A first chance exception of type 'System.ArgumentException' occurred
我不确定将结构体转换为对象是否会抛出此异常。任何形式的指针将不胜感激
c#结构:
public struct INBOUND_RADIO_STATUS {
public int wMsgId;
public int channel;
public int unit_id;
public int wStatus;
public int wRadioStatus;
public int wTimeMinutes;
public int wPrimarySetID;
public int wSecondarySetID;
public byte[] individualAlias;
public int wZoneId;
public int wSiteId;
public int dest_unit;
public byte[] destinationAlias;
}
vb 6 struct:
Public Type INBOUND_RADIO_STATUS
wMsgId As Integer
channel As Integer
unit_id As Long
wStatus As Integer
wRadioStatus As Integer
wTimeMinutes As Integer
wPrimarySetID As Integer
wSecondarySetID As Integer
individualAlias(0 To 49) As Byte
wZoneId As Integer
wSiteId As Integer
dest_unit As Long
destinationAlias(0 To 49) As Byte
End Type
在VB6中,Integer
实际上是2个字节,因此它的。net等效类型是short
。同样,Long
也是int
。您还需要指定数组的大小,因为它们是固定大小的。c#中的结构应该是这样的:
[StructLayout(LayoutKind.Sequential)]
public struct INBOUND_RADIO_STATUS
{
public short wMsgId;
public short channel;
public int unit_id;
public short wStatus;
public short wRadioStatus;
public short wTimeMinutes;
public short wPrimarySetID;
public short wSecondarySetID;
[MarshalAs(UnmanagedType.LPArray, SizeConst=50)]
public byte[] individualAlias;
public short wZoneId;
public short wSiteId;
public int dest_unit;
[MarshalAs(UnmanagedType.LPArray, SizeConst = 50)]
public byte[] destinationAlias;
}
注意顶部的顺序布局属性和特定大小的数组。这将保证结构体的布局/大小与VB6版本相同。
同样重要的是要注意,虽然byte
是值类型,但byte[]
是引用类型,并且可以是null
。由于您正在封送对象,因此您分配的数据大小与非托管代码期望的大小相同是非常重要的。
你可能还需要用一些额外的属性来修饰你的c#代码,比如:
public static extern bool RecognizeEvent(int Id ,long DataLength ,[Out] ref object EventData);
另一件让我注意到的事情是,你正在传递一个object
来代替结构类型。这意味着您将对INBOUND_RADIO_STATUS
进行装箱,实际上是将其转换为不同的类型。尝试在其位置使用实际类型而不是object
。装箱可能也会给您带来一些问题,当涉及到在托管代码和非托管代码之间传递值时,您应该了解其含义。