Flutter调用win32 SCardTransmit成功但RC-380读卡器无法读取NFC卡UID/IDM求助
问题原因与解决办法
核心错误点
- 接收缓冲区分配容量不足,且长度参数使用不符合
SCardTransmit接口规范:- 你当前仅为
pbRecvBuffer分配了1字节的内存空间,远不足以存储NFC卡UID(通常为4/7/10字节)+ 2字节APDU执行状态码的返回内容 pcbRecvLength参数需要单独分配内存,输入时需预先设置为接收缓冲区的总容量,接口执行完成后才会写入实际收到的字节数;你直接将接收缓冲区指针强转为Uint32*传入的写法完全错误,会导致读写内存越界,这也是两次读取返回随机值的原因
- 你当前仅为
- 发送的
0xFF 0xCA 0x00 0x00 0x00指令本身是符合PCSC标准的读UID指令,没有问题。
修正后的代码示例
// 省略前面协议判断的逻辑 int hCard = phCard.value; List<int> data = [0xff, 0xca, 0x00, 0x00, 0x00]; Uint8List bytes = Uint8List.fromList(data); Pointer<Uint8> pbSendBuffer = bytes.allocatePointer(); // 分配足够大的接收缓冲区,这里设为256字节覆盖所有常规场景 const recvBufferSize = 256; Pointer<Uint8> pbRecvBuffer = calloc<Uint8>(recvBufferSize); // 单独分配长度参数指针,初始值设置为接收缓冲区容量 Pointer<Uint32> pcbRecvLength = calloc<Uint32>(); pcbRecvLength.value = recvBufferSize; Pointer<SCARD_IO_REQUEST> pioSendPci = calloc<SCARD_IO_REQUEST>() ..ref.cbPciLength = sizeOf<SCARD_IO_REQUEST>() ..ref.dwProtocol = SCARD_PROTOCOL; ret = SCardTransmit(hCard, pioSendPci, pbSendBuffer, bytes.length, nullptr, pbRecvBuffer, pcbRecvLength); if (ret == SCARD_S_SUCCESS) { Uint8List recvData = pbRecvBuffer.asTypedList(pcbRecvLength.value); if (recvData.length >= 2) { // 最后2字节是APDU状态码,0x9000代表执行成功 int sw1 = recvData[recvData.length - 2]; int sw2 = recvData[recvData.length - 1]; if (sw1 == 0x90 && sw2 == 0x00) { // 前面的内容就是UID Uint8List uid = recvData.sublist(0, recvData.length - 2); print("读取到的UID: ${uid.map((e) => e.toRadixString(16).padLeft(2, '0')).join(' ')}"); } else { print("指令执行失败,状态码: ${sw1.toRadixString(16)} ${sw2.toRadixString(16)}"); } } } // 用完释放所有申请的堆内存,避免内存泄漏 calloc.free(pbSendBuffer); calloc.free(pbRecvBuffer); calloc.free(pcbRecvLength); calloc.free(pioSendPci);
额外注意事项
- 若读取Felica卡的IDM,需要替换为对应Felica的读卡指令,上述指令仅适配ISO14443A协议的NFC卡
- 调用接口前需确认
hCard、SCARD_PROTOCOL参数已经通过SCardConnect接口正确获取,没有被提前释放
内容的提问来源于stack exchange,提问作者Mevius21
相关产品推荐
相关产品推荐

