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

时间:2015-05-21 19:04:41

标签: c# c++ c#-4.0 vb6

我有一个像这样的dll之一的c ++调用,

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 

我不确定将struct转换为object是否会抛出此异常。 任何类型的指针将不胜感激

  

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

1 个答案:

答案 0 :(得分:1)

在VB6中,Integer实际上是2个字节,因此它的.NET等效类型是short。同样地,Longint。您还需要指定数组的大小,因为它们是固定大小的。你在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。拳击可能也会给你一些问题,你应该知道在托管代码和非托管代码之间传递值的含义。