开发者

PInvoke Marshalling Struct and BYTE* as parameter result the Bad Pointer

开发者 https://www.devze.com 2023-04-12 22:56 出处:网络
I had spent 1 day to find out why this problem happen, but the result is still failed. When I debug in the Native DLL, it show the Bad Pointer for the second parameter. Need the expert in here to advi

I had spent 1 day to find out why this problem happen, but the result is still failed. When I debug in the Native DLL, it show the Bad Pointer for the second parameter. Need the expert in here to advice what is missing in my step that produce this error.

  • Native Struct
 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;
  • Struct in C#
    public struct T_TK_KTMB_CSC_SALE_INFO
    {
        public byte b开发者_JAVA百科cdTicketMainType; //   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;
    }
  • Native Function

int KTMBBiz_CSCSale( T_TK_KTMB_CSC_SALE_INFO CSCSaleInfo, BYTE* pbTranxData );

  • Function in 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);

  • Function called in 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);
    }
  • Error founded in Native C++

PInvoke Marshalling Struct and BYTE* as parameter result the Bad Pointer


the SizeParamIndex attribute means that the n-th function parameter (zero-based, counting from the left) contains the actual size of the array. your function has only 2 parameters, not 127.

what is more, you swapped the pbTranxData and CSTSaleInfo parameters in C++ and C#.

you can use SizeParamIndex to let the C++ function know the size of pbTranxData array:

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);

now call it with KTMBBiz_CSTSale(cscSale, trxData, trxData.Length);

you should also add [StructLayout(LayoutKind.Sequential)] before your C# structure.

instead of public char[] szPaymentMediaID; you can say string szPaymentMediaID. By default strings are marshalled as char*, you can change it to UnmanagedType.ByValTStr with given SizeConst.

0

精彩评论

暂无评论...
验证码 换一张
取 消