lua学习笔记3-c调用lua

lua C api

PS:这里是默认我已经学完了lua脚本的基本知识(包括table,元表,函数,基本库, 文件io,库导入等等)

lua是c写的,无论是lua调用c还是c调用lua都非常容易,以下是基于文档做的一些学习笔记,在文档的索引可以快速找到api的名称方便参考,文档地址如下:
官网5.3文档:http://www.lua.org/manual/5.3/#index
中文文档:http://www.runoob.com/manual/lua53doc/contents.html#index

文档包括两部分,一部分是介绍lua的语法,以及一些注(keng)意(die)事项,比如其中说到空字符串和0都被认为是true,恩,要注意(MDZZ),感觉lua的强大之处在于他的table(手动咸鱼),下面开始修仙,下面通过问答的方式给自己学习lua做一些笔记,在此之前,先编译lua,我们到官网可以下载lua的源码

源码下载页面:http://www.lua.org/download.html
5.3源码下载:http://www.lua.org/ftp/lua-5.3.4.tar.gz

lua源码非常小,很容易编译,windows下,装个Mingw即可用make编译,以下是linux的

1.下载解压源码

wget http://www.lua.org/ftp/lua-5.3.4.tar.gz
tar -xzvf lua-5.3.4.tar.gz
~/local/lua/lua-5.3.4$ make
Please do 'make PLATFORM' where PLATFORM is one of these:
   aix bsd c89 freebsd generic linux macosx mingw posix solaris
See doc/readme.html for complete instructions.

上面提示指定编译选项,如果是windows下用Mingw的,就make -j12 mingw, -j12是多线程编译,分12个线程编译,现在是debian,可以选择posix,如果提示缺少一些库,使用apt-get 安装即可

make -j12 posix

编译成功后,在src文件生成一个lua(lua解释器),luac(lua脚本编译器),以及静态库liblua.a,c调用lua的时候,现在是用静态库,现在把以下文件复制到项目目录下
头文件:lua.h lualib.h lauxlib.h luaconf.h
静态库文件:liblua.a
我的项目目录为:~/project/lua
我把头文件放置在~/project/lua/include
静态库文件放在~/project/lua/lib

以下所有的操作都是在项目目录(用$PRO_HOME描述这个目录)


1.c是如何调用lua写的代码的?

1.首先了解,lua在c代码中是如何“工作”的,在c中要调用lua,首先我得创建一个lua状态机(lua_State)
文件$PRO_HOME/main.c

#include "lua.h"
#include "lualib.h"
#include "lauxlib.h"

int main(void)
{
  //创建一个lua状态机
  lua_State *L  = luaL_newstate();
  //销毁这货
  lua_close(L);
  return 0;
}

然后尝试编译这个源文件

$gcc -I ../include -c main.c
$gcc -lm -o main main.o ../lib/liblua.a

编译成功说明配置没有问题

c调用lua代码,首先要学会怎么把lua代码“翻译”成c的代码,先不着急如何把lua代码加载到lua状态机运行,先了解下它是怎么运行的,根据文档参考,写以下一段代码

-- a是一个全局变量
a="测试"
print(a)

a是一个全局变量,在lua中,无非在维护一个堆栈stack和一个环境表_G(暂时理解)
那么用c怎么写呢?
1.创建一个状态机(lua_State),加载基本库(luaL_openlibs())
2.把字符串“测试”压入堆栈(lua_pushstring)
3.把这个字符串弹出,设置为global,名称为a(lua_setglobal())
4.从全局变量中,把print函数压栈(lua_getglobal())
5.把参数a从全局变量中压栈(lua_getglobal())
6.调用lua_call执行函数

#include "lua.h"
#include "lualib.h"
#include "lauxlib.h"

int main(void)
{
    lua_State *L = luaL_newstate();
   //加载基本库(print在其中)
    luaL_openlibs(L);
    //这里相当于设置全局变量a="测试"
    lua_pushstring(L,"测试");
    lua_setglobal(L,"a");
    //print函数压栈
    lua_getglobal(L,"print");
    //参数压栈yiban
    lua_getglobal(L,"a");
    //调用函数,1个参数,0个返回值
    lua_call(L,1,0);
    lua_close(L);
    return 0;
}

小总结:

在lua 的 C api中,
数据类型有:
lua_Integer 整形
lua_Number 默认对应的是C double
lua_Unsigned 无符号整形

字符串、布尔型或者是lua的table之类的,都是不能直接“拿出来”的
如果要操作,设置某某某的变量,可以通过lua_pushxxxx来把对应的数据类型的变量的值压入堆栈,如果,要把变量设置为一个全局变量,就把它设置为global(lua_setglobal()),lua_setglobal会把栈顶的元素弹出,病设置到环境表,详情查看文档,

关于堆栈

lua的堆栈是lua自己实现的一个数据结构,并不是c语言执行时的那个堆栈,这个堆栈,由栈底往栈顶数,元素的序号是1 2 3 4 5...,这是它的绝对索引的方式,还有它支持负索引,也就是参考点是栈顶,而不是栈底,比如-1代表的是栈顶的元素,-2代表栈顶的下一个元素

对于堆栈的操作有:
1.获取栈顶的索引值,lua_gettop(L)(这个值,可以当做是栈元素个数)

2.把数据压栈(lua_pushxxx,根据压入的数据类型不一样,有对应有一系列的操作函数,例如,lua_pushstring(L,"测试"),把字符串压入,详情看文档lua_pushxxxx),又或者是

3.把堆栈的元素“读取”出来,lua_toxxxx,就可以不弹出堆栈中的数据,把它转换成c的数据类型,例如:lua_tolstring,注意,这个返回值是const类型,也就是说你不能对他进行更改,如果要做其他用途,你需要
把他copy出来

4.更改元素在堆栈中的位置

5.lua有垃圾回收机制GC,一般不用担心内存释放的问题


2.如何在lua状态机中执行一个c写的函数?

刚刚已经学了,如何在c中,“执行”lua,这个print函数他已经实现了,但是我们自己怎么实现一个函数,然后在lua中调用呢?
这个函数可以是
1.lua写的函数
2.c写的可以让lua识别的函数
我们先来搞第二种,程序还是在原来的基础上进行扩充

我们把print换成我们自己实现的一个函数,这个函数在lua里叫print2,它比较简单,只能接受一个参数,不做任何检查,也不做任何的错误的处理

lua注册的函数的类型是:
static int fun(lua_State *L);
返回值是这个函数的返回值个数(因为lua支持多个返回值,执行完毕后,把返回值依次压栈,然后返回返回值个数就行了),调用结束后,堆栈中剩下的是fun的返回值(如果有返回值,并且按照顺序压栈)

#include "lua.h"
#include "lualib.h"
#include "lauxlib.h"

static int print2(lua_State *L)
{
   const char * s = luaL_optlstring (L,1,"啥都没",NULL);  //获取函数调用时第1个参数为字符串,如果参数不存在或者是nil就返回“啥都没”,并且把长度放在第四个参数(这里设置为NULL,不获取长度),
  printf("这是:%s\n",s);
  return 0;  //返回值个数为0
}

int main(void)
{
    lua_State *L = luaL_newstate();
    luaL_openlibs(L);      //加载基本库(print在其中)
    //这里相当于设置全局变量a=image.png"测试"
    lua_pushstring(L,"测试");
    lua_setglobal(L,"a");
  
  //注册这个函数到全局表 
    lua_register(L,"print2",print2);

    lua_getglobal(L,"print2");      //把这个函数从全局表中压栈
    lua_getglobal(L,"a");         //参数压栈
    lua_call(L,1,0);         //调用函数,1个参数,0个返回值
    lua_close(L);          //关闭状态机
    return 0;
}

未完待续

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 214,313评论 6 496
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,369评论 3 389
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 159,916评论 0 349
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,333评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,425评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,481评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,491评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,268评论 0 269
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,719评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,004评论 2 328
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,179评论 1 342
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,832评论 4 337
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,510评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,153评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,402评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,045评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,071评论 2 352

推荐阅读更多精彩内容

  • 原文地址:C语言函数调用栈(一)C语言函数调用栈(二) 0 引言 程序的执行过程可看作连续的函数调用。当一个函数执...
    小猪啊呜阅读 4,599评论 1 19
  • 当在Lua和C之间交换数据时主要的问题是自动回收与手动回收内存管理的不一致。因此,Lua 用一个抽象的栈在Lua与...
    luffier阅读 2,644评论 0 3
  • 第一篇 语言 第0章 序言 Lua仅让你用少量的代码解决关键问题。 Lua所提供的机制是C不擅长的:高级语言,动态...
    testfor阅读 2,664评论 1 7
  • 1. 写在前面 很多时候我们都需要借助一些脚本语言来为我们实现一些动态的配置,那么就会涉及到如何让脚本语言跟原生语...
    杰嗒嗒的阿杰阅读 3,429评论 9 31
  • 昨天和孩子爸讨论了孩子教育的问题。 这次是有效的一次沟通。 孩子的爸爸比我,有耐心,我把孩子学过的和要预习的数学和...
    里娃阅读 124评论 0 0