在带Lua 5.1支持的otclient中,如何读取COM3串口原始数据?
读取COM3串口数据的两种可行方案(适配otclient)
Lua方案:解决luaserial DLL加载失败问题
你加载luaserial DLL失败大概率是这几个原因,对应解决即可:
- 位数不匹配:otclient如果是32位程序,必须用32位版本的luaserial DLL;64位则用64位版本,别搞混。
- 路径问题:把DLL放到otclient的主程序目录,或者在Lua代码里通过
package.cpath指定DLL路径,比如:package.cpath = package.cpath .. ";./serial/?.dll" -- 假设DLL在serial子目录 - 依赖缺失:luaserial可能依赖特定版本的VC运行库,确保系统已安装对应版本的Visual C Redistributable。
解决后,用luaserial读取COM3的示例代码:
local serial = require("serial") local port = serial.open("COM3", { baudrate = 9600, databits = 8, parity = "none", stopbits = 1 }) if port then while true do local data = port:read(1024) -- 每次读取最多1024字节 if data and #data > 0 then print("收到数据:", data) -- 此处可将数据传入otclient逻辑处理 end os.execute("sleep 0.1") -- 避免循环过度占用CPU end port:close() else print("无法打开COM3串口") end
C++方案:直接在otclient中实现串口读取
如果Lua方案折腾不出来,C++实现确实更稳定,无需依赖第三方DLL。Windows下用Win32 API就能快速搞定,示例代码如下:
1. 串口操作封装函数
#include <windows.h> #include <iostream> HANDLE openSerialPort(const char* portName) { HANDLE hSerial = CreateFileA(portName, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); if (hSerial == INVALID_HANDLE_VALUE) { return NULL; } // 配置串口参数(波特率9600,8位数据位,无校验,1位停止位) DCB dcbSerialParams = {0}; dcbSerialParams.DCBlength = sizeof(dcbSerialParams); if (!GetCommState(hSerial, &dcbSerialParams)) { CloseHandle(hSerial); return NULL; } dcbSerialParams.BaudRate = CBR_9600; dcbSerialParams.ByteSize = 8; dcbSerialParams.StopBits = ONESTOPBIT; dcbSerialParams.Parity = NOPARITY; if (!SetCommState(hSerial, &dcbSerialParams)) { CloseHandle(hSerial); return NULL; } // 设置超时参数 COMMTIMEOUTS timeouts = {0}; timeouts.ReadIntervalTimeout = 50; timeouts.ReadTotalTimeoutConstant = 50; timeouts.ReadTotalTimeoutMultiplier = 10; SetCommTimeouts(hSerial, &timeouts); return hSerial; } bool readSerialData(HANDLE hSerial, char* buffer, DWORD bufferSize, DWORD* bytesRead) { return ReadFile(hSerial, buffer, bufferSize, bytesRead, NULL); }
2. 集成到otclient
你可以在otclient初始化时启动单独线程读取串口数据:
void serialReadThread() { HANDLE hSerial = openSerialPort("COM3"); if (!hSerial) { std::cerr << "无法打开COM3串口" << std::endl; return; } char buffer[1024]; DWORD bytesRead; while (true) { if (readSerialData(hSerial, buffer, sizeof(buffer), &bytesRead) && bytesRead > 0) { // 处理读取到的原始数据,比如转成字符串传给Lua层,或直接在C++逻辑处理 std::string rawData(buffer, bytesRead); std::cout << "收到串口数据:" << rawData << std::endl; // 如果要传递给Lua层,可使用otclient的Lua绑定API,示例: // g_lua.push(rawData); // g_lua.callGlobal("onSerialDataReceived"); } Sleep(100); // 降低CPU占用率 } CloseHandle(hSerial); } // 在otclient初始化代码中启动线程 // std::thread serialThread(serialReadThread); // serialThread.detach();
两种方案里,C方案更适配otclient这类原生C程序,避免了Lua扩展的兼容性问题,稳定性更高。
内容的提问来源于stack exchange,提问作者DoDr
相关产品推荐
相关产品推荐

