PInvoke编组结构和BYTE *作为参数导致错误指针

时间:2011-10-12 07:03:42

标签: pinvoke

我花了一天的时间来找出这个问题发生的原因,但结果仍然失败了。 当我在Native DLL中调试时,它会显示第二个参数的Bad Pointer。需要专家在这里建议我的步骤中缺少产生此错误的内容。

  • 原生结构
 typedef struct
        {
            BYTE  bcdTicketMainType;
            BYTE  bcdTicketSubType;
            BYTE  bcdValidityStartDate[4];      // YYYYMMDD
            BYTE  bcdValidityEndDate[4];        // YYYYMMDD
            BYTE  bcdPhysicalExpiryDate[4];     // YYYYMMDD
            BYTE  bFareZone;
            SHORT sDepositAmount;               // NEW ARGUMENT
            LONG  lBalance;                     // NEW ARGUMENT
            BYTE  bcdStationIDOrigin[2];
            BYTE  bcdStationIDDestination[2];
            BYTE  bcdPaymentType;
            CHAR  strPaymentMediaID[20];
            CHAR  strAgentID[8];
            BYTE  bcdShiftID;
        } T_TK_KTMB_CSC_SALE_INFO;
  • C#中的结构
    public struct T_TK_KTMB_CSC_SALE_INFO
    {
        public byte bcdTicketMainType; //   1
        public byte bcdTicketSubType;   //   1
        [MarshalAsAttribute(UnmanagedType.ByValArray, SizeConst = 4)]
        public byte[] bcdValidityStartDate;       // YYYYMMDD
        [MarshalAsAttribute(UnmanagedType.ByValArray, SizeConst = 4)]
        public byte[] bcdValidityEndDate;     // YYYYMMDD
        [MarshalAsAttribute(UnmanagedType.ByValArray, SizeConst = 4)]
        public byte[] bcdPhysicalExpiryDate;      // YYYYMMDD
        public byte bFareZone;
        public short sDepositAmount;              // NEW ARGUMENT
        public long lBalance;                     // NEW ARGUMENT
        [MarshalAsAttribute(UnmanagedType.ByValArray, SizeConst = 2)]
        public byte[] bcdStationIDOrigin;
        [MarshalAsAttribute(UnmanagedType.ByValArray, SizeConst = 2)]
        public byte[] bcdStationIDDestination;
        public byte bcdPaymentType;
        [MarshalAsAttribute(UnmanagedType.ByValArray, SizeConst = 20)]
        public char[] szPaymentMediaID;
        [MarshalAsAttribute(UnmanagedType.ByValArray, SizeConst = 8)]
        public char[] szAgentID;
        public byte bcdShiftID;
    }
  • 原生功能
  

int KTMBBiz_CSCSale(T_TK_KTMB_CSC_SALE_INFO CSCSaleInfo,BYTE *   pbTranxData);

  • C#中的功能

      

    [的DllImport( “KTMBBizRule.dll”)]   public static extern int KTMBBiz_CSTSale([In,Out,MarshalAs(UnmanagedType.LPArray,SizeParamIndex => 127)] byte [] pbTranxData,T_TK_KTMB_CST_SALE_INFO CSTSaleInfo);

  • 在C#中调用的函数

  private void btnCscSale_Click(object sender, EventArgs e)
    {
        T_TK_KTMB_CSC_SALE_INFO cscSale = new T_TK_KTMB_CSC_SALE_INFO();
        byte[] trxData = new byte[2];
        BizRule.KTMBBiz_CSCSale(cscSale, trxData);
    }
  • 在Native C ++中创建的错误

enter image description here

1 个答案:

答案 0 :(得分:0)

SizeParamIndex属性表示第n个函数参数(从零开始,从左边开始计算)包含数组的实际大小。 你的函数只有2个参数,而不是127个。

此外,您在C ++和C#中交换了pbTranxDataCSTSaleInfo参数。

你可以使用SizeParamIndex让C ++函数知道pbTranxData数组的大小:

C ++

int KTMBBiz_CSCSale(T_TK_KTMB_CSC_SALE_INFO CSCSaleInfo,
                    BYTE* pbTranxData, INT iLength);

C#

[DllImport("KTMBBizRule.dll")]
public static extern int KTMBBiz_CSTSale(
      T_TK_KTMB_CST_SALE_INFO CSTSaleInfo,
      [In, Out, MarshalAs(UnmanagedType.LPArray, SizeParamIndex=2)]
      byte[] pbTranxData,
      int iLength);

现在使用KTMBBiz_CSTSale(cscSale, trxData, trxData.Length);

进行调用

您还应该在C#结构之前添加[StructLayout(LayoutKind.Sequential)]

而不是public char[] szPaymentMediaID;,您可以说string szPaymentMediaID。 默认情况下,字符串被编组为char *,您可以使用给定的UnmanagedType.ByValTStr将其更改为SizeConst