首页 > 编程语言 >在C/C++中嵌入Lua代码及使用VS Code调试

在C/C++中嵌入Lua代码及使用VS Code调试

时间:2024-08-15 16:24:46浏览次数:9  
标签:lua C++ Lua json VS usr include

  Lua在设计之初就是为了嵌入到应用程序中,为这些应用程序提供灵活的扩展和定制功能。Lua的核心是用C语言编写的,所以Lua脚本可以很容易地与C/C++代码进行交互,通过Lua脚本,用户可以在不修改原有C/C++代码的基础上,实现功能的扩展和定制。

  在C/C++程序中可以使用Lua来编写一些需要频繁修改的逻辑,而不需要重新编译整个C/C++程序,从而加快开发周期。对于一些复杂的逻辑,使用Lua脚本实现可能比直接用C/C++编写更加简单和直观。在以上基础上Lua脚本还可以快速实现和测试新的想法和功能,快速完成原型开发。

 编写C/C++代码

在C/C++中嵌入Lua代码的流程如下: 

  1. 初始化Lua环境:使用Lua提供的API(luaL_newstate)创建一个新的Lua环境(Lua State)。
  2. 加载Lua脚本:使用Lua的C API(luaL_dofile)加载并执行Lua脚本文件。
  3. 调用Lua函数:通过Lua的C API(lua_getgloballua_pushnumberlua_pcall等)调用Lua脚本中定义的函数,并传递参数。
  4. 获取返回值:Lua函数执行完毕后,使用Lua的C API(lua_tonumberlua_tostring等)从栈中获取返回值。
  5. 关闭Lua环境:使用Lua的C API(lua_close)关闭Lua环境,释放相关资源。

Lua和C/C++之间的交互主要依赖于一个虚拟栈(Lua State)。这个栈是先进后出的,用于在Lua和C/C++之间传递数据和函数参数。当C/C++代码需要调用Lua函数或访问Lua变量时,它会将数据压入栈中;Lua执行完毕后,会将结果压回栈中,供C/C++代码读取。这种机制使得Lua和C/C++之间的交互变得简单而高效。 

在Lua与C/C++的交互过程中,需要进行数据类型转换。比如将C语言中的整数类型转换为Lua中的数值类型,或将Lua中的表转换为C语言中的结构体等。在注册到Lua环境中的C函数和扩展模块中,需要对数据进行正确的类型转换。 

C语言示例

  先新建一个test.c文件,将以下内容复制到文件中:

// test.c
#include <lua.h>  
#include <lualib.h>  
#include <lauxlib.h>  
  
int main(void) {  
    lua_State *L = luaL_newstate();  // 创建Lua状态机 
    luaL_openlibs(L);                // 打开Lua标准库 
  
    // 执行Lua脚本 
    const char *lua_script = "print('Hello gay boy!')";  
    if (luaL_dostring(L, lua_script) != LUA_OK) {  
        const char *message = lua_tostring(L, -1);  
        printf("Error executing Lua script: %s\n", message);  
        lua_pop(L, 1);  // 弹出错误消息
    }  
  
    lua_close(L);  // 关闭Lua状态机 
    return 0;  
}
C++示例

 先新建一个test.cpp文件,将以下内容复制到文件中:

#include <iostream>  
#include <lua.hpp>
  
int main() {  
    lua_State* L = luaL_newstate();      // 初始化Lua状态机  
    luaL_openlibs(L);  // 打开Lua标准库  
  
    const char* luaCode = "print('Hello from Lua!')";  
    if (luaL_dostring(L, luaCode)) {   
        std::cerr << "Lua error: " << lua_tostring(L, -1) << std::endl;  
        lua_pop(L, 1);  // 移除错误消息  
        return 1;  // 返回错误码  
    }  
    // 关闭Lua状态机  
    lua_close(L);  
  
    return 0;
}

编译C/C++文件

 C语言文件编译

在Linux和Windows系统中,都需要先找到lua.h的安装路径,Windows系统为path环境变量中保存的路径,我使用的Ubuntu系统,路径如下:

 在找到安装路径后,可以使用以下命令编译并运行嵌入了Lua代码的C源文件,在-I后面需要替换为自己的实际路径

gcc test.c -I/usr/include/lua5.4/ -llua5.4 -o test
./test

 运行结果如下:

 Windows使用以下命令:
在Windows中,链接库时通常使用库的完整名称,包括前缀和后缀。如果使用的是MinGW或类似工具链,需要指定-llua对应的完整库名,如-llua54-llua,具体取决于库文件(如lua54.dlllua.dll)的实际名称。

gcc test.c -IC:\path\to\lua\include -LC:\path\to\lua\lib -llua54 -o test

 这里: -IC:\path\to\lua\include指定了Lua头文件的位置。

    -LC:\path\to\lua\lib指定了Lua库文件的位置

C++语言文件编译

C++语言嵌入Lua语言需要找到lua.hpp文件,编译命令与C语言文件编译方式相似:

g++  test.cpp -I/usr/include/lua5.4/ -llua5.4 -o test
./test

在VS Code中调试 

这里因为没有在VS Code中配置头文件导入路径,会产生报错曲线: 

 这里可以点击左侧的debug图标,随后点击 运行和调试创建launch.json

 在项目文件夹中会出现.vscode文件夹,文件夹中存在以下三个文件:

tasks.json:该文件用于配置编译任务。它指定了编译命令、编译参数以及输出文件的位置。对于多文件项目,需要确保tasks.json中包含了所有相关的源文件。

launch.json:该文件用于配置调试任务。它指定了调试器的类型(如gdb或lldb)、调试请求的类型(如launch或attach)、程序路径、工作目录以及其他调试选项。在调试过程中,VS Code会根据launch.json中的配置启动调试器,加载可执行文件,并在设置的断点处暂停执行。

c_cpp_properties.json:通过配置编译器路径、头文件搜索路径、预处理器宏定义等信息,支持VSCode中的IntelliSense功能,提供高效的代码补全、代码导航和调试支持。 

 C语言版本

首先将包含 lua.h 的文件夹安装路径添加到c_cpp_properties.json中

                "/usr/include/lua5.4/",
                "/home/astra/luajit/src/"

完整的c_cpp_properties.json内容如下: 

{
    "configurations": [
        {
            "name": "Linux",
            "includePath": [
                "${workspaceFolder}/**",
                "/usr/include/lua5.4/",
                "/home/astra/luajit/src/"
            ],
            "defines": [],
            "compilerPath": "/usr/bin/gcc",
            "cStandard": "c17",
            "cppStandard": "gnu++17",
            "intelliSenseMode": "linux-gcc-x64"
        }
    ],
    "version": 4
}

 将以下编译命令添加到tasks.json中,这里需要自己的lua版本进行修改

                "-I/usr/include/lua5.4/",  
                "-llua5.4", 

完整的tasks.json内容如下:

{
    "tasks": [
        {
            "type": "cppbuild",
            "label": "C/C++: gcc build active file",
            "command": "/usr/bin/gcc",
            "args": [
                "-fdiagnostics-color=always",
                "-g",
                "${file}",
                "-o",
                "${fileDirname}/${fileBasenameNoExtension}",
                "-I/usr/include/lua5.4/",  
                "-llua5.4",  
            ],
            "options": {
                "cwd": "${fileDirname}"
            },
            "problemMatcher": [
                "$gcc"
            ],
            "group": {
                "kind": "build",
                "isDefault": true
            },
            "detail": "Task generated by Debugger."
        }
    ],
    "version": "2.0.0"
}

点击右上角的调试按钮,即可对代码进行调试

C/C++版本 

 调试C++文件需要在上述json文件中加入连接到C++标准库的显示连接

                "-lstdc++"  // 显式链接到C++标准库

 launch.json

{  
    "version": "0.2.0",  
    "configurations": [  
        {  
            "name": "C++ Lua Debug",  
            "type": "cppdbg",  
            "request": "launch",  
            "program": "${fileDirname}/${fileBasenameNoExtension}",  
            "args": [
                "-fdiagnostics-color=always",  
                "-g",  
                "${file}",  
                "-o",  
                "${fileDirname}/${fileBasenameNoExtension}",  
                "-I/usr/include/lua5.4/",  
                "-llua5.4",  
                "-lstdc++"  // 显式链接到 C++ 标准库  
            ],  
            "stopAtEntry": false,  
            "cwd": "${workspaceFolder}",  
            "environment": [],  
            "externalConsole": false,  
            "MIMode": "gdb",  
            "setupCommands": [  
                {  
                    "description": "Enable pretty-printing for gdb",  
                    "text": "-enable-pretty-printing",  
                    "ignoreFailures": true  
                }  
            ],  
            "preLaunchTask": "C/C++: gcc build active file",  
            "miDebuggerPath": "/usr/bin/gdb"
        }  
    ]  
}

 tasks.json

{  
    "version": "0.2.0",  
    "configurations": [  
        {  
            "name": "C++ Lua Debug",  
            "type": "cppdbg",  
            "request": "launch",  
            "program": "${fileDirname}/${fileBasenameNoExtension}",  
            "args": [
                "-fdiagnostics-color=always",  
                "-g",  
                "${file}",  
                "-o",  
                "${fileDirname}/${fileBasenameNoExtension}",  
                "-I/usr/include/lua5.4/",  
                "-llua5.4",  
                "-lstdc++"  // 显式链接到C++标准库  
            ],  
            "stopAtEntry": false,  
            "cwd": "${workspaceFolder}",  
            "environment": [],  
            "externalConsole": false,  
            "MIMode": "gdb",  
            "setupCommands": [  
                {  
                    "description": "Enable pretty-printing for gdb",  
                    "text": "-enable-pretty-printing",  
                    "ignoreFailures": true  
                }  
            ],  
            "preLaunchTask": "C/C++: gcc build active file",  
            "miDebuggerPath": "/usr/bin/gdb"
        }  
    ]  
}

 c_cpp_properties.json

{
    "configurations": [
        {
            "name": "Linux",
            "includePath": [
                "${workspaceFolder}/**",
                "/usr/include/lua5.4/",
                "/home/astra/luajit/src/"
            ],
            "defines": [],
            "compilerPath": "/usr/bin/gcc",
            "cStandard": "c17",
            "cppStandard": "gnu++17",
            "intelliSenseMode": "linux-gcc-x64"
        }
    ],
    "version": 4
}

标签:lua,C++,Lua,json,VS,usr,include
From: https://blog.csdn.net/m0_73500130/article/details/141105623

相关文章

  • 基于价值流DevSecOps效能案例介绍
    背景    数字经济时代,企业数字化转型加速,软件业务收入目标设定,产业基础保障水平提升。DevSecOps:作为解决交付能力挑战的方法,强调开发(Dev)、安全(Sec)、运维(Ops)的整合。DevSecOps持续发布流水线通过两种发布快速通路实现质量效率的均衡,一种是以自动Q点(质量检查点)检查快速上线方......
  • JAVA8 stream 流 vs JDFrame (转)
    转自: https://juejin.cn/post/7356652717392740404个人开源框架矩阵百万级任务重试框架Fast-Retrystream流太难用了看看JDFramespring-smart-di动态切换实现类框架UniHttp第三方接口对接框架0、简介由于经常记不住stream的一些API每次要复制来复制去并且又长又臭,想要更......
  • C++标准库 algorithm 堆操作 heap
    算法库-堆操作基本操作make_heap()(1)从一个元素范围创建出一个最大堆(2)将区间内的元素转化为heap.--传比较器push_heap()对heap增加一个元素.将一个元素加入到一个最大堆pop_heap()对heap取出下一个元素.从最大堆中移除最大元素sort_heap()对heap转化为一......
  • C++标准库 iomanip 输入输出操纵符 Manipulator
    输入/输出操纵符输入输出操纵符是C++中用于控制输入输出流格式的一组特殊函数或对象。它们通常用于格式化输出,例如设置宽度、精度、对齐方式等,而不涉及数据的实际读写。功能概述:输入输出操纵符能够控制输出的外观,比如调整对齐方式、设置输出的宽度和精度、控制换行等。使用......
  • 【计算机二级C++】题目与C++知识自检
    @目录公共基础知识计算机基础数据库数据结构树链表排序队列栈C++const与static指针函数重载构造与析构多态、继承、权限数据类型输入输出流模板公共基础知识计算机基础计算机完成一条指令所花费的时间称为指令周期顺序程序不具有并发性下列叙述中正确的是CA.算法的......
  • C/C++ 动态分配:malloc()和free()所涉及的空指针和强制类型转换、与new和delete的对比
    1、动态分配的内涵所谓动态内存分配,是指在程序运行时根据需要分配和释放内存,而不是在编译时确定内存需求。动态分配包括两方面的内涵:在堆上分配内存。对于linux的虚拟内存,可以分成以下5段:文本段、数据段(分初始化和未初始化数据段)、堆和栈。不使用动态分配定义一个变量,这个变......
  • c#和c++数据交互二
    1:新建c++模板,生成类型动态库2:c++里类型点击查看代码classA{public: inta; };typedefstruct{ intup; intdown; charinfos[4]; //LPWSTRinfos;}info,*LPinfo;3:c++声明动态库方法点击查看代码#defineCVAPIextern"C"__declspec(dll......
  • C++:命名空间与输入输出
    目录前言一、命名空间1.1namespace的价值1.2namespace的定义1.3命名空间的使用二、C++输入&输出前言   C++是一种面向对象的计算机程序设计语言,‌它扩展了C语言的功能,‌并引入了面向对象编程的概念,‌如类、‌继承和多态等,C++是以C语言为基础进行了拓展与创新,C......
  • 在K8S中,Kube-Proxy为什么使用ipvs,而不使用iptables?
    Kubernetes中的kube-proxy是负责实现服务(Services)负载均衡的核心组件之一。它支持两种主要的代理模式:iptables模式和ipvs模式。这两种模式都可以用来实现服务的网络流量转发,但它们之间存在一些关键的区别。1.为什么使用ipvs而不是iptables?性能优势:连接跟踪:ipvs直......
  • c#和C++数据交互 一CLR篇
    1:配置VC++目录:包含目录:头文件的所在路径,#include时用“”链接器:输入:附加依赖项如果是clr模板,一定要用lib文件,不然会报链接错误2:先建立一个简单的dll模板,实现加法运算点击查看代码NativeCalculate.hclass__declspec(dllexport)NativeCalculate{public: ......