Win32下 Qt与Lua交互使用(三):在Lua脚本中connect Qt 对象
话接上文。笔者为了方便使用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 对象的更多相关文章
- JavaScript -- 时光流逝(三):js中的 String 对象的方法
JavaScript -- 知识点回顾篇(三):js中的 String 对象的方法 (1) anchor(): 创建 HTML 锚. <script type="text/javasc ...
- Win32下 Qt与Lua交互使用(二):在Lua脚本中使用Qt类
话接上篇.成功配置好Qt+Lua+toLua后,我们可以实现在Lua脚本中使用各个Qt的类.直接看代码吧. #include "include/lua.hpp" #include ...
- C++与Lua交互(三)
通过上一篇的热身,我们对C++调用lua变量有了一个认识,现在让我们再深入一点,去探索一下如何调用lua的函数.表. Lua与宿主通讯的关键--栈 lua是个动态脚本语言,它的数据类型如何映射到C++ ...
- C++与lua交互之C++访问lua
假设lua中: name="gzw" id=17010805 sex=man tab={ num=100, str="hello" } foo_one=func ...
- Win32下 Qt与Lua交互使用(四):在Lua脚本中自由执行Qt类中的函数
话接上篇.通过前几篇博客,我们实现在Lua脚本中执行Qt类中函数的方法,以及在Lua脚本中连接Qt对象的信号与槽. 但是,我们也能发现,如果希望在Lua脚本中执行Qt类的函数,就必须绑定一个真正实现功 ...
- 从零开始的Lua宅[1]:编译Lua解释器
Lua是一门神奇的脚本语言,游戏宅必备,懒人必备.Lua差多不是学起来用起来最简单的语言了,以至于简单到自身就是文档,自身就是配置文件.但是Lua的运行效率却是众多脚本中非常高的,据说仅次于V8爹下的 ...
- QT 编译遇到重定义;不同的基类型&在QT中使用C++ lib库
最近在使用osg和qt开发,在集成osg时候因为我使用的qt版本为非opengl的版本,导致qt自己封了一遍opengl的一些基类变量如double 这时候就会跟osg中声明的opengl的类型冲突, ...
- Win32下 Qt与Lua交互使用(一):配置Qt下Lua运行环境
偶然间看到Lua这种脚本语言,有点兴趣,简单学习了一下. 发现Lua与C++之间可以实现非常强的交互性.Lua中可以使用C++中的函数,C++中也可以使用Lua中的函数.由此可以引发出很多奇思妙想了. ...
- Win32下 Qt与Lua交互使用:配置Qt下Lua运行环境
Lua与C++之间可以实现非常强的交互性.Lua中可以使用C++中的函数,C++中也可以使用Lua中的函数.由此可以引发出很多奇思妙想了. 简单来说,Lua动态的特性补充了C++的功能.当然,也看你具 ...
随机推荐
- C语言 goto, return等跳转
C语言 goto, return等跳转 Please don't fall into the trap of believing that I am terribly dogmatical about ...
- N的N次方(高校俱乐部)
最近一直在刷字符串和线段树,也越来越少玩高校俱乐部,无聊看到一题N的N次方的问题,脑海中各种打表就涌现出来了. 弄了不一会儿,就写完了,马上提交,但是系统好像出了问题,提示"哦哦,出了点状况 ...
- 九度OJ 1533 最长上升子序列 -- 动态规划
题目地址:http://ac.jobdu.com/problem.php?pid=1533 题目描述: 给定一个整型数组, 求这个数组的最长严格递增子序列的长度. 譬如序列1 2 2 4 3 的最长严 ...
- Linux中的简单命令
history:打印你输过的命令 1.用户在shell中输入的命令会自动保存到内存缓冲区 2.在退出shell的时候,内存中的数据会刷新到磁盘文件:~/.bash_history ...
- plsql通过instantclient连接oracle数据库报连接超时
配置:数据库oracle10.2;服务器操作系统centos5.5:客户机操作系统win7 32位:plsql版本10.0.5 配置前提必须关闭客户机与服务器操作系统的防火墙,否则会出现“连接超时”的 ...
- 腾讯视频嵌入手机端网站demo - 就像微信文章中一样一样的
页面中的调用如下: <iframe id="video_iframe" class="video_iframe" src="TenVideoPl ...
- WPF 列表控件中的子控件上下文绑定
<DataGrid Grid.ColumnSpan=" Height="Auto" SelectedItem="{Binding Path=SelectP ...
- 【GPS】 数据围栏
1.记录gps信息,定位类型 gps agps ,偏移量 2.根据id检索用户 gps 历史记录 3.创建围栏 4.围栏内用户检索(先实现 圆形和矩形) 5.判断一个点是否进出围栏 应用场景: o ...
- Elasticsearch强大的聚合功能Facet
在常规数据库中,我们都知道有一个sql就是group,分组.如果主表只有对应的一个列记录的分组的ID,那么还好统计,比如说每本书book表,有一个分类catId,记录是属于哪一类的书,那么直接按照ca ...
- 转 scrollLeft,scrollWidth,clientWidth,offsetWidth之完全详解
scrollHeight: 获取对象的滚动高度. scrollLeft:设置或获取位于对象左边界和窗口中目前可见内容的最左端之间的距离 scrollTop:设置或获取位于对象最顶端和窗口中可见内容的最 ...