• Qt 如何搭建Lua的运行环境


    一、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
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    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
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

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

    #include 
    #include 
    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();
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68

    3、输出结果

    sum = 25
    subtract = -5
    multiply = 150
    divide = 0.667
    
    • 1
    • 2
    • 3
    • 4

    五、附上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")
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
  • 相关阅读:
    P2PNet-Soy原理梳理
    Linux网络配置管理
    python画box图并标记
    如何在树莓派上安装cpolar内网穿透
    @Valid和@Validated注解校验以及异常处理
    【PY】倒计时日历
    MATLAB算法实战应用案例精讲-【智能优化算法】灰狼算法(GWO) (附MATLAB和Python源码)
    Go 单元测试基本介绍
    调查:三分之一接受调查的黄金买家认为比特币是更好的选择
    自己定义 Advisor 实现自定义注解修饰的方法增强
  • 原文地址:https://blog.csdn.net/hellokandy/article/details/136619092