在C#上导入的DLL中出现“无符号字符*”时出错

时间:2013-12-09 14:23:15

标签: c# pinvoke

我一直在尝试使用C#中的非接触式mifare读卡器提供的VB DLL,但是传递变量类型时出现问题。原始代码是:

READER_API int __stdcall  RDR_LoginToSector(UCHAR Sector, UCHAR KeyType, unsigned char * KEY);

UCHAR可以毫无问题地用作“uint”或“byte”,但是“unsigned char *”无法正常工作

我尝试将其称为各种类型:

[DllImport("SmartReader.dll", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)] public static extern int RDR_LoginToSector(byte Sector, byte KeyType, IntPtr KEY);
byte[] D = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
IntPtr F = new IntPtr();
F = Marshal.AllocHGlobal(Marshal.SizeOf(D));
Logged = RDR_LoginToSector((byte) 0x01, (byte)0x60, F);

[DllImport("SmartReader.dll", CallingConvention = CallingConvention.Cdecl] public static extern int RDR_LoginToSector(byte Sector, byte KeyType, StringBuilder KEY);
StringBuilder E = new StringBuilder(6);
E.Append((byte)0xff);
E.Append((byte)0xff);
E.Append((byte)0xff);
E.Append((byte)0xff);
E.Append((byte)0xff);
E.Append((byte)0xff);
Logged = RDR_LoginToSector((byte) 0x01, (byte)0x60, E);

[DllImport("SmartReader.dll", CharSet = CharSet.Unicode)] public static extern int RDR_LoginToSector(byte Sector, byte KeyType, byte[] KEY); 
byte[] D = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
Logged = RDR_LoginToSector((byte) 0x01, (byte)0x60, D);

[DllImport("SmartReader.dll", CharSet = CharSet.Unicode)] public static extern int RDR_LoginToSector(byte Sector, byte KeyType, char[] KEY); 
char[] C = { (char)0xff, (char)0xff, (char)0xff, (char)0xff, (char)0xff, (char)0xff };
Logged = RDR_LoginToSector((byte) 0x01, (byte)0x60, C);

我也试过“ref”声明但没有成功。

在所有方法中,返回值为3表示登录失败。我使用我正在工作的Android应用程序仔细检查了密钥,并且可以正确记录,也可以使用它附带的已编译源代码。

所有不需要“unsigned char *”的方法都能正常工作,例如验证卡类型,打开COM端口等的方法。

有什么想法吗?

谢谢大家。

2 个答案:

答案 0 :(得分:1)

声明这个的正确方法是:

[DllImport("SmartReader.dll", CallingConvention = CallingConvention.Stdcall)]
public static extern int RDR_LoginToSector(
    byte Sector, 
    byte KeyType, 
    [In] byte[] Key
);

此声明与您提供的本机声明匹配。您的尝试使用了错误的调用约定,最终参数应为byte[]。实际上,您甚至可以省略CallingConvention,因为Stdcall是默认值。但是,要明确这一点并不会有害。同样,[In]可以省略,但再次明确是明智的。

因此返回值指示的错误意味着您传递的参数不正确。我们很难调试你传递的参数,因为我们不知道这个函数的细节。

所以,我想说的是,如果你使用上面的p / invoke,你可以从可能的失败模式列表中删除interop。事实上,要完全确定你应该用C ++编写一个成功调用函数的测试程序。这样你就可以调试你使用的参数,而不必担心它会导致问题的互操作。

答案 1 :(得分:0)

当您的C函数声明为__stdcall时,您应该使用匹配的调用约定:CallingConvention.StdCall

Unicode Charset对您没有任何帮助。我想你想使用字节数组作为前两个参数的最后一个参数(aka,Key)和字节。 (除了调用约定和不必要的Charset之外,你的第三个例子看起来正确。)

您还可以验证字节数组中数据的字节顺序。我不确定它是如何在其他领域使用的。