我正在尝试为 C API(本机 Win dll)编写 C# P/Invoke 包装器,通常这工作正常。唯一的例外是在 C 代码中将结构作为参数的特定方法。该函数在没有任何异常的情况下被调用,但它返回 false 表示执行失败。
在 API 头文件中,涉及的方法和结构定义如下:
#define MAX_ICE_MS_TRACK_LENGTH 256
typedef struct tagTRACKDATA
{
UINT nLength;
BYTE TrackData[MAX_ICE_MS_TRACK_LENGTH];
} TRACKDATA, FAR* LPTRACKDATA;
typedef const LPTRACKDATA LPCTRACKDATA;
BOOL ICEAPI EncodeMagstripe(HDC /*hDC*/,
LPCTRACKDATA /*pTrack1*/,
LPCTRACKDATA /*pTrack2*/,
LPCTRACKDATA /*pTrack3*/,
LPCTRACKDATA /*reserved*/);
我尝试使用以下代码创建 C# P/Invoke 包装器:
public const int MAX_ICE_MS_TRACK_LENGTH = 256;
[StructLayout(LayoutKind.Sequential)]
public class MSTrackData {
public UInt32 nLength;
public readonly Byte[] TrackData = new byte[MAX_ICE_MS_TRACK_LENGTH];
}
[DllImport("ICE_API.dll", CharSet = CharSet.Auto, SetLastError = true)]
public static extern bool EncodeMagstripe(IntPtr hDC,
[In]ref MSTrackData pTrack1,
[In]ref MSTrackData pTrack2,
[In]ref MSTrackData pTrack3,
[In]ref MSTrackData reserved);
然后我尝试使用以下 C# 代码调用 EncodeMagstripe 方法:
CardApi.MSTrackData trackNull = null;
CardApi.MSTrackData track2 = new CardApi.TrackData();
byte[] trackBytes = Encoding.ASCII.GetBytes(";0123456789?");
track2.nLength = (uint)trackBytes.Length;
Buffer.BlockCopy(trackBytes, 0, track2.TrackData, 0, trackBytes.Length);
if (!CardApi.EncodeMagstripe(hDC, ref trackNull, ref track2, ref trackNull, ref trackNull)) {
throw new ApplicationException("EncodeMagstripe failed", Marshal.GetLastWin32Error());
}
这会导致抛出 ApplicationException,错误代码为 801,根据文档,这意味着“数据包含太多字符,无法用于所选的 Track 2 格式。”。但是,所选曲目格式最多应允许 39 个字符(我也尝试过较短的字符串)。
我怀疑问题的发生是由于我在 MSTrackData 定义中做错了什么,但我看不出这可能是什么。有没有人有什么建议?