Question

I have a P/Invoke with a C struct pointer passed into a function under Windows CE platform

C++ Code
typedef struct{
    unsigned char MerchName[256];    
    unsigned char MerchCateCode[2];  
    unsigned char MerchId[15];       
    unsigned char TermId[8];         
    unsigned char TerminalType;      
    unsigned char Capability[3];     
    unsigned char ExCapability[5];   
    unsigned char TransCurrExp;      
    unsigned char ReferCurrExp;      
    unsigned char ReferCurrCode[2];  
    unsigned char CountryCode[2];    
    unsigned char TransCurrCode[2];  
    unsigned long ReferCurrCon;      
    unsigned char TransType;         
    unsigned char ForceOnline;       
    unsigned char GetDataPIN;        
    unsigned char SurportPSESel;     
}EMV_PARAM;

SKY_EMV_API void SKY_EmvLib_SetParam(EMV_PARAM *tParam)

C# code:

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
public struct EMV_PARAM
{
    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)]
    public string MerchName;
    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 2)]
    public string MerchCateCode;
    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 15)]
    public string MerchId;
    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 8)]
    public string TermId;
    public byte TerminalType;
    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 3)]
    public string Capability;
    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 5)]
    public string ExCapability;
    public byte TransCurrExp;
    public byte ReferCurrExp;
    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 2)]
    public string ReferCurrCode;
    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 2)]
    public string CountryCode;
    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 2)]
    public string TransCurrCode;
    public int ReferCurrCon;
    public byte TransType;
    public byte ForceOnline;
    public byte GetDataPIN;
    public byte SurportPSESel;
}

 [DllImport("SKY_EMV.dll")]
 private static extern int SKY_EmvLib_SetParam(ref EMV_PARAM param);

The issues is the data doesn't packed up. I know in C# code, the string is treated as an Unicode string, and when it goes into C++ code, every character in C# string will occupy 2 bytes in C++ side.

for example I set MerchName as "abc" in C#, it will change into "a0b0c0" in C++ side. since the platform is Windows CE, there is no CharSet.ASCII in this platform.

Anybody could help how to solve this issue without changing C++ EMV_Param struct, Is anyway to change the C# code to make it work?

Was it helpful?

Solution

CharSet.Ansi does not exist on CE. Which means that you cannot use string in the C# struct definition. Instead, if you leave the C++ unchanged, you would have to use byte arrays. The next problem that you face is the need to convert from UTF-16 to ANSI/ASCII. If your text on the C# side us restricted to ASCII characters then that is easy enough to do. You just convert each character into its ordinal, and truncate into the range 0..127.

This seems rather painful. Frankly, the right solution is to modify the C++ to accept UTF-16 text. If the underlying library is ASCII, then you can make the conversion in the C++ code which does at least contain functions for that purpose.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top