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 
#include 
#include 

#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");
}

你可能感兴趣的:(C API-调用LUA函数)