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

avatar
作者
筋斗云
阅读量:0

  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 }

    广告一刻

    为您即时展示最新活动产品广告消息,让您随时掌握产品活动新动态!