lua与c之间交互详解(一)

lua与c之间交互是通过“lua堆栈”通信的。不管是lua调用c还是c调用lua,都是通过操作lua堆栈实现的。顾名思义,lua堆栈也满足后进先出的特点,入栈/出栈都围绕栈顶进行的。与通用的栈不同的是,这个虚拟栈每个位置都对应一个索引,可以通过索引操作指定位置的数据。1代表栈底,向栈顶依次递增;-1代表栈顶,向栈底依次递减,如图。

在这里插入图片描述

  1. lua中类型在c中如何表示
    要实现c和lua之间的交互,先了解下lua中基本类型与c中类型怎么对应的。lua中有八种基本类型:nil、boolean、number、string、table、function、userdata、thread,其中,userdata分轻量用户数据(lightuserdata)和完成用户数据(userdata)两种。这些类型都可以压入栈中,在c中统一用TValue结构表示,是一个{值,类型}结构。

在这里插入图片描述

(图片来自http://www.cnblogs.com/sevenyuan/p/4511808.html)

TValue->tt表示类型,类型定义在lua.h,nil为LUA_TNIL,boolean为LUA_TBOOLEAN等

// lua.h
#define LUA_TNIL                0
#define LUA_TBOOLEAN            1
#define LUA_TLIGHTUSERDATA      2
#define LUA_TNUMBER             3
#define LUA_TSTRING             4
#define LUA_TTABLE              5
#define LUA_TFUNCTION           6
#define LUA_TUSERDATA           7
#define LUA_TTHREAD             8

TValue->Value是个union:

int b:只存boolean类型,注:number类型并不存在这里,b只存boolean

lua_Number n:存放所有number类型

void *p:存放轻量用户数据类型(lightuserdata)

gcObject *gc:存放所有需要垃圾回收的类型,是一个指向union GCObject的指针,通过GCObject可以看到其包含string、userdata、closure、table、proto、upvalue、thread

由此可知,nil、boolean、number、lightuserdata类型是把数据本身直接存在栈里,和lua的垃圾回收无关;而GCObject表示的类型是把数据的内存地址(即指针)存在栈里的,当生命周期结束需要垃圾回收释放内存。

  1. 对堆栈的基本操作
    luaL_newstate:创建一个状态机,
    lua_close:关闭状态机
#include <stdio.h>

#include <lua.h>
#include <lauxlib.h>
#include <lualib.h>

int main(int argc, char *argv[]){
    lua_State *L = luaL_newstate(); //创建一个状态机

    lua_pushnil(L); //nil
    int type = lua_type(L, -1);
    printf("nil type = %d\n", type);
    if(lua_isnil(L, -1)){
        printf("------nil-----\n");
    }

    lua_pushboolean(L, 0); //boolean
    type = lua_type(L, -1);
    printf("boolean type = %d\n", type);
    if(lua_isboolean(L, -1))
        printf("--------boolean------\n");

    lua_pushlightuserdata(L, NULL); //lightuserdata
    type = lua_type(L, -1);
    printf("lightuserdata type = %d\n", type);
    if(lua_islightuserdata(L, -1))
        printf("--------lightuserdata------\n");

    lua_pushnumber(L, 10); //number
    type = lua_type(L, -1);
    printf("number type = %d\n", type);
    if(lua_isnumber(L, -1))
        printf("--------number------\n");

    lua_pushstring(L, "string"); //string
    type = lua_type(L, -1);
    printf("string type = %d\n", type);
    if(lua_isstring(L, -1))
        printf("--------string------\n");

    lua_newtable(L); //table, 创建空表,并压入栈
    type = lua_type(L, -1);
    printf("table type = %d\n", type);
    if(lua_istable(L, -1))
        printf("--------table------\n");

    lua_newuserdata(L, 1024); //userdata, 分配1024大小的内存块,并把内存地址压入栈
    type = lua_type(L, -1);
    printf("userdata type = %d\n", type);
    if(lua_isuserdata(L, -1))
        printf("--------userdata------\n");

    lua_pushthread(L); //thread, 创建一个lua新线程,并将其压入栈。lua线程不是OS线程
    type = lua_type(L, -1);
    printf("thread type = %d\n", type);
    if(lua_isthread(L, -1))
        printf("--------thread------\n");

    lua_close(L); //关闭状态机
    return 0;
}

lua_pushXXX:push*族api向栈顶压入数据,比如lua_pushnumber压入数值,lua_pushstring压入字符串,lua_pushcclosure压入c闭包。

lua_isXXX:is*族api判断栈里指定位置的索引是否是指定类型,比如,lua_istable(L,-1)判断栈顶位置的数据是否是表,lua_isuserdata(L,-1)判断栈顶位置的数据是否是用户数据等。

gcc -o main.o main.c /usr/local/lib/liblua.a -I/usr/local/include/ -lm -ldl
运行结果如下,对应lua.h中的类型定义。c与lua之间详细的api介绍参照
在这里插入图片描述

http://cloudwu.github.io/lua53doc/contents.html#contents

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值