Lua程序设计笔记之七: lua与c互调

5 篇文章 0 订阅
这篇博客探讨了Lua程序设计中的C-Lua交互,包括从C调用Lua的table操作,如读取、写入及创建新table,并通过lua_setglobal和lua_getglobal管理全局变量。同时,介绍了如何从Lua中调用C函数,强调了C函数的注册、参数获取与返回值处理。C函数通过lua_CFunction原型定义,并用lua_pushcfunction进行注册。
摘要由CSDN通过智能技术生成

一. 扩展应用程序,从C中调用lua,lua的一个重要用途就是作为一种配置语言;

1. table操作:

1). 读取操作:Lua API只提供了一个函数lua_gettable,它能处理所有的类型,但它需要知道table在栈中的位置,然后才会在栈中弹出key,并压入相应的value。由于经常需要使用字符串来索引table,在lua5.1中,提供了一个lua_gettable的特化版本lua_getfield。

2). 写入操作:lua_settable能处理各种类型,它会从栈中获取所需的操作数。lua_settable要求传入一个table索引参数,然后它会设置这个table,并弹出key和value。Lua5.1同样为字符串key提供了一个lua_settable的特化版本,名为lua_field.下面是一段是lua配置的实例代码,第一段是lua代码,第二段是c代码

background = {r = 0.3, g = 0.4 , b = 0.5}

#include <stdio.h>
#include "lua.h"
#include "lauxlib.h"

static void stackDump(lua_State *L)
{
	int i;
	int top = lua_gettop(L);
	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");
}

#define MAX_COLOR 255

int getfield (lua_State * L, const char *key)
{
	int result;
	lua_pushstring(L, key);
	lua_gettable(L, -2);
	if (!lua_isnumber(L, -1)) printf("lua_isnumber invalid\n");
	result = (int)(lua_tonumber(L, -1)*MAX_COLOR);
	stackDump(L);
	lua_pop(L, 1); // 删除数字
	stackDump(L);
	
	printf("result: %d\n", result);
	
	return result;
}

int main(void)
{
	lua_State *L = luaL_newstate();
	
	if (luaL_loadfile(L, "tabletest.lua") || lua_pcall(L, 0, 0, 0)) printf("error");
	
	lua_getglobal(L, "background");
	if (!lua_istable(L, -1)) printf("error");
	
	int red = getfield(L, "r");
	int green = getfield(L, "g");
	int blue = getfield(L, "b");
	
	printf("r: %d, g: %d b: %d",red, green,blue);
	
	return 0;
}

3). 使用lua_newtable来创建一个空的table,并将其压入栈中。

lua_setglobal从栈中弹出一个值,并根据名称将其赋予全局变量

lua_getglobal根据名称将全局变量取出,并放入到栈中

===================================================

二. 从Lua中调用C:

1. lua能调用C函数,但并不意味着可以调用任意的C函数。对于一个能被lua调用的C函数,它必须遵循一个获取参数和返回结果的协议。此外,还必须注册C函数,以便用某种适当的方式将函数地址告诉lua。

当lua调用c函数时,也使用了一个与C调用lua时相同的栈。C函数从栈中获取函数参数,并将结果压入到栈中。为了将在栈中将函数结果与其他值区分开,C函数还应该返回其压入栈中的结果数量。

栈不是一个全局性的结构,每个函数都有自己的局部私有栈。当Lua调用一个C函数时,第一个参数总是这个局部栈的索引1。即使这个C函数调用了Lua代码,并且Lua代码又调用了相同的C函数,这些C函数调用只看到自己的私有栈,他们的第一个参数都是索引1。

2. 所有注册到Lua中的函数都具有相同的原型,该函数的原型定义在lua.h中的lua_CFunction:

typedef int (*lua_CFunction) (lua_State *L)

这个C函数仅有一个表示Lua状态的参数。它返回一个整数,表示其压入栈中的返回值数量。这个函数无需在压入结果前清空栈。在它返回后,Lua会自动删除栈中结果之下的内容。

3. 在lua使用这个函数之前,必须注册这个函数的。可以用lua_pushcfunction来进行注册,这个函数要求传入一个指向C函数的指针,它会在Lua中创建一个“函数”类型的值,该值就表示这个C函数。当注册完成后,这个C函数就具有了与其他Lua函数一样的行为。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值