You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

在带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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.11 22:57:54