话接上文。笔者为了方便使用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. HTML Music Entities/音乐符号

    HTML Music Entities Musical symbols Description Character(click) HTML-Entity Code-Decimal Code-Hex Q ...

  2. makefile-0711-168 SEVERE ERROR: Input file:

    ld: 0711-168 SEVERE ERROR: Input file: /cicm/commlib/include        Input files must be regular file ...

  3. C++ GUI Programming with Qt4 笔记 -- chap2 QDialog

    以 finddialog 为例,介绍 QDialog.并对 Qt 的基本概念和技巧做了更进一步(chap1)的介绍. 1.MOC 扩展与signals–slots 机制 严格来说,Qt 开发,写的并不 ...

  4. VS2010 EntityFramework Database First

    本文演练介绍如何使用实体框架进行 Database First 开发.通过 Database First,可以从现有数据库对模型进行反向工程处理.模型存储在一个 EDMX 文件(扩展名为 .edmx) ...

  5. mysql 高性能

    第一章节:共享锁(读锁),排他锁(写锁) 查询数据表所使用的存储引擎:show table status like '表名' \G 转换数据表的存储引擎:alter table 表名 engine=引 ...

  6. ASP.NET输入文本框自动提示功能

    在ASP.NET Web开发中会经常用到自动提示功能,比如百度搜索.我们只要输入相应的关键字,就可以自动得到相似搜索关键字的提示,方便我们快速的输入关键字进行查询. 那么在ASP.NET中,如果我们需 ...

  7. [HttpClient]SSL双向实例

    package com.jerry.httpclient; import java.io.File; import java.io.FileInputStream; import java.secur ...

  8. rhel_6.x 安装mysql

    不知为何mysql的官网很难下载,本人网上找了好久,终于找到了个镜像: 特别感谢http://mirrors.sohu.com/mysql/MySQL-5.6/    ^_^ 首先下载mysql的下面 ...

  9. 解决MySQL查询不区分大小写

    需要设置collate(校对) . collate规则: *_bin: 表示的是binary case sensitive collation,也就是说是区分大小写的 *_cs: case sensi ...

  10. struts2 修改action的后缀

    struts2 修改action的后缀 struts2 的默认后缀是 .action 虽然很直观,但是很烦琐.很多人喜欢将请求的后缀改为 .do 在struts2中修改action后缀有两种比较简单的 ...