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");
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值