这是用到的那个结构体:
TRealRecordInfo = packed record
Size: Integer; // 此结构大小(包含Size), 调用前需要设置, 以防止访问越界
CardNo: array[0..17] of char; // 存储卡号最长16位
timeString: array[0..15]of char; // 刷卡时间14个字符
IsIDCard: Boolean; // 如果时ID卡为true,否则为false是IC卡
NoCard: Boolean; // 如果为true,则没有卡片在感应区,此结构其他数据无效
Reader: Integer; // 范围从1-4指几号读头
Flag: Integer; // 打卡结果
Mark: Integer; // 打卡标志
times: Integer; // 充值次数
balance: Integer; // 消费后余额,单位角
consume: Integer; // 消费额,单位角
sign_time: TDateTime; // Double格式时间 OverPwd: array[0..9] of char; // 超额消费密码
reserved1: DWORD; // 保留
reserved2: DWORD; // 保留 Clock_ver : Integer; //消费记录版本号
Clock_ID : Integer; //机号
POS_Sequ : Integer; //POS交易流水号
Card_Sequ : Integer; //卡交易流水号
Op_CardNo : array[0..19] of Char; //机操作员卡号
Date_ver : array[0..19] of Char; //时间版本号
reserved3 : array[0..19] of Char; // 保留
reserved4 : array[0..19] of Char; // 保留
end;
这是要导出的函数调用
//实时读记录
function RealReadRecord(hPort: THandle; clock_id: Integer; ARecord: PRealRecordInfo): Boolean; stdcall; external EASTRIVERD_API
//参数说明:
// hPort : 端口句柄, 不需要联机
// clock_id : 机号, 允许值:0-255
// Card : TRealRecordInfo 指针,存储返回结果
//返回值:
// True : 成功
// False : 失败
// 说明: 如果机器是690D:
// consume=0 //待机状态刷卡,需要马上回传此卡的余额
// consume<>0 //终端机输入的扣除金额, 如果是充值机(机号=0), 则为充值金额
// //需将此卡原余额扣除后回传
我尝试在C#中按照以下方式使用:
/// <summary>
/// ER-690C/D 实时通讯 返回数据 结构体
///
/// </summary>
[StructLayoutAttribute(LayoutKind.Sequential,CharSet = CharSet.Ansi,Pack=1)]
public struct TRealRecordInfo
{
#region 基本成员 /// <summary>
/// 此结构大小(包含Size), 调用前需要设置, 以防止访问越界
/// </summary>
public int Size;
/// <summary>
/// 存储卡号最长16位
/// </summary>
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 18)]
public string CardNo;
/// <summary>
/// 刷卡时间14个字符
/// </summary>
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 16)]
public string TimeString;
/// <summary>
/// 如果时ID卡为true,否则为false是IC卡
/// </summary>
[MarshalAs(UnmanagedType.Bool)]
public bool IsIDCard;
/// <summary>
/// 如果为true,则没有卡片在感应区,此结构其他数据无效
/// </summary>
[MarshalAs(UnmanagedType.Bool)]
public bool NoCard;
/// <summary>
/// 范围从1-4指几号读头
/// </summary>
public int Reader;
/// <summary>
/// 打卡结果
/// </summary>
public int Flag;
/// <summary>
/// 打卡标志
/// </summary>
public int Mark;
/// <summary>
/// 充值次数
/// </summary>
public int Times;
/// <summary>
/// 消费后余额,单位角
/// </summary>
public int Balance;
/// <summary>
/// 消费额,单位角
/// </summary>
public int Consume;
/// <summary>
/// 打卡Double格式时间
/// </summary>
[MarshalAs(UnmanagedType.R8)]
public double Sign_Time; #endregion #region ER-690D 新扩充成员 /// <summary>
/// 超额消费密码
/// </summary>
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 10)]
public string OverPassword;
/// <summary>
/// 保留
/// </summary>
public int DwReserved1;
/// <summary>
/// 保留
/// </summary>
public int DwReserved2; #endregion #region ER-6902.0 扩展成员
/// <summary>
/// 消费记录版本号
/// </summary>
public int Clock_ver;
/// <summary>
/// 机号
/// </summary>
public int Clock_ID;
/// <summary>
/// POS交易流水号
/// </summary>
public int POS_Sequ;
/// <summary>
/// 卡交易流水号
/// </summary>
public int Card_Sequ;
/// <summary>
/// 机操作员卡号
/// </summary>
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 20)]
public string Op_CardNo;
/// <summary>
/// 时间版本号
/// </summary>
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 20)]
public string Date_ver;
/// <summary>
/// 保留
/// </summary>
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 20)]
public string szReserved3;
/// <summary>
/// 保留
/// </summary>
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 20)]
public string szReserved4; #endregion
}
/// <summary>
///参数说明:
/// hPort : 端口句柄, 不需要联机
/// clock_id : 机号, 允许值:0-255
/// Card : TRealRecordInfo 指针,存储返回结果
///返回值:
/// True : 成功
/// False : 失败
/// 说明: 如果机器是690D:
/// consume=0 //待机状态刷卡,需要马上回传此卡的余额
/// consume<>0 //终端机输入的扣除金额, 如果是充值机(机号=0), 则为充值金额
/// //需将此卡原余额扣除后回传
/// </summary>
/// <param name="hPort">端口句柄, 不需要联机</param>
/// <param name="clock_id">机号, 允许值:0-255</param>
/// <param name="aRecord">TRealRecordInfo 指针,存储返回结果</param>
/// <returns></returns>
[DllImport("EastRiverD.dll", EntryPoint = "RealReadRecord",CharSet = CharSet.Ansi, CallingConvention = CallingConvention.StdCall)]
public extern static bool RealReadRecord(IntPtr hPort, int clock_id, ref TRealRecordInfo aRecord);
其他相关的调用的地方均省略。现在的状况是:
1. 我在Delphi中调用RealReadRecord后得到得到的结构体实例(正确值)与C#调用得到的不一致。
2. TRealRecordInfo在Delphi中用Sizeof得到的大小是186(是此结构体pack布局后正常的大小),而在C#中使用Marshal.SizeOf(...)[注:我是直接new的那个结构,不知道这是不是正确的]后得到大小为192。所以,我认为问题的原因还是在C#结构体定义和实例化这块。
请高手帮忙指点迷津。灰常感谢不尽先。:)
TRealRecordInfo = packed record
Size: Integer; // 此结构大小(包含Size), 调用前需要设置, 以防止访问越界
CardNo: array[0..17] of char; // 存储卡号最长16位
timeString: array[0..15]of char; // 刷卡时间14个字符
IsIDCard: Boolean; // 如果时ID卡为true,否则为false是IC卡
NoCard: Boolean; // 如果为true,则没有卡片在感应区,此结构其他数据无效
Reader: Integer; // 范围从1-4指几号读头
Flag: Integer; // 打卡结果
Mark: Integer; // 打卡标志
times: Integer; // 充值次数
balance: Integer; // 消费后余额,单位角
consume: Integer; // 消费额,单位角
sign_time: TDateTime; // Double格式时间 OverPwd: array[0..9] of char; // 超额消费密码
reserved1: DWORD; // 保留
reserved2: DWORD; // 保留 Clock_ver : Integer; //消费记录版本号
Clock_ID : Integer; //机号
POS_Sequ : Integer; //POS交易流水号
Card_Sequ : Integer; //卡交易流水号
Op_CardNo : array[0..19] of Char; //机操作员卡号
Date_ver : array[0..19] of Char; //时间版本号
reserved3 : array[0..19] of Char; // 保留
reserved4 : array[0..19] of Char; // 保留
end;
这是要导出的函数调用
//实时读记录
function RealReadRecord(hPort: THandle; clock_id: Integer; ARecord: PRealRecordInfo): Boolean; stdcall; external EASTRIVERD_API
//参数说明:
// hPort : 端口句柄, 不需要联机
// clock_id : 机号, 允许值:0-255
// Card : TRealRecordInfo 指针,存储返回结果
//返回值:
// True : 成功
// False : 失败
// 说明: 如果机器是690D:
// consume=0 //待机状态刷卡,需要马上回传此卡的余额
// consume<>0 //终端机输入的扣除金额, 如果是充值机(机号=0), 则为充值金额
// //需将此卡原余额扣除后回传
我尝试在C#中按照以下方式使用:
/// <summary>
/// ER-690C/D 实时通讯 返回数据 结构体
///
/// </summary>
[StructLayoutAttribute(LayoutKind.Sequential,CharSet = CharSet.Ansi,Pack=1)]
public struct TRealRecordInfo
{
#region 基本成员 /// <summary>
/// 此结构大小(包含Size), 调用前需要设置, 以防止访问越界
/// </summary>
public int Size;
/// <summary>
/// 存储卡号最长16位
/// </summary>
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 18)]
public string CardNo;
/// <summary>
/// 刷卡时间14个字符
/// </summary>
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 16)]
public string TimeString;
/// <summary>
/// 如果时ID卡为true,否则为false是IC卡
/// </summary>
[MarshalAs(UnmanagedType.Bool)]
public bool IsIDCard;
/// <summary>
/// 如果为true,则没有卡片在感应区,此结构其他数据无效
/// </summary>
[MarshalAs(UnmanagedType.Bool)]
public bool NoCard;
/// <summary>
/// 范围从1-4指几号读头
/// </summary>
public int Reader;
/// <summary>
/// 打卡结果
/// </summary>
public int Flag;
/// <summary>
/// 打卡标志
/// </summary>
public int Mark;
/// <summary>
/// 充值次数
/// </summary>
public int Times;
/// <summary>
/// 消费后余额,单位角
/// </summary>
public int Balance;
/// <summary>
/// 消费额,单位角
/// </summary>
public int Consume;
/// <summary>
/// 打卡Double格式时间
/// </summary>
[MarshalAs(UnmanagedType.R8)]
public double Sign_Time; #endregion #region ER-690D 新扩充成员 /// <summary>
/// 超额消费密码
/// </summary>
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 10)]
public string OverPassword;
/// <summary>
/// 保留
/// </summary>
public int DwReserved1;
/// <summary>
/// 保留
/// </summary>
public int DwReserved2; #endregion #region ER-6902.0 扩展成员
/// <summary>
/// 消费记录版本号
/// </summary>
public int Clock_ver;
/// <summary>
/// 机号
/// </summary>
public int Clock_ID;
/// <summary>
/// POS交易流水号
/// </summary>
public int POS_Sequ;
/// <summary>
/// 卡交易流水号
/// </summary>
public int Card_Sequ;
/// <summary>
/// 机操作员卡号
/// </summary>
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 20)]
public string Op_CardNo;
/// <summary>
/// 时间版本号
/// </summary>
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 20)]
public string Date_ver;
/// <summary>
/// 保留
/// </summary>
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 20)]
public string szReserved3;
/// <summary>
/// 保留
/// </summary>
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 20)]
public string szReserved4; #endregion
}
/// <summary>
///参数说明:
/// hPort : 端口句柄, 不需要联机
/// clock_id : 机号, 允许值:0-255
/// Card : TRealRecordInfo 指针,存储返回结果
///返回值:
/// True : 成功
/// False : 失败
/// 说明: 如果机器是690D:
/// consume=0 //待机状态刷卡,需要马上回传此卡的余额
/// consume<>0 //终端机输入的扣除金额, 如果是充值机(机号=0), 则为充值金额
/// //需将此卡原余额扣除后回传
/// </summary>
/// <param name="hPort">端口句柄, 不需要联机</param>
/// <param name="clock_id">机号, 允许值:0-255</param>
/// <param name="aRecord">TRealRecordInfo 指针,存储返回结果</param>
/// <returns></returns>
[DllImport("EastRiverD.dll", EntryPoint = "RealReadRecord",CharSet = CharSet.Ansi, CallingConvention = CallingConvention.StdCall)]
public extern static bool RealReadRecord(IntPtr hPort, int clock_id, ref TRealRecordInfo aRecord);
其他相关的调用的地方均省略。现在的状况是:
1. 我在Delphi中调用RealReadRecord后得到得到的结构体实例(正确值)与C#调用得到的不一致。
2. TRealRecordInfo在Delphi中用Sizeof得到的大小是186(是此结构体pack布局后正常的大小),而在C#中使用Marshal.SizeOf(...)[注:我是直接new的那个结构,不知道这是不是正确的]后得到大小为192。所以,我认为问题的原因还是在C#结构体定义和实例化这块。
请高手帮忙指点迷津。灰常感谢不尽先。:)
解决方案 »
免费领取超大流量手机卡,每月29元包185G流量+100分钟通话, 中国电信官方发货