Структура сортировки PInvoke и БАЙТ * в качестве параметра приводят к неправильному указателю

#pinvoke

#pinvoke

Вопрос:

Я потратил 1 день, чтобы выяснить, почему возникла эта проблема, но результат по-прежнему не удался. Когда я выполняю отладку в собственной DLL, он показывает неверный указатель для второго параметра. Нужен эксперт здесь, чтобы посоветовать, чего не хватает на моем шаге, который приводит к этой ошибке.

  • Собственная структура
  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, БАЙТ* pbTranxData );

  • Функция в C#

    [DllImport(«KTMBBizRule.dll «)] public static extern int KTMBBiz_CSTSale([Вход, выход, маршалы(неуправляемый тип.LPArray, SizeParamIndex = >127)] байт[] 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);
    }
  
  • Ошибка, основанная на родном C

введите описание изображения здесь

Комментарии:

1. В вашем объявлении функции на C # два аргумента поменялись местами.

Ответ №1:

SizeParamIndex атрибут означает, что n-й параметр функции (основанный на нуле, считая слева) содержит фактический размер массива. ваша функция имеет только 2 параметра, а не 127.

более того, вы поменяли pbTranxData CSTSaleInfo местами параметры и в C и C #.

вы можете использовать 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);

вы также должны добавить [StructLayout(LayoutKind.Sequential)] перед своей структурой C #.

вместо public char[] szPaymentMediaID; этого вы можете сказать string szPaymentMediaID . По умолчанию строки сортируются как char*, вы можете изменить его на UnmanagedType.ByValTStr with given SizeConst .