考古 《【Qt项目实战 】:使用脚本拓展CPP应用程序(1)——Lua脚本及编辑器》
一、LuaBridge
最近在项目的某个模块再次使用Lua作为程序拓展语言,开发了一些新的功能。
这里借助 LuaBridge 轻松实现Qt调用C++类成员函数及成员对象等功能;在(1)中,我们更多展示的是使用CFunction的方式,提供接口给Lua脚本调用。
LuaBridge https://github.com/DeHby/LuaBridge
使用及其简单,推荐指数5颗星
二、如何在Qt控件中展示Lua打印消息
我们都很清楚,print
函数可以在lua脚本中轻松实现打印。但是要将打印结果重定向到Qt控件中,新手朋友可能会稍微有点烦恼。
这里提供两种方法,一种简单,另一种进阶:
2.1、定义自己的print
函数,并使用qDebug()实现打印输出。
Qt支持qDebug()
的输出重定向。
在 Qt 中,qDebug()
是用于输出调试信息的函数。默认情况下,它将信息输出到标准输出(通常是控制台)。如果你想重定向 qDebug()
的输出,可以使用 QDebug
类的 setOutput
方法,或者通过重定向 qInstallMessageHandler
函数来实现。
方法 1: 使用 qInstallMessageHandler
你可以通过安装自定义的消息处理程序来重定向 qDebug()
的输出。以下是一个示例,展示如何将 qDebug()
的输出重定向到文件:
#include <QCoreApplication>
#include <QDebug>
#include <QFile>
#include <QTextStream>
void customMessageHandler(QtMsgType type, const QMessageLogContext &context, const QString &msg) {
QFile outFile("debug_output.txt");
if (outFile.open(QIODevice::Append | QIODevice::Text)) {
QTextStream ts(&outFile);
switch (type) {
case QtDebugMsg:
ts << "Debug: " << msg << "\n";
break;
case QtWarningMsg:
ts << "Warning: " << msg << "\n";
break;
case QtCriticalMsg:
ts << "Critical: " << msg << "\n";
break;
case QtFatalMsg:
ts << "Fatal: " << msg << "\n";
abort(); // 终止程序
}
outFile.close();
}
}
int main(int argc, char *argv[]) {
QCoreApplication a(argc, argv);
// 安装自定义消息处理程序
qInstallMessageHandler(customMessageHandler);
// 测试 qDebug 输出
qDebug() << "This is a debug message.";
qWarning() << "This is a warning message.";
qCritical() << "This is a critical message.";
return a.exec();
}
说明
- 自定义消息处理程序:
customMessageHandler
函数根据消息类型将输出写入文件debug_output.txt
。 qInstallMessageHandler
: 在main
函数中调用此函数来安装自定义的消息处理程序。- 消息类型: 根据消息类型(调试、警告、严重、致命)输出不同的前缀。
方法 2: 使用 QDebug
的 setOutput
方法
如果你想将 qDebug()
的输出重定向到其他输出流(如 QFile
),可以使用 QDebug
的构造函数来实现:
#include <QCoreApplication>
#include <QDebug>
#include <QFile>
#include <QTextStream>
int main(int argc, char *argv[]) {
QCoreApplication a(argc, argv);
QFile outFile("debug_output.txt");
if (outFile.open(QIODevice::WriteOnly | QIODevice::Text)) {
QTextStream ts(&outFile);
QDebug debug(&ts); // 将 QDebug 输出重定向到 QTextStream
debug << "This is a debug message.";
debug << "Another debug message.";
outFile.close();
}
return a.exec();
}
说明
QFile
和QTextStream
: 创建一个文件并打开以写入。QDebug
构造函数: 使用QDebug debug(&ts);
将输出重定向到QTextStream
,从而写入文件。
展开你的想象,既然可以定向到文件,自然可以定向到控件。通过信号和槽可以轻松的实现~ 这里比较简单,只提供思路。
2.2 直接在print函数中发送信号(啥!Lua调用的C++函数也可以发送信号~)
答案,是肯定的。搞那么复杂,我们只是想在Lua调用print方法时,可以将输出信息展示在窗口控件上,直接通过信号和槽函数绑定自然是最简单的。
这里给个示例:
int MyClass::luaPrint(lua_State *L) {
// 获取全局变量 qtBridgeLuaInstance
lua_getglobal(L, "qtBridgeLuaInstance");
QtBridgeLua *instance = static_cast<MyClass*>(lua_touserdata(L, -1));
lua_pop(L, 1); // 弹出 qtBridgeLuaInstance
if (!instance) {
qDebug() << "QtBridgeLua instance is null!";
return 0; // 返回 0,避免崩溃
}
int n = lua_gettop(L); // 获取参数个数
QString output;
for (int i = 1; i <= n; ++i) {
if (lua_isstring(L, i)) { // 检查参数是否为字符串
if (i > 1) output += " "; // 添加空格分隔
output += QString::fromUtf8(lua_tostring(L, i)); // 获取字符串参数
} else {
qDebug() << "Argument" << i << "is not a string!";
}
}
qDebug() << "luaprin==>" << instance;
emit instance->lua_print_info(output); // 发射信号
return 0; // 返回值
}
signals:
void lua_print_info(QString s);
多么轻松且自由~
OKK,下班下班。且到这里~