Qt 如何搭建lua的运行环境

news2024/11/25 14:34:22

一、lua简介

Lua 是一种强大的、高效的、轻量级的、可嵌入的脚本语言。它支持过程(procedural)编程、面向对象编程、函数式编程以及数据描述。Lua 是动态类型的,运行速度快,支持自动内存管理,因此被广泛用于配置、脚本编写等场景。

二、lua的优势

Lua脚本可以很容易的被C/C++ 代码调用,也可以反过来调用C/C++的函数,这使得Lua在应用程序中可以被广泛应用。不仅仅作为扩展脚本,也可以作为普通的配置文件,代替XML、ini等文件格式,并且更容易理解和维护。 Lua由标准C编写而成,代码简洁优美,几乎在所有操作系统和平台上都可以编译、运行。 一个完整的Lua解释器不过200k,在所有脚本引擎中,Lua的速度是最快的。这一切都决定了Lua是作为嵌入式脚本的最佳选择。

三、Qt + lua 环境搭建

Lua是用标准C编写的,所以几乎常见的编程环境它都能编译Lua。下载源码包后,直接编译即可。

1、 下载lua(下载地址:https://www.lua.org/ftp/)

在这里插入图片描述

2、 使用QtCreator编译lua.a库

打开QtCreator,新建项目 > Library > C++库,在后续弹出的窗口中选择 Statically Linked Library,根据向导完成项目的创建,然后删掉由向导添加的头文件和源文件。将除了lua.c和luac.c以外的文件加入到你的开发环境中进行编译即可。(文末有对应的pro文件,可以参考一下。)
ps:lua.c 和 luac.c 中都有main函数,需要分别编译这两个文件。其中,lua.c编译出来是解析器,luac.c编译出来是编译器。

四、在Qt中调用lua

1、 新建一个math.lua文件,内容如下:

function fn_add(x,y)
    return x + y
end

function fn_subtract(x,y)
    return x - y
end

function fn_multiply(x,y)
    return x * y
end

function fn_divide(x,y)
    return x*1.0 / y
end

2、Qt调用lua的测试代码

新建Qt控制台程序,在该控制台程序的pro文件,配置一下lua库的头文件以及库文件路径:

CONFIG(debug, debug|release){
    DESTDIR = $$PWD/../bin/debug
    OBJECTS_DIR += $$PWD/../obj/debug
    DIR_NAME = debug
}
CONFIG(release, debug|release){
    DESTDIR = $$PWD/../bin/release
    OBJECTS_DIR += $$PWD/../obj/release
    DIR_NAME = release
}
INCLUDEPATH  += $$PWD/./3rdparty/libLua/include
LIBS += -L$$PWD/./3rdparty/libLua/lib/$${DIR_NAME}/ -lliblua

控制台main.cpp的代码如下:

#include <QCoreApplication>
#include <stdio.h>
extern "C"{
#include "lua.h"
#include "lauxlib.h"
#include "lualib.h"
}

lua_State *L;
double luaMath(std::string fname, int x, int y)
{
    /* 要调用一个函数请遵循以下协议:
     * 首先,要调用的函数应该被压入栈,接着把需要传递给这个函数的参数按正序压栈,
     * 这是指第一个参数首先压栈。最后调用一下 lua_call,当函数调用完毕后,
     * 所有的参数以及函数本身都会出栈,而函数的返回值这时则被压栈。*/

    double result;
    /*获取函数名*/
    lua_getglobal(L, fname.c_str());

    /*压入第一个参数*/
    lua_pushnumber(L, x);

    /*压入第二个参数*/
    lua_pushnumber(L, y);

    /*使用2个参数调用函数,返回1个结果。*/
    lua_call(L, 2, 1);

    /*获取结果*/
    result = (double)lua_tonumber(L,-1);

    /*清理返回结果*/
    lua_pop(L, 1);

    return result;
}

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);
    L =  luaL_newstate();//新建lua解释器
    luaL_openlibs(L);//载入lua基础库

#if 1
    //执行lua脚本:
    luaL_dofile(L, "lua/math.lua");//填写实际的math.lua文件的相对路径

    /*call the add function*/
    int sum = luaMath("fn_add", 10, 15);
    printf("sum = %d\r\n", sum);

    int subtract = luaMath("fn_subtract", 10, 15);
    printf("subtract = %d\r\n", subtract);

    int multiply = luaMath("fn_multiply", 10, 15);
    printf("multiply = %d\r\n", multiply);

    auto divide = luaMath("fn_divide", 10, 15);
    printf("divide = %.3f\r\n", divide);
#endif

    /*cleanup Lua*/
    lua_close(L);

    system("pause");
    return a.exec();
}

3、输出结果

sum = 25
subtract = -5
multiply = 150
divide = 0.667

五、附上lua库的pro文件内容:

QT -= gui

TEMPLATE = lib
CONFIG += staticlib

CONFIG += c++11

#去掉生成空的debug和release目录
CONFIG -= debug_and_release

# 编译时临时文件路径
RCC_DIR += $$PWD/../temp/rcc_tmp
MOC_DIR += $$PWD/../temp/moc_tmp
UI_DIR  += $$PWD/../temp/ui_tmp

CONFIG(debug, debug|release){
    DESTDIR = $$PWD/../lib/debug
    OBJECTS_DIR += $$PWD/../obj/debug
    DIR_NAME = debug
}
CONFIG(release, debug|release){
    DESTDIR = $$PWD/../lib/release
    OBJECTS_DIR += $$PWD/../obj/release
    DIR_NAME = release
}

# The following define makes your compiler emit warnings if you use
# any Qt feature that has been marked deprecated (the exact warnings
# depend on your compiler). Please consult the documentation of the
# deprecated API in order to know how to port your code away from it.
DEFINES += QT_DEPRECATED_WARNINGS

# You can also make your code fail to compile if it uses deprecated APIs.
# In order to do so, uncomment the following line.
# You can also select to disable deprecated APIs only up to a certain version of Qt.
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000    # disables all the APIs deprecated before Qt 6.0.0

SOURCES += \
    lapi.c \
    lauxlib.c \
    lbaselib.c \
    lcode.c \
    lcorolib.c \
    lctype.c \
    ldblib.c \
    ldebug.c \
    ldo.c \
    ldump.c \
    lfunc.c \
    lgc.c \
    linit.c \
    liolib.c \
    llex.c \
    lmathlib.c \
    lmem.c \
    loadlib.c \
    lobject.c \
    lopcodes.c \
    loslib.c \
    lparser.c \
    lstate.c \
    lstring.c \
    lstrlib.c \
    ltable.c \
    ltablib.c \
    ltm.c \
    lundump.c \
    lutf8lib.c \
    lvm.c \
    lzio.c

HEADERS += \
    lapi.h \
    lauxlib.h \
    lcode.h \
    lctype.h \
    ldebug.h \
    ldo.h \
    lfunc.h \
    lgc.h \
    ljumptab.h \
    llex.h \
    llimits.h \
    lmem.h \
    lobject.h \
    lopcodes.h \
    lopnames.h \
    lparser.h \
    lprefix.h \
    lstate.h \
    lstring.h \
    ltable.h \
    ltm.h \
    lua.h \
    lua.hpp \
    luaconf.h \
    lualib.h \
    lundump.h \
    lvm.h \
    lzio.h

# Default rules for deployment.
unix {
    target.path = $$[QT_INSTALL_PLUGINS]/generic
}
!isEmpty(target.path): INSTALLS += target

#拷贝头文件到include目录下
win32 {
    SrcIncludeDir = $${PWD} #定义的宏变量,在非首位置使用时需要带{}
    SrcIncludeDir = $$replace(SrcIncludeDir, /, \\)
    DstIncludeDir = $$PWD/../include/
    DstIncludeDir = $$replace(DstIncludeDir, /, \\)
    #多条命令语句之间可以用&&隔开,自动连续执行
    QMAKE_POST_LINK += echo "---------prepare to copy *.h---------" && echo.
    QMAKE_POST_LINK += cd $$SrcIncludeDir &&  xcopy /s/y/i $$SrcIncludeDir\lauxlib.h $$DstIncludeDir
    QMAKE_POST_LINK += &&  xcopy /s/y/i $$SrcIncludeDir\lua.h $$DstIncludeDir
    QMAKE_POST_LINK += &&  xcopy /s/y/i $$SrcIncludeDir\luaconf.h $$DstIncludeDir
    QMAKE_POST_LINK += &&  xcopy /s/y/i $$SrcIncludeDir\lualib.h $$DstIncludeDir

    #打印测试
    #message("--SrcIncludeDir= $$SrcIncludeDir")
    #message("--DstIncludeDir= $$DstIncludeDir")
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1512009.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

鸿蒙Harmony应用开发—ArkTS声明式开发(基础手势:Select)

提供下拉选择菜单&#xff0c;可以让用户在多个选项之间选择。 说明&#xff1a; 该组件从API Version 8开始支持。后续版本如有新增内容&#xff0c;则采用上角标单独标记该内容的起始版本。 子组件 无 接口 Select(options: Array<SelectOption>) 参数&#xff1a;…

HUAWEI 华为交换机 配置 MAC 地址漂移检测示例

组网需求 如 图 2-17 所示&#xff0c;网络中两台 LSW 间网线误接形成了网络环路&#xff0c;引起 MAC 地址发生漂 移、MAC 地址表震荡。 为了能够及时检测网络中出现的环路&#xff0c;可以在 Switch 上配置 MAC 地址漂移检测功能&#xff0c; 通过检测是否发生MAC 地址漂移…

网络学习:BGP路径属性分类

目录 前言&#xff1a; 路径属性分类 公认必遵 公认任意 可选过渡 可选非过渡 前言&#xff1a; 在默认情况下&#xff0c;到达同一目的地&#xff0c;BGP只走单条路径&#xff0c;并不会在多条路径之间执行负载均衡。对于IGP路由协议&#xff0c;当有多条路径可以到达同…

丘一丘正则表达式

正则表达式(regular expression,regex,RE) 正则表达式是一种用来简洁表达一组字符串的表达式正则表达式是一种通用的字符串表达框架正则表达式是一种针对字符串表达“简洁”和“特征”思想的工具正则表达式可以用来判断某字符串的特征归属 正则表达式常用操作符 操作符说明实…

[vscode]将命令行参数传递给调试目标

一、简介 本文介绍了在vscode中使用cmake工具时&#xff0c;如何传递参数给编译目标的方法。 前提&#xff1a;使用vscodecmake编译C/C程序。 二、方法 在.vscode/目录下新建settings.json文件&#xff0c;并将待传底的参数写在 cmake.debugConfig里。 下面介绍了一个示例&a…

DAY14二叉树迭代遍历

二叉树前序迭代法遍历 前序遍历是中左右&#xff0c;每次先处理的是中间节点&#xff0c;那么先将根节点放入栈中&#xff0c;然后将右孩子加入栈&#xff0c;再加入左孩子。 为什么要先加入 右孩子&#xff0c;再加入左孩子呢&#xff1f; 因为这样出栈的时候才是中左右的顺…

Stable Diffusion 如何写好提示词(Prompt)

本文收录于《AI绘画从入门到精通》专栏&#xff0c;专栏总目录&#xff1a;点这里。 大家好&#xff0c;我是水滴~~ 本文深入探讨了如何撰写出优质的提示词&#xff0c;内容涵盖多个维度&#xff1a;提示词的多样化分类、模型应用中的经典提示词案例、提供丰富资源的提示词参考…

基于STM32的智慧农业管理系统设计与实现

文章目录 一、前言1.1 项目介绍【1】项目功能【2】设计实现的功能【3】项目硬件模块组成 1.2 设计思路1.3 传感器功能介绍1.4 开发工具的选择 二、EMQX开源MQTT服务器框架三、购买ECS云服务器3.1 登录官网3.2 购买ECS服务器3.3 配置安全组3.4 安装FinalShell3.5 远程登录到云服…

Java代码审计工程师直播第六期

本期直播课程将深入探讨Java代码审计的关键概念和技术。涵盖课题包括安全漏洞分析、代码审查方法、常见漏洞案例分析等。学员将通过实例掌握代码审计实战技能&#xff0c;提升对Java应用程序安全的认知和技能水平。 课程大小&#xff1a;6.1G 课程下载&#xff1a;https://do…

Docker 容器化技术:构建高效、可移植的开发环境和部署流程|Docker 三要素

镜像、容器、镜像仓库是 Docker 中最核心的三个概念&#xff0c;组成了 Docker 的整个生命周期。 &#xff08;镜像、容器、镜像仓库三者运行关系&#xff09; 1、镜像 镜像是 Docker 的核心元素质疑&#xff0c;作为容器运行的基础&#xff0c;Docker Hub 官网提供了庞大的镜…

第十五届蓝桥杯(Web 应用开发)模拟赛 3 期-大学组(被题目描述坑惨了)

目录 1.创意广告牌 2.原子化css 3.神秘咒语 4.朋友圈 5.美食蛋白揭秘 6.营业状态变更 7.小说阅读器 8.冰岛人 9.这是一个”浏览器“ 10.趣味加密解密 总结 1.创意广告牌 这个题目不多说了&#xff0c;只要知道这些css应该都能写出来&#xff0c;不会的平时多查查文…

突破界限的力量:探索Facebook如何打破国界、文化和语言的障碍

在当今全球化的时代&#xff0c;社交媒体已经成为人们生活中不可或缺的一部分&#xff0c;而Facebook作为其中的先驱者&#xff0c;更是在打破国界、文化和语言障碍方面发挥着举足轻重的作用。它不仅成为了人们交流、连接的重要平台&#xff0c;更是为不同国家、不同文化、不同…

固态存储是未来|浅析SSD架构的演进与创新技术-1

常见的SSD架构中&#xff0c;包括了SSD控制器、NAND颗粒、DRAM颗粒三大组件&#xff0c;SSD控制器的固件需要兼顾坏块管理、ECC纠错、垃圾回收GC、磨损均衡WL、NAND die介质管理、缓存交互等等。 随着时代的发展&#xff0c;SSD架构&#xff0c;也不断有新的挑战和需求。基于小…

抓取Instagram数据:Fizzler库带您进入C#爬虫程序的世界

引言 在当今数字化的世界中&#xff0c;数据是无价之宝。社交媒体平台如Instagram成为了用户分享照片、视频和故事的热门场所。作为开发人员&#xff0c;我们可以利用爬虫技术来抓取这些平台上的数据&#xff0c;进行分析、挖掘和应用。本文将介绍如何使用C#编写一个简单的Ins…

一条 sql 语句可能导致的表锁和行锁以及死锁检测

锁 MDL 当对一个表做增删改查操作的时候&#xff0c;加 MDL 读锁&#xff1b;当要对表做结构变更操作的时候&#xff0c;加 MDL 写锁 ALTER TABLE tbl_name NOWAIT add column ... ALTER TABLE tbl_name WAIT N add column ... …

小程序bindtap 和 catchtap 的区别以及如何使用

Hello大家好&#xff01;我是咕噜铁蛋&#xff01;我今天要和大家聊一聊小程序开发中的一个常见问题&#xff1a;bindtap 和 catchtap 的区别以及如何使用。这两个在小程序开发中经常被提及的事件绑定方式&#xff0c;它们之间到底有什么不同呢&#xff1f;让我们一起来深入探讨…

Prometheus监控Mysql数据库在Grafana展示

未安装prometheus和Grafana可以参考这个博客操作 Docker安装Prometheus监控-CSDN博客 Windows版本数据库 一、在数据库服务器安装mysqld-exporter 下载mysqld-exporter文件 Releases prometheus/mysqld_exporter GitHub 二、配置mysqld-exporter文件 1、解压进入mysqld…

微服务架构中的拆分粒度决策

大家好&#xff01;今天我来和大家分享一下微服务架构中的拆分粒度决策问题&#xff0c;希望能帮助大家更好地理解和应用微服务架构&#xff01; 问题背景 在设计和实施微服务架构时&#xff0c;拆分粒度的决策非常重要。拆分得太细&#xff0c;会增加系统间通信和部署的复杂性…

基于Springboot的驾校预约学习系统(有报告)。Javaee项目,springboot项目。

演示视频&#xff1a; 基于Springboot的驾校预约学习系统&#xff08;有报告&#xff09;。Javaee项目&#xff0c;springboot项目。 项目介绍&#xff1a; 采用M&#xff08;model&#xff09;V&#xff08;view&#xff09;C&#xff08;controller&#xff09;三层体系结构…

12、设计模式之代理模式(Proxy)

一、什么是代理模式 代理模式属于结构型设计模式。为其他对象提供一种代理以控制对这个对象的访问。 在某些情况下&#xff0c;一个对象不适合或者不能直接引用另一个对象&#xff0c;而代理对象可以在客户端和目标对象之间起到中介的作用。 二、分类 代理模式分为三类&#…