将代码从 vb6 转换为 c#-System.Variant.Marshal Helper 将对象转换为变体'

Converting code from vb6 to c#-System.Variant.Marshal Helper Convert Object To Variant'

本文关键字:转换 对象 Variant 代码 vb6 c#-System Marshal Helper      更新时间:2023-10-16

我有一个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);

,其中Statusstruct。当我试图通过代码步进时,我得到以下错误

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。装箱可能也会给您带来一些问题,当涉及到在托管代码和非托管代码之间传递值时,您应该了解其含义。