PInvoke Marshalling Struct and BYTE* as parameter result the Bad Pointer
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++
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
.
精彩评论