话接上文。笔者为了方便使用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. 往xml中更新节点

    /* System.out.println("2323"); DocumentBuilderFactory factory = DocumentBuilderFactory.new ...

  2. There is no Action mapped for namespace [/] and action name [user] associated with context path

    从c++转到java,初学struts,竟然碰到一个因写错单词而造成的错误,structs --> struts

  3. C语言经典案例

    题目:企业发放的奖金根据利润提成.利润(I)低于或等于10万元时,奖金可提10%:利润高于10万元,低于20万元时,低于10万元的部分按10%提成,高于10万元的部分,可可提成7.5%:20万到40万 ...

  4. HTML5入门篇

    ---- HTML5简介 HTML5 是用于取代1999年所制定的 HTML 4.01 和 XHTML 1.0 标准的 HTML 标准版本,现在仍处于发展阶段,但大部分浏览器已经支持某些 HTML5 ...

  5. php用正则表达式获取网站的标题内容

    已知网站的网址,用php获取网站的内容. 编写正则表达式. 用preg_match_all函数获取标题内容. $url='http://www.m-ivi.com'; $content=file_ge ...

  6. 虚拟机添加磁盘LVM分区

    参考博客:http://kimjinlsgd.blog.51cto.com/1918030/932210 一.查看磁盘情况 新添加一块磁盘. [root@VMhost /]# fdisk -l Dis ...

  7. Codeforces Round #345 (Div. 1) B. Image Preview

    Vasya's telephone contains n photos. Photo number 1 is currently opened on the phone. It is allowed ...

  8. PL/SQL — 集合及常用方法

    PL/SQL中提供了常用的三种集合联合数组.嵌套表.变长数组,而对于这几个集合类型中元素的操作,PL/SQL提供了相应的函数或过程来操纵数组中的元素或下标.这些函数或过程称为集合方法.一个集合方法就是 ...

  9. myeclipse10.0优化

    一.Myeclipse10修改字体  MyEclipse10是基于Eclipse3.7内核,但在Eclipse的Preferences-〉general-〉 Appearance->Colors ...

  10. C# foreach 原理以及模拟的实现

    public class Person:IEnumerable     //定义一个person类  并且 实现IEnumerable 接口  (或者不用实现此接口 直接在类 //里面写个GetEnu ...