#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
.