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

  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
}

  • 8
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值