C API-调用LUA函数

lua_pcall 函数

lua_pcall 可以执行lua代码 前面的例子中load时就执行了lua脚本或者lua编译文件

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

nargs: 待调用函数的参数数量
nresults: 期望的结果个数
errfunc: 处理错误函数的索引

就像 settop函数的赋值一样,lua_pcall 会根据要求的数量来调整实际参数,即压入nil或者丢弃多余的结果。压入一个结果前,lua_pcall会向删除栈中的函数以及参数。如果一个函数有多个返回值,那么第一个结果最先入栈。

如果lua_pcall在运行时有任何错误,lua_pcall会返回一个非零值,并且在栈中压入一条错误消息。不过即使如此,它仍然会弹出函数以及参数。然而,在压入错误消息前,如果存在一个错误处理函数,lua_pcall会调用它。通过lua_pcall的最后一个参数可以指定错误处理函数。0表示没有错误处理函数,那么最终的消息就是原来的错误消息。如果传入非零值,那么这个参数就应该时一个处务处理函数在栈中的索引,因此,错误处理函数必须先压入栈中,也就是必须位于待调用函数机器参数的下面,先其入栈。

对于一个普通的错误,lua_pcall返回错误代码LUA_ERRRUN。担忧两种特殊的错误情况,不会运行错误处理函数。第一种时内存分配错误,这类错误lua_pcall总是返回LUA_ERRMEM。第二类错误发生在lua运行错误处理函数时,在这种情况没有必要再次调用错误处理函数,因此lua_pcall会立即返回LUA_ERRERR

代码示例:
load_func.lua

function f (x, y) 
       return (x^2 * math.sin(y)) / (1-x)
end

main.cc

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

#ifdef __cplusplus
extern "C" {
#include "lua.h"
#include "lauxlib.h"
#include "lualib.h"
}

#endif // __cplusplus

static void stack_dump(lua_State *L) {
    int i;
    int top = lua_gettop(L);//
    printf("stack len:%d  ", top);
    for (i = 1; i <= top; i++) {
        int t = lua_type(L, i);
        switch (t) {
        case LUA_TSTRING: {
            printf("'%s'", lua_tostring(L, i));
            break;
        }
        case LUA_TBOOLEAN: {
            printf(lua_toboolean(L, i) ? "true" : "false");
            break;
        }
        case LUA_TNUMBER: {
            printf("%g", lua_tonumber(L, i));
            break;
        }
        default:
            printf("%s", lua_typename(L, t));
            break;
        }
        printf("  ");
    }
    printf("\n");
}


void error(lua_State *L, const char* fmt, ...) {
    va_list argp;
    va_start(argp, fmt);
    vfprintf(stderr, fmt, argp);
    va_end(argp);
    lua_close(L);
    exit(EXIT_FAILURE);
}

double f(lua_State* L, double x, double y) {
    double z;
    //压入函数和参数
    lua_getglobal(L, "f"); //待调用的函数
    lua_pushnumber(L, x); //压入第一个参数
    lua_pushnumber(L, y); //压入第二个参数
    stack_dump(L);
    //完成调用 (2个参数  1个结果) 执行之后,压入的变量会被弹出
    if (lua_pcall(L, 2, 1, 0) != 0) {
        error(L, "error running function 'f' :%s \n", lua_tostring(L, -1));
    }
    stack_dump(L);
    //检索结果
    if (!lua_isnumber(L, -1)) {
        error(L, "error running function 'f' must return a number :%s \n", lua_tostring(L, -1));
    }

    z = lua_tonumber(L, -1);// 弹出结果
    lua_pop(L, 1); //把结果 以及压入的函数和参数弹出
    stack_dump(L);
    return z;
}

void load(lua_State* L, const char* fname) {
    if (luaL_loadfile(L, fname) || lua_pcall(L, 0, 0, 0)) {
        //luaL_loadfile\lua_pcall 发生错误,两个函数都会把错误消息压入栈,并返回一个非零的错误代码,可以通过lua_tostring获得错误信息
        error(L, "error cannot run config  file:%s\n", lua_tostring(L, -1));
    }
    
}

int main() {
    lua_State* L = luaL_newstate();
    luaL_openlibs(L); //打开标准库  lualib.h
        
    load(L, "./load_func.lua");

    double x = 2.5f;
    double y = 3.0f;
    double z = 0.0f;
    z = f(L, x, y);
    printf("function f result is %g \n", z);

    lua_close(L);
    system("pause");
}
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • Lua 5.1 参考手册 by Roberto Ierusalimschy, Luiz Henrique de F...
    苏黎九歌阅读 14,008评论 0 38
  • 原文地址:C语言函数调用栈(一)C语言函数调用栈(二) 0 引言 程序的执行过程可看作连续的函数调用。当一个函数执...
    小猪啊呜阅读 4,753评论 1 19
  • 第一篇 语言 第0章 序言 Lua仅让你用少量的代码解决关键问题。 Lua所提供的机制是C不擅长的:高级语言,动态...
    testfor阅读 2,766评论 1 7
  • 当在Lua和C之间交换数据时主要的问题是自动回收与手动回收内存管理的不一致。因此,Lua 用一个抽象的栈在Lua与...
    luffier阅读 2,707评论 0 3
  • lua语言的功能就不用过多的描述,详细的可以去找相关的lua书籍去看看!这里主要说的是c++和lua相互调用的情况...
    David_Longzy阅读 1,736评论 0 2