我正在尝试为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*/);
Run Code Online (Sandbox Code Playgroud)
我尝试使用以下代码创建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);
Run Code Online (Sandbox Code Playgroud)
然后我尝试使用以下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());
}
Run Code Online (Sandbox Code Playgroud)
这会导致抛出ApplicationException,错误代码为801,根据文档的含义,"数据包含所选Track 2格式的太多字符".但是,所选的曲目格式最多允许39个字符(我也尝试过较短的字符串).
我怀疑问题是由于我在MSTrackData定义中做错了,但我看不出这可能是什么.有没有人有什么建议?
到目前为止给出的所有答案都有一些答案但不完整.你需要MarshalAs - ByValArray以及新的,你的MSTrackDatas已经是引用所以你不需要通过ref传递它们你必须检查ICEAPI代表什么样的调用约定,如果它是StdCall你不需要改变任何东西但是如果是cdecl,则需要将CallingConvention添加到DllImport属性中.此外,您可能需要将MarshalAs属性添加到bool返回值,以确保它被封送为4字节WinApi样式bool.以下是您(可能)需要的声明:
public const int MAX_ICE_MS_TRACK_LENGTH = 256;
[StructLayout(LayoutKind.Sequential)]
public class MSTrackData {
public UInt32 nLength;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 256)]
public Byte[] TrackData = new byte[MAX_ICE_MS_TRACK_LENGTH];
}
[DllImport("ICE_API.dll", CharSet = CharSet.Auto, SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool EncodeMagstripe(IntPtr hDC,
[In] MSTrackData pTrack1,
[In] MSTrackData pTrack2,
[In] MSTrackData pTrack3,
[In] MSTrackData reserved);
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
6509 次 |
| 最近记录: |