您的位置:首页 > 编程语言 > Lua

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

2013-07-15 23:31 302 查看
一. 扩展应用程序,从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函数一样的行为。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: