lua_pcall() 函数是 C API 接口,用来和 lua 进行交互的函数,其原型为:

int lua_pcall (lua_State *L, int nargs, int nresults, int msgh);

nargs: 表示参数个数,即你向栈中压入的参数个数。

nresults: 返回值个数,如果有返回值,则 lua 会按这个数量将返回值压入栈中。

msgh: 如果是 0 则表示要调用的函数如果出错了,则出错信息返回压入栈顶,非 0 时,则表示处理出错的函数在栈中的 index。

返回值:

/* thread status */
#define LUA_OK      0
#define LUA_YIELD   1
#define LUA_ERRRUN  2
#define LUA_ERRSYNTAX   3
#define LUA_ERRMEM  4
#define LUA_ERRERR  5

有如下代码,需要调用 lua 里的 parseData 函数,但这个函数里有一个错误,即:COM.lua_func(12, 23, 45);  因为没给 lua_func 赋过值,所以这里调用会失败。调用 lua 里的语句如果出错,则哪里出错就从哪里返回了。

我们先看最后一个lua_pcall() 最后一个参数是 0 的情况:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>#ifdef __cplusplus
extern "C" {
#include <lauxlib.h>
#include <lua.h>
#include <lualib.h>
}
#endif/* 将要注册给Lua 的函数, 定义Lua 传回三个数值 */
int LuaFunc(lua_State *L)
{if(lua_gettop(L) != 3){printf("lua send back para is not correct.\n");return 1;}int ret1 = (int)lua_tonumber(L, -3);int ret2 = (int)lua_tonumber(L, -2);int ret3 = (int)lua_tonumber(L, -1);printf("Line: %d, Lua send back  %d, %d, %d\n", __LINE__, ret1, ret2, ret3);return 0;
}int errFunc(lua_State* L)
{printf("error handler, top type = %d\n", lua_type(L, -1));char buf[128] = {0};if(LUA_TSTRING == lua_type(L, -1)){memcpy(buf, lua_tostring(L, -1), sizeof(buf));printf("get error from lua: %s\n", buf);}
}int main()
{lua_State *L = luaL_newstate();luaL_openlibs(L);if(luaL_loadfile(L, "parse.lua")){printf("load file: parse.lua faild...\n");lua_close(L);return 1;}lua_pcall(L, 0, 0, 0); /* 前面这几步都基本固定 */lua_getglobal(L, "COM");         /* 先找到表 */if(lua_type(L, -1) != LUA_TTABLE)    {printf("can not find table: COM \n");lua_close(L);return 1;}// lua_pushstring(L, "lua_func");    /* 注册函数 */// lua_pushcfunction(L, LuaFunc);    /* 往表 COM 里设置了COM[key] = value, 即 COM["lua_func"] = LuaFunc */// lua_settable(L, -3);lua_getglobal(L, "parseData");if(lua_type(L, -1) != LUA_TFUNCTION){printf("can not find function: parseData.\n");lua_close(L);return 1;}lua_pushstring(L, "C Call Lua function");int ret = lua_pcall(L, 1, 0, 0);printf("ret = %d, top type: %d\n", ret, lua_type(L, -1));char errStr[128] = {0};memcpy(errStr, lua_tostring(L, -1), sizeof(errStr));printf("get err: %s\n", errStr);lua_close(L);return 0;
}
--定义了一个全局表
COM = {}function parseData(str)print("From c/c++ str: "..str);COM.lua_func(12, 23, 45);COM.lua_var = "changed in lua";
end

出错时,直接从栈顶获取出错信息。如果要添加出错处理函数呢,该怎么处理呢?如下:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>#ifdef __cplusplus
extern "C" {
#include <lauxlib.h>
#include <lua.h>
#include <lualib.h>
}
#endif/* 将要注册给Lua 的函数, 定义Lua 传回三个数值 */
int LuaFunc(lua_State *L)
{if(lua_gettop(L) != 3){printf("lua send back para is not correct.\n");return 1;}int ret1 = (int)lua_tonumber(L, -3);int ret2 = (int)lua_tonumber(L, -2);int ret3 = (int)lua_tonumber(L, -1);printf("Line: %d, Lua send back  %d, %d, %d\n", __LINE__, ret1, ret2, ret3);return 0;
}int errFunc(lua_State* L)
{printf("error handler, top type = %d\n", lua_type(L, -1));char buf[128] = {0};if(LUA_TSTRING == lua_type(L, -1)){memcpy(buf, lua_tostring(L, -1), sizeof(buf));printf("get error from lua: %s\n", buf);}
}int main()
{lua_State *L = luaL_newstate();luaL_openlibs(L);if(luaL_loadfile(L, "parse.lua")){printf("load file: parse.lua faild...\n");lua_close(L);return 1;}lua_pcall(L, 0, 0, 0); /* 前面这几步都基本固定 */lua_pushcfunction(L, errFunc);lua_getglobal(L, "COM");         /* 先找到表 */if(lua_type(L, -1) != LUA_TTABLE)    {printf("can not find table: COM \n");lua_close(L);return 1;}// lua_pushstring(L, "lua_func");    /* 注册函数 */// lua_pushcfunction(L, LuaFunc);    /* 往表 COM 里设置了COM[key] = value, 即 COM["lua_func"] = LuaFunc */// lua_settable(L, -3);lua_getglobal(L, "parseData");if(lua_type(L, -1) != LUA_TFUNCTION){printf("can not find function: parseData.\n");lua_close(L);return 1;}lua_pushstring(L, "C Call Lua function");int ret = lua_pcall(L, 1, 0, -4);printf("ret = %d, top type: %d\n", ret, lua_type(L, -1));lua_close(L);return 0;
}

代码中两处不一样:1)添加处理函数:lua_pushcfunction(L, errFunc);  2)lua_pcall 函数指定处理函数在栈中的 index = -4,这里为什么是 -4 呢?因为这个函数是最先入栈的,然后是 “COM” 的值,接着是 “parseData” 的值,最后是参数 “C Call Lua function”,所以从栈顶开始它是 -4 的位置,其执行结果为:

lua_pcall 函数详解相关推荐

  1. C语言网络编程:accept函数详解

    文章目录 前言 函数描述 代码实例 如何得到客户端的IP 和 端口号 前言 当使用tcp服务器使用socket创建通信文件描述符,bind绑定了文件描述符,服务器ip和端口号,listen将服务器端的 ...

  2. 【FFmpeg】函数详解(三)

    FFmpeg函数详解 14.av_write_frame 15.av_interleaved_write_frame 16.av_write_trailer 17.avio_close 18.av_i ...

  3. 【FFmpeg】函数详解(二)

    FFmpeg函数详解 9.av_dump_format 10.avio_open 11.avformat_write_header 12.avcodec_send_frame 13.avcodec_r ...

  4. 【FFmpeg】函数详解(一)

    FFmpeg函数详解 一.错误码相关 1.AVERROR 2.av_strerror 3.其他错误码解释 二.编解码 1.获取编解码器 2.申请.释放上下文环境 3.打开编码器avcodec_open ...

  5. 【ES6】Generator函数详解

    [ES6]Generator函数详解 一.Generator函数简介 基本概念 函数写法 yield关键字介绍 二.next方法的参数 三.for...of循环 四.关于普通throw()与Gener ...

  6. mysql的聚合函数综合案例_MySQL常用聚合函数详解

    一.AVG AVG(col) 返回指定列的平均值 二.COUNT COUNT(col) 返回指定列中非NULL值的个数 三.MIN/MAX MIN(col):返回指定列的最小值 MAX(col):返回 ...

  7. python平方数迭代器_对python中的高效迭代器函数详解

    python中内置的库中有个itertools,可以满足我们在编程中绝大多数需要迭代的场合,当然也可以自己造轮子,但是有现成的好用的轮子不妨也学习一下,看哪个用的顺手~ 首先还是要先import一下: ...

  8. python基础知识~ 函数详解2

    python~函数详解2  1 生成器函数    定义 如果函数有yield这个关键字,就是生成器函数.生成器函数() 获取的是生成器,不执行函数   须知 yield和return一样,都可以返回数 ...

  9. scanf函数详解与缓冲区

    1.基本信息 函数原型: int scanf( char *format, args, ...); 函数返回值: 读入并赋给args的数据个数,遇到文件结束返回EOF,出错返回0. 函数功能: sca ...

最新文章

  1. epoll_wait被signal信号中断时的处理
  2. Android Studio 错误: 非法字符: #39;\ufeff#39; 解决方式|错误: 须要class, interface或enum...
  3. 上海的互联网数据中心“一柜难求
  4. 此情应是长相守 你若无心我便休
  5. e3是合法浮点数吗_下列哪些是不合法的浮点数的选项是 123 2e4.2 .e5 -e3 .234 1e3
  6. mpvue小程序以及微信直播踩坑总结
  7. 4月1日被愚了吗,我就看看你们都比较都喜欢哪些教程?
  8. ananconda3安装(python3.8)
  9. 如何在原有的cookie里面添加值_【平面设计教程】如何创建一个漂亮又好吃的饼干呢?...
  10. 【源码】VB6聊天机器人
  11. 电信iptv机顶盒破解方法大全(图文教程)
  12. Matlab编程基础
  13. VBAProject密码清除 for EXCEL2003
  14. 基于WinPcap的网络流量在线分析系统的设计与实现
  15. 1000瓶水里面有一瓶毒水,通过用兔子去喝水的方式检验,只能让兔子喝一次水,那么最少用多少只兔子检验出来是哪一瓶?
  16. Apple Pay 究竟是什么
  17. pymongo 基本操作
  18. window的onload事件的用法
  19. java super父类的父类_java super关键字,super访问父类成员详解
  20. 一线大厂面试官问:你真的懂电商订单开发吗?

热门文章

  1. coures包下载和安装 可解决报错ImportError: No module named '_curses'
  2. Linux病毒扫描工具ClamAV安装使用
  3. 常用字符串API实现(笔试会考)
  4. 高中计算机学什么软件,高中学业水平考试的计算机上机考试考的是啥软件
  5. ucweb7.0 for WM/PPC/SP/S60V1/S60V2/S60V3/S60V5/ 平台安装包下载
  6. java后台 重置手机密码(邮箱点击确认)
  7. css3彩虹渐变色,css3渐变 彩虹条纹
  8. 如何选择适合自己的吉他弦(下)
  9. 12弦原声大吉他音源 Orange Tree Samples Evolution Jumbo 12 Kontakt
  10. 用NEON intrinsic实现RGB转YUV420SP(NV12)