话接上文。笔者为了方便使用Lua,自己编写了一个Lua的类。主要代码如下:

QLua.h

 #ifndef QLUA_H
#define QLUA_H // own
#include "include/lua.hpp" // qt
#include <QObject>
#include <QFile>
#include <QDebug> #include <QWidget>
#include <QLineEdit>
#include <QPushButton>
#include <QMessageBox> class QLua : public QObject
{
Q_OBJECT
public:
QLua(QObject *parent = );
~QLua(); // lua
void init();
void close(); void pushFunction(QString funcName, lua_CFunction func); void beginModule(QString);
void addType(QString, lua_CFunction deleteFunc);
void moduleTypeFunction(QString, lua_CFunction);
void endModule(); void run(QString);
signals: public slots: private:
lua_State *luaState; bool isStartModule;
}; #endif // QLUA_H

QLua.cpp

 #include "qlua.h"

 QLua::QLua(QObject *parent) :
QObject(parent)
, luaState(NULL)
, isStartModule(false)
{
init();
} QLua::~QLua()
{
close();
} void QLua::init()
{
luaState = luaL_newstate();
luaL_openlibs(luaState);
} void QLua::close()
{
if(luaState != NULL)
{
lua_close(luaState);
luaState = NULL;
}
} void QLua::pushFunction(QString funcName, lua_CFunction func)
{
if (funcName.isEmpty()) return;
if (func == NULL) return; lua_pushcfunction(luaState, func);
lua_setglobal(luaState, funcName.toLocal8Bit().data());
} void QLua::beginModule(QString name)
{
if(luaState == NULL) return; if (isStartModule == false)
{
tolua_open(luaState);
tolua_module(luaState, NULL, );
isStartModule = true;
} const char *str = name.isEmpty()? NULL : name.toLocal8Bit().data();
tolua_beginmodule(luaState, str);
} void QLua::addType(QString name, lua_CFunction deleteFunc)
{
if (luaState == NULL) return;
if (name.isEmpty()) return;
if (deleteFunc == NULL) return; tolua_usertype(luaState, name.toLocal8Bit().data());
const char *str = name.toLocal8Bit().data();
tolua_cclass(luaState, str, str, "", deleteFunc);
beginModule(name);
} void QLua::moduleTypeFunction(QString name, lua_CFunction func)
{
if(luaState == NULL) return ;
if (name.isEmpty()) return; const char *str = name.toLocal8Bit().data();
tolua_function(luaState, str, func);
} void QLua::endModule()
{
tolua_endmodule(luaState);
} void QLua::run(QString str)
{
luaL_loadbuffer(luaState, str.toLocal8Bit().data(), str.length(), "line");
lua_pcall(luaState, , , );
}

QLua类可以方便的实现一些简单的Lua操作,如初始化,关闭,运行Lua代码,绑定函数等。

笔者目前想做到的是能在Lua代码中自有的生成Qt对象,然后能连接Qt原生对象的信号与槽。那么如何实现呢?

Qt中连接信号与槽的函数是QObject::connect(QObject * a, SIGNAL(), QObject * b, SLOT())。首先,我们要弄清楚SIGNAL和SLOT到底是什么。

从connect的参数列表中,我们可以很清晰的看到SIGNAL和SLOT的结果都是char*类型的字符串。我们可以直接在SIGNAL上点右键,转到SIGNAL的定义。或者做个简单的实验。测试如下Qt代码:

    qDebug() << QString::fromLocal8Bit(SIGNAL(clicked()));
qDebug() << QString::fromLocal8Bit(SLOT(close()));

得到的结果很有意思:

"2clicked()"
"1close()"

简单总结就是我们只要传入函数名的字符串,加上前缀即可。SIGNAL的前缀是2,SLOT的前缀是1。

这样我们就可以实现在Lua中的connect函数了。仍在使用C++编写,然后绑定到Lua里。如下:

 static int connect(lua_State* state)
{
QObject * a = (QObject*)tolua_tousertype(state, , );
const char * signal = tolua_tostring(state, , );
QObject * b = (QObject*)tolua_tousertype(state, , );
const char * slot = tolua_tostring(state, , ); QObject::connect(a, QString("2%0").arg(signal).toLocal8Bit().data(),
b, QString("1%0").arg(slot).toLocal8Bit().data());
}

绑定时可以使用上面的QLua类:

lua.pushFunction("connect", connect);

完整main.cpp代码如下:

#include "include/lua.hpp"
#include "qlua.h"
#include <QWidget>
#include <QApplication>
#include <QFile>
#include <QDebug> static int test(lua_State* state)
{
QPushButton* a = (QPushButton*)tolua_tousertype(state, , );
if(a)
a->show();
} static int connect(lua_State* state)
{
QObject * a = (QObject*)tolua_tousertype(state, , );
const char * signal = tolua_tostring(state, , );
QObject * b = (QObject*)tolua_tousertype(state, , );
const char * slot = tolua_tostring(state, , ); QObject::connect(a, QString("2%0").arg(signal).toLocal8Bit().data(),
b, QString("1%0").arg(slot).toLocal8Bit().data());
} static int tolua_new_QWidget(lua_State* state)
{
QWidget* widget = new QWidget();
tolua_pushusertype(state, widget, "QWidget");
return ;
} static int tolua_delete_QWidget(lua_State* state)
{
qDebug() << "delete Start";
QWidget* widget = (QWidget* )tolua_tousertype(state, , );
if(NULL != widget)
{
qDebug() << "delete~";
widget->close();
delete widget;
}
return ;
} static int tolua_Show_QWidget(lua_State* state)
{
QWidget* widget = (QWidget* )tolua_tousertype(state, , ); if(widget != NULL)
{
widget->show();
}
return ;
} static int tolua_new_QPushButton(lua_State* state)
{
QPushButton* button = new QPushButton();
tolua_pushusertype(state, button, "QPushButton");
return ;
} static int tolua_delete_QPushButton(lua_State* state)
{
QPushButton* button = (QPushButton* )tolua_tousertype(state, , );
if(NULL != button)
{
button->close();
delete button;
}
return ;
} static int tolua_Show_QPushButton(lua_State* state)
{
QPushButton* button = (QPushButton* )tolua_tousertype(state, , ); if(button != NULL)
{
button->show();
}
return ;
} static int tolua_setText_QPushButton(lua_State* state)
{
QPushButton* button = (QPushButton* )tolua_tousertype(state, , );
const char * text = tolua_tostring(state, , ); if(button != NULL)
{
button->setText(QString::fromLocal8Bit(text));
}
return ;
} static int tolua_Resize_QWidget(lua_State* state)
{
QWidget* widget = (QWidget* )tolua_tousertype(state, , );
double a = tolua_tonumber(state, , );
double b = tolua_tonumber(state, , ); if(widget)
{
widget->resize((int)a, (int)b);
}
return ;
} static int QApplication_instance(lua_State* state)
{
tolua_pushusertype(state, QApplication::instance(), "QApplication");
return ;
} static int QApplication_quit(lua_State* state)
{
QApplication * app = (QApplication *)tolua_tousertype(state, , );
if(app)
app->quit();
return ;
} static int QApplication_delete(lua_State*)
{
return ;
} int main(int argc, char * argv[])
{
Q_INIT_RESOURCE(resources);
QApplication a(argc, argv); QLua lua; lua.beginModule(""); lua.addType("QWidget", tolua_delete_QWidget);
lua.moduleTypeFunction("new", tolua_new_QWidget);
lua.moduleTypeFunction("show", tolua_Show_QWidget);
lua.moduleTypeFunction("resize", tolua_Resize_QWidget);
lua.endModule(); lua.addType("QPushButton", tolua_delete_QPushButton);
lua.moduleTypeFunction("new", tolua_new_QPushButton);
lua.moduleTypeFunction("show", tolua_Show_QPushButton);
lua.moduleTypeFunction("setText", tolua_setText_QPushButton);
lua.endModule(); lua.addType("QApplication", QApplication_delete);
lua.moduleTypeFunction("instance", QApplication_instance);
lua.moduleTypeFunction("quit", QApplication_quit);
lua.endModule(); lua.endModule(); lua.pushFunction("test", test);
lua.pushFunction("connect", connect); // 读取资源文件
QFile file("://test.lua");
file.open(QIODevice::ReadOnly | QIODevice::Text); QTextStream in(&file);
in.setCodec("UTF-8"); // 执行
lua.run(in.readAll()); return a.exec();
}

test.lua代码如下:

widget = QWidget:new()
widget:show() button = QPushButton:new()
button:setText("China")
button:show() connect(button, "clicked()", widget, "close()")
connect(button, "clicked()", button, "close()") print("run over")

程序运行结果如下:

点击China按钮,button和widget的窗口都会关闭。

至此,已经实现了连接 Qt 对象的信号与槽。

如果继续做下去,完全可以实现在Lua脚本中使用Qt的类和对象,写出Lua的Gui程序。

附完整代码工程文件:http://pan.baidu.com/s/1ntmFdjj

附个偶的博客地址:http://www.cnblogs.com/IT-BOY/

Win32下 Qt与Lua交互使用(三):在Lua脚本中connect Qt 对象的更多相关文章

  1. JavaScript -- 时光流逝(三):js中的 String 对象的方法

    JavaScript -- 知识点回顾篇(三):js中的 String 对象的方法 (1) anchor(): 创建 HTML 锚. <script type="text/javasc ...

  2. Win32下 Qt与Lua交互使用(二):在Lua脚本中使用Qt类

    话接上篇.成功配置好Qt+Lua+toLua后,我们可以实现在Lua脚本中使用各个Qt的类.直接看代码吧. #include "include/lua.hpp" #include ...

  3. C++与Lua交互(三)

    通过上一篇的热身,我们对C++调用lua变量有了一个认识,现在让我们再深入一点,去探索一下如何调用lua的函数.表. Lua与宿主通讯的关键--栈 lua是个动态脚本语言,它的数据类型如何映射到C++ ...

  4. C++与lua交互之C++访问lua

    假设lua中: name="gzw" id=17010805 sex=man tab={ num=100, str="hello" } foo_one=func ...

  5. Win32下 Qt与Lua交互使用(四):在Lua脚本中自由执行Qt类中的函数

    话接上篇.通过前几篇博客,我们实现在Lua脚本中执行Qt类中函数的方法,以及在Lua脚本中连接Qt对象的信号与槽. 但是,我们也能发现,如果希望在Lua脚本中执行Qt类的函数,就必须绑定一个真正实现功 ...

  6. 从零开始的Lua宅[1]:编译Lua解释器

    Lua是一门神奇的脚本语言,游戏宅必备,懒人必备.Lua差多不是学起来用起来最简单的语言了,以至于简单到自身就是文档,自身就是配置文件.但是Lua的运行效率却是众多脚本中非常高的,据说仅次于V8爹下的 ...

  7. QT 编译遇到重定义;不同的基类型&在QT中使用C++ lib库

    最近在使用osg和qt开发,在集成osg时候因为我使用的qt版本为非opengl的版本,导致qt自己封了一遍opengl的一些基类变量如double 这时候就会跟osg中声明的opengl的类型冲突, ...

  8. Win32下 Qt与Lua交互使用(一):配置Qt下Lua运行环境

    偶然间看到Lua这种脚本语言,有点兴趣,简单学习了一下. 发现Lua与C++之间可以实现非常强的交互性.Lua中可以使用C++中的函数,C++中也可以使用Lua中的函数.由此可以引发出很多奇思妙想了. ...

  9. Win32下 Qt与Lua交互使用:配置Qt下Lua运行环境

    Lua与C++之间可以实现非常强的交互性.Lua中可以使用C++中的函数,C++中也可以使用Lua中的函数.由此可以引发出很多奇思妙想了. 简单来说,Lua动态的特性补充了C++的功能.当然,也看你具 ...

随机推荐

  1. 21_resultMap和resultType总结

    [resultType] [ 作用 ] 将查询结果按照SQL列名与pojo属性名一致性 映射到pojo中. [ 使用场合 ] 常见的一些明细记录的展示,比如用户购买商品的明细,将关联查询信息全部展示在 ...

  2. 10_Jaxws使用自定义pojo发布服务

    [简述] 查询三天的天气信息(天气概况.日期.温度),测试jaxws是否支持自定义pojo发布服务. [开发过程] 服务端: 1.自定义pojo(天气概况.日期.温度) 2.开发SEI接口及实现类 3 ...

  3. Java如何获得平台相关的行分隔符、路径分隔符?

    我的技术博客经常被流氓网站恶意爬取转载.请移步原文:http://www.cnblogs.com/hamhog/p/3550194.html ,享受整齐的排版.有效的链接.正确的代码缩进.更好的阅读体 ...

  4. Nginx 域名转发

    例如访问www.b.cn直接跳到www.a.cn上去,又不想多域名捆绑一个目录. server { listen 80; server_name www.b.cn; rewrite ^/(.*)$ h ...

  5. Git-it:一个学习Git和Github的教程(软件)

    Git-it https://github.com/jlord/git-it 2016-08-01 在FreeCodeCamp的引导下了解到的Git-it.OSC有收录. Git-it是一个指导使用G ...

  6. RX学习笔记:FreeCodeCamp的JavaScript基本算法挑战

    FreeCodeCamp的JavaScript基本算法挑战 https://www.freecodecamp.com 2016-07-03 JavaScript还不是非常熟悉,用已经会的知识来解这些题 ...

  7. javascript中的sort()方法

    现在在学习javascript中,发现sort()函数是有点奇怪的东西(可能是本人水平的问题-_-!),于是就在这里记录一下自己找到的东西吧.sort()这个方法的参数很奇怪,必须是函数,但也是可选参 ...

  8. 初试mysql存储过程&触发器

    玩mysql以来,一直没有试过实现存储过程,因为存储过程的语法看起来有些笨重.所以一直采用手动批量运行查询,而且要手动改日期之类的参数. 今天尝试着学了一会,发现其实是很简单的.语法上确实格式复杂些, ...

  9. 免费使用的图表控件XML/SWF Charts 5.08

    免费使用的图表控件XML/SWF Charts 5.08 http://www.pin5i.com/showtopic-26053.html 10个免费的在线统计图表工具 http://paranim ...

  10. 闲谈前端编码解码、C#编码解码。

    最近做项目,出现中文乱码的问题,特地研究一下. GB2312,指的是中文 UTF8,指的是国标,包含中文.英文. 但是通过JQuery.ajax的Get.Post,如果直接传递中文或者特殊字符的特使字 ...