微信登录

C 语言调用 Lua - 传递参数与获取返回值 - 数据交互

C 语言调用 Lua - 传递参数与获取返回值 - 数据交互

引言

Lua 是一种轻量级、高效的脚本语言,常被嵌入到 C/C++ 程序中,用于实现灵活的配置和扩展功能。在 C 语言中调用 Lua 脚本时,经常需要在 C 语言和 Lua 之间进行数据交互,包括传递参数给 Lua 脚本以及从 Lua 脚本获取返回值。本文将详细介绍如何在 C 语言中实现这些数据交互操作,并提供实用的示例代码。

Lua 栈

在深入了解数据交互之前,我们需要先了解 Lua 栈的概念。Lua 使用一个栈来实现 C 和 Lua 之间的数据交互。栈是一种后进先出(LIFO)的数据结构,C 语言通过操作这个栈来传递参数给 Lua 脚本,以及从 Lua 脚本获取返回值。

栈操作函数

Lua 提供了一系列函数来操作栈,以下是一些常用的栈操作函数:
| 函数名 | 功能 |
| —— | —— |
| lua_pushnumber(lua_State *L, lua_Number n) | 将一个数值压入栈顶 |
| lua_pushstring(lua_State *L, const char *s) | 将一个字符串压入栈顶 |
| lua_gettop(lua_State *L) | 返回栈顶元素的索引 |
| lua_pop(lua_State *L, int n) | 从栈顶弹出 n 个元素 |
| lua_tonumber(lua_State *L, int index) | 获取栈中指定索引位置的数值 |
| lua_tostring(lua_State *L, int index) | 获取栈中指定索引位置的字符串 |

传递参数给 Lua 脚本

示例:传递数值和字符串参数

以下是一个简单的 C 语言程序,用于传递一个数值和一个字符串参数给 Lua 脚本:

  1. #include <lua.h>
  2. #include <lauxlib.h>
  3. #include <lualib.h>
  4. #include <stdio.h>
  5. int main() {
  6. // 创建一个新的 Lua 状态机
  7. lua_State *L = luaL_newstate();
  8. // 打开所有标准 Lua 库
  9. luaL_openlibs(L);
  10. // 加载并执行 Lua 脚本
  11. if (luaL_dofile(L, "test.lua")!= 0) {
  12. fprintf(stderr, "Error: %s\n", lua_tostring(L, -1));
  13. return 1;
  14. }
  15. // 获取 Lua 函数
  16. lua_getglobal(L, "test_function");
  17. // 传递参数
  18. lua_pushnumber(L, 10); // 传递数值参数
  19. lua_pushstring(L, "Hello, Lua!"); // 传递字符串参数
  20. // 调用 Lua 函数,2 个参数,0 个返回值
  21. if (lua_pcall(L, 2, 0, 0)!= 0) {
  22. fprintf(stderr, "Error: %s\n", lua_tostring(L, -1));
  23. return 1;
  24. }
  25. // 关闭 Lua 状态机
  26. lua_close(L);
  27. return 0;
  28. }

对应的 Lua 脚本 test.lua 如下:

  1. function test_function(num, str)
  2. print("Received number: ".. num)
  3. print("Received string: ".. str)
  4. end

代码解释

  1. 创建 Lua 状态机:使用 luaL_newstate() 创建一个新的 Lua 状态机,并使用 luaL_openlibs() 打开所有标准 Lua 库。
  2. 加载并执行 Lua 脚本:使用 luaL_dofile() 加载并执行指定的 Lua 脚本。
  3. 获取 Lua 函数:使用 lua_getglobal() 获取 Lua 脚本中定义的函数。
  4. 传递参数:使用 lua_pushnumber()lua_pushstring() 将数值和字符串参数压入栈顶。
  5. 调用 Lua 函数:使用 lua_pcall() 调用 Lua 函数,第一个参数表示传递的参数个数,第二个参数表示期望的返回值个数。
  6. 关闭 Lua 状态机:使用 lua_close() 关闭 Lua 状态机。

从 Lua 脚本获取返回值

示例:获取数值和字符串返回值

以下是一个 C 语言程序,用于从 Lua 脚本获取一个数值和一个字符串返回值:

  1. #include <lua.h>
  2. #include <lauxlib.h>
  3. #include <lualib.h>
  4. #include <stdio.h>
  5. int main() {
  6. // 创建一个新的 Lua 状态机
  7. lua_State *L = luaL_newstate();
  8. // 打开所有标准 Lua 库
  9. luaL_openlibs(L);
  10. // 加载并执行 Lua 脚本
  11. if (luaL_dofile(L, "test.lua")!= 0) {
  12. fprintf(stderr, "Error: %s\n", lua_tostring(L, -1));
  13. return 1;
  14. }
  15. // 获取 Lua 函数
  16. lua_getglobal(L, "return_function");
  17. // 调用 Lua 函数,0 个参数,2 个返回值
  18. if (lua_pcall(L, 0, 2, 0)!= 0) {
  19. fprintf(stderr, "Error: %s\n", lua_tostring(L, -1));
  20. return 1;
  21. }
  22. // 获取返回值
  23. double num = lua_tonumber(L, -2); // 获取数值返回值
  24. const char *str = lua_tostring(L, -1); // 获取字符串返回值
  25. // 输出返回值
  26. printf("Received number: %f\n", num);
  27. printf("Received string: %s\n", str);
  28. // 关闭 Lua 状态机
  29. lua_close(L);
  30. return 0;
  31. }

对应的 Lua 脚本 test.lua 如下:

  1. function return_function()
  2. return 20, "Hello, C!"
  3. end

代码解释

  1. 创建和加载 Lua 脚本:与传递参数的示例相同。
  2. 获取 Lua 函数:使用 lua_getglobal() 获取 Lua 脚本中定义的函数。
  3. 调用 Lua 函数:使用 lua_pcall() 调用 Lua 函数,指定 0 个参数和 2 个返回值。
  4. 获取返回值:使用 lua_tonumber()lua_tostring() 从栈中获取数值和字符串返回值。注意,栈顶元素的索引为 -1,倒数第二个元素的索引为 -2。
  5. 输出返回值:将获取的返回值输出到控制台。
  6. 关闭 Lua 状态机:使用 lua_close() 关闭 Lua 状态机。

总结

通过 Lua 栈,我们可以方便地在 C 语言和 Lua 脚本之间进行数据交互。传递参数时,将参数依次压入栈顶;获取返回值时,从栈中取出相应的元素。在实际应用中,我们可以根据需要传递和获取不同类型的数据,实现更加复杂的功能。

希望本文能帮助你更好地理解 C 语言调用 Lua 时的数据交互操作。

C 语言调用 Lua - 传递参数与获取返回值 - 数据交互