C++与LUA相互调用

c++调用lua

创建一个state

// -- 函数原型: 
lua_State *luaL_newstate (void);

创建一个新的 Lua 状态机。 它以一个基于标准 C 的 realloc 函数实现的内存分配器 调用 lua_newstate 。 并把可打印一些出错信息到标准错误输出的 panic 函数(参见 §4.6) 设置好,用于处理致命错误。

返回新的状态机。 如果内存分配失败,则返回 NULL

lua_State *L = luaL_newstate();

使用完之后要调用:

lua_close(L);

运行脚本

// -- 函数原型: 
int luaL_dofile (lua_State *L, const char *filename);

加载并运行指定的文件。相当于:

luaL_loadfile(L, filename) && lua_pcall(L, 0, LUA_MULTRET, 0)

如果没有错误,函数返回假; 有错则返回真。

获取某个变量的值

// -- 函数原型: 
int lua_getglobal (lua_State *L, const char *name);

把全局变量 name 里的值压栈,返回该值的类型。

示例:

// -- test.lua

mystr = "hello world"
my_table = {name = "yxli8", id = 123456}

function a_add_b(a,b)
	return a+b
end

// -- c++

lua_getglobal(L, "mystr"); 
std::string str = lua_tostring(L, -1); 

获取table 表中的值

方法一:

// -- 函数原型: 
int lua_gettable (lua_State *L, int index);

t[k] 的值压栈, 这里的 t 是指索引指向的值, 而 k 则是栈顶放的值。

这个函数会弹出堆栈上的键,把结果放在栈上相同位置。 和在 Lua 中一样, 这个函数可能触发对应 “index” 事件的元方法 (参见 §2.4 )。返回压入值的类型。

示例:

lua_getglobal(L, "my_table") // <== push my_table

lua_pushstring(L, "name");   // <== my_table = {name= 123,fullname="asdfasdf"}
// --或者
lua_pushnumber(L, 1)        // <== my_table = {123123,"asdfasdf","sdfas"}
    
lua_gettable(L, -2)         // <== pop key 1, push mytable[1]
    
const char *name = lua_tostring(L, -1); //在栈顶取出数据
printf("name:%s\n", name);

另一:

// -- 函数原型: 可以获取字符串键 (my_table = {name= 123,fullname="asdfasdf"})
int lua_getfield (lua_State *L, int index, const char *k);

t[k] 的值压栈, 这里的 t 是索引指向的值。 在 Lua 中,这个函数可能触发对应 “index” 事件对应的元方法 (参见 §2.4 )。函数将返回压入值的类型。

示例:

lua_getglobal(L, "my_table");
lua_getfield(L, -1, "name");
str = lua_tostring(L, -1);
cout << "table:name=" << str << endl;

lua_getglobal(L, "my_table");
lua_getfield(L, -1, "id");
int nNumber = lua_tonumber(L, -1);
cout << "table:id=" << nNumber << endl;

另二:

// -- 函数原型: 可以获取数值键 (my_table = {123,"asdfasdf")
int lua_rawgeti (lua_State *L, int index, lua_Integer n);

t[n] 的值压栈, 这里的 t 是指给定索引处的表。 这是一次直接访问;就是说,它不会触发元方法。

返回入栈值的类型。

示例:

lua_getglobal(L, "my_table") <== push my_table
lua_rawgeti(L, -1, 2)       <== push my_table[2],作用同下面注释的两行调用
const char * str = lua_tostring(L, -1);

//lua_pushnumber(L, 2)      <== push key 1
//lua_rawget(L,-2)          <== pop key 1, push my_table[2]

调用lua中的函数

// -- 函数原型: 
int lua_pcall (lua_State *L, int nargs, int nresults, int msgh);

以保护模式调用一个函数。

要调用一个函数请遵循以下协议: 首先,要调用的函数应该被压入栈; 接着,把需要传递给这个函数的参数按正序压栈; nargs 是你压入栈的参数个数。 nresults 是返回值个数。

如果 msgh 是 0 , 返回在栈顶的错误消息就和原始错误消息完全一致。 否则, msgh 就被当成是 错误处理函数 在栈上的索引位置。 (在当前的实现里,这个索引不能是伪索引。) 在发生运行时错误时, 这个函数会被调用而参数就是错误消息。 错误处理函数的返回值将被 lua_pcall 作为错误消息返回在堆栈上。

典型的用法中,错误处理函数被用来给错误消息加上更多的调试信息, 比如栈跟踪信息。 这些信息在 lua_pcall 返回后, 由于栈已经展开,所以收集不到了。

lua_pcall 函数会返回下列常数 (定义在 lua.h 内)中的一个:

  • LUA_OK (0): 成功。
  • LUA_ERRRUN: 运行时错误。
  • LUA_ERRMEM: 内存分配错误。对于这种错,Lua 不会调用错误处理函数。
  • LUA_ERRERR: 在运行错误处理函数时发生的错误。
  • LUA_ERRGCMM: 在运行 __gc 元方法时发生的错误。 (这个错误和被调用的函数无关。)

调用示例:

// -- c++
lua_getglobal(L, "a_add_b");
lua_pushnumber(L, 10); // 将参数压入栈 a
lua_pushnumber(L, 20); // 将参数压入栈 b
int iRet = lua_pcall(L, 2, 1, 0);

// 判断调用返回值
if (iRet)
{
    const char* pErrorMsg = lua_tostring(L, -1);
    cout << pErrorMsg << endl;
    lua_close(L);
    return -1;
}
	
// 获取结果
if (lua_isnumber(L, -1))
{
    double fValue = lua_tonumber(L, -1);
    cout << "a + b = " << fValue << endl;
}

-- test.lua

function a_add_b(a,b)
	return a+b
end

清空虚拟栈

// -- 函数原型:
void lua_settop (lua_State *L, int index);

参数允许传入任何索引以及 0 。 它将把堆栈的栈顶设为这个索引。 如果新的栈顶比原来的大, 超出部分的新元素将被填为 nil 。 如果 index 为 0 , 把栈上所有元素移除

加载标准库

void luaL_openlibs (lua_State *L);

打开指定状态机中的所有 Lua 标准库。 或者宿主程序也可以用 luaL_requiref 分别打开这些库: luaopen_base (基础库), luaopen_package (包管理库), luaopen_coroutine (协程库), luaopen_string (字符串库), luaopen_utf8 (UTF8 库), luaopen_table (表处理库), luaopen_math (数学库), luaopen_io (I/O 库), luaopen_os (操作系统库), luaopen_debug (调试库)。 这些函数都定义在 lualib.h 中。

lua调用c++函数

// -- 函数原型:
void lua_register (lua_State *L, const char *name, lua_CFunction f);

把 C 函数 f 设到全局变量 name 中。 它通过一个宏定义

#define lua_register(L,n,f) (lua_pushcfunction(L, f), lua_setglobal(L, n))

示例:

// --test.c
#include <stdio.h>
#include <string.h>
#include <iostream>

extern "C"
{
#include <lua.h>
#include <lualib.h>
#include <lauxlib.h>
}
using namespace std;
lua_State* L;//C++与Lua的通信机制

int Average(lua_State *L)
{
	//code3   lua_gettop是取出栈顶的索引值。此时栈顶的索引值大小就是站内元素的个数
	int n = lua_gettop(L);
	double sum = 0;
	//code4 使用循环变量站内所有的元素,通过lua_tonumber取出栈内的值,然后进行相加操作。
	for (int i = 1; i <= n; ++i)
		sum += lua_tonumber(L, i);
	//code5 将运算后的值返还给Lua。把要返回的值再压入栈。此时此时栈内7条数据
	lua_pushnumber(L, sum / n); // 第一个返回值 average 
	lua_pushnumber(L, sum); // 第二个返回值 的 sum
	//code6 告诉lua主程序,返回2个值。lua这是可以用参数接受这两个值
	return 2;

}

int main()

{
	L = luaL_newstate();
	luaL_openlibs(L);
	//code1 lua_register注册函数把Lua函数和C++函数进行绑定。其实就是先用lua_pushcfunction把在c++中定义的函数压如栈中,然后lua_setglobal来设置栈顶的元素对应的值,这样就可以把lua函数和栈顶的c++函数建立引用关系。
	lua_register(L, "average", Average);
	//code2  加载并执行lua脚本,此时lua中的函数average被执行,同时向栈中压如5个参数。
	luaL_dofile(L, "test.lua");
	lua_close(L);
	printf("Press enter to exit...");
	getchar();
	return 0;
}


-- test.lua
avg, sum = average(10,20,30,40,50);
print("The average is ", avg)
print("The sum is ", sum)

参考学习:http://blog.csdn.net/shun_fzll/article/details/39120965

  • 21
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值