【发布时间】:2019-10-16 14:00:26
【问题描述】:
我正在使用 RFideas 的 DLL,文档表明 DLL 函数的用法是:
short GetActiveID32(BYTE *pBuf, short wBufMaxSz)
他们没有 Delphi 示例,但有 VB.NET、C# 等。以下是 C# 的摘录:
public static void getActiveID()
{
pcproxlib.SetDevTypeSrch(PRXDEVTYP_USB);
int rc = pcproxlib.usbConnect();
Thread.Sleep(2500);
if (rc == 1)
{
IntPtr result1 = Marshal.AllocHGlobal(32 * sizeof(int));
byte[] arr = new byte[32];
int nBits = pcproxlib.GetActiveID32(result1, 32);
if(nBits == 0)
{
Console.WriteLine("\nNo Id Found, Please put card on the reader and make sure it must be configured with the card placed on it");
return;
}
int Bytes = (nBits + 7) / 8;
if (Bytes < 8)
{
Bytes = 8;
}
Marshal.Copy(result1, arr, 0, 32);
String cardData = "";
for (int i = 0; i < Bytes; i++)
{
String data = String.Format("{0:X2} ", arr[i]);
cardData = data + cardData;
}
Console.WriteLine("\n" + nBits+"Bits" + ": " + cardData);
}
else
{
Console.WriteLine("\n Reader Not Connected");
}
}
我在 Delphi 中定义了以下函数。
function GetActiveID32( CardID : pInt; Max_Buffer_Size : integer ) : word; stdcall external 'pcProxAPI32.dll';
我这样调用函数:
// Connect to USB Reader
SetConnectProduct( PRODUCT_PCPROX );
SetDevTypeSrch( PRXDEVTYP_USB );
USBDisconnect;
try
DeviceID := 0;
Results := GetDevCnt;
Results := USBConnect( );
if Results <> 0 then
begin
// Get Active USB reader ID
//CardID := 0;
repeat
Sleep( 250 );
Results := GetActiveID32( @CardID , 32 );
BytesToProcess := ( Results + 7) / 8;
if ( BytesToProcess < 8 ) then
BytesToProcess := 8;
// StrLCopy( BytesArray, PInt( CardID ), 32 );
// Marshal.Copy(result1, arr, 0, 32);
CardData := '';
for I := 0 to Trunc( BytesToProcess ) do
begin
CardData := CardData + BytesArray[ i ];
end;
until Results > 0;
// Disconnect from USB Reader until next needed
USBDisconnect;
end;
except
on E : Exception do
begin
results := GetLastLibErr;
ShowMessage( 'Error reading card ' + Results.ToString);
end;
end;
lblCardValue.Caption := String( @CardID );
标题总是垃圾。我究竟做错了什么?我认为这与我滥用指针有关。
【问题讨论】:
-
甚至 C# 也是错误的。 C 中的
short是 16 位(至少在 Windows 上),但 C#int是 32 位。 C# 代码分配了一个 32 个整数的数组,即 128 个字节,但对函数说它是一个长度为 32 的字节数组。我确信 C# 代码中还有许多其他错误。 Delphi 代码,嗯,谁知道呢。你没有提供足够的信息。例如,我们不知道 CardID 是什么。您犯了使用浮点运算而不是整数运算的错误。您要求该函数填充 CardID,然后您忽略其内容。 -
如果有更多关于实际结果应该是什么的信息会很高兴(您是否尝试过 C# 代码?)。但是关于 dll 例程本身,我认为您需要将“max_buffer_size”指定为短整数而不是整数。其次,也许该例程使用另一个调用约定,如 cdecl 而不是 stdcall...
-
@R.Hoek 你不觉得代码忽略了native函数返回的数据是个问题吗?
-
@DavidHeffernan 好吧,这肯定也是一个大问题,因为它在示例中已被注释掉。如果 Larry 能够编辑代码以使其代表应该工作的确切代码,那就太好了。因为我还缺少他作为缓冲区提供的 CardID 的内存分配(也称为 Delphi 类型)。
-
@R.Hoek 感谢大家的帮助。这是预期的:ID:33 位 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 3E A1 0B 18,此数据来自他们的实用程序用于测试读卡器/凭证,因此我们知道正确的数据。我没有尝试 C# 代码,我认为它是正确的,并试图将其转换为 Delphi。我会将 max_buffer_size 更改为 short 并进行测试。我会尝试 cdecl。