转自:http://foredoomed.org/blog/2013/12/07/integrate-c-with-lua/

我们在用C写程序的时候,很多情况下需要用到List,Map等集合,但是C是不原生支持这些数据结构的。碰到这种情况的话,要么自己实现一套API,要么就用别人写好的现成的类库。但是大多数情况下现有类库的API使用起来非常不舒服,自己写呢又重复造轮子,那有没有其他的办法呢?答案是肯定的。我们可以用Lua这个嵌入式脚本语言与C搭配使用,来弥补C这个古老语言的很多先天性的不足。

0.什么是Lua

引用Lua官网上的解释:

Lua is a powerful, fast, lightweight, embeddable scripting language.

Lua combines simple procedural syntax with powerful data description constructs based on associative arrays and extensible semantics. Lua is dynamically typed, runs by interpreting bytecode for a register-based virtual machine, and has automatic memory management with incremental garbage collection, making it ideal for configuration, scripting, and rapid prototyping.

Lua和Ruby,Python一样都是脚本语言,但是Lua还有其他脚本语言不具备的特性:Lua还是嵌入式的脚本语言。Lua脚本可以很容易的被 C/C++ 代码调用,也可以反过来调用C/C++的函数,这使得Lua在应用程序中可以被广泛应用。Lua由标准C编写而成,代码简洁优美,几乎在所有操作系统和平台上都可以编译,运行。一个完整的Lua解释器不过200k,在目前所有脚本引擎中,Lua的速度是最快的。

而且,Lua还有一个LuaJIT的项目,可以提供在特定平台上的即时编译功能,这将给Lua带来更加优秀的性能。

1.在C中执行Lua脚本

首先是C代码:

  1. #include "lua.h"
  2. #include "lauxlib.h"
  3. #include "lualib.h"
  4. int main(){
  5. lua_State *L = luaL_newstate(); /* opens Lua */
  6. luaL_openlibs(L); /* opens the standard libraries */
  7. luaL_dofile(L,"test.lua"); /* runs Lua script */
  8. lua_close(L);
  9. return 0;
  10. }

然后是Lua脚本:

  1. print("This is executed from C")

最后编译运行:

  1. $ gcc -o test test.c -I/usr/local/Cellar/lua/5.1.5/include -llua
  2. $ ./test
  3. This is executed from C

现在我们来详细看这段代码。首先我们要引入三个头文件lua.hlauxlib.hlualib.hlua.h中定义的是最基础的API,lauxlib.h中的函数都以luaL_开头,他们是比基础API更抽象的函数,lualib.h中定义了打开标准类库的API,比如luaL_openlibs(L)

程序开始用luaL_newstate()函数创建一个lua_Statelua_State中保存了Lua运行时的所有的状态信息(比如变量的值等),并且所有的Lua的C的API都有一个lua_newstate指针的参数。luaL_newstate函数会创建一个全新的Lua运行时状态,其中没有任何预先定义好的函数(包括最基本的print函数)。如果需要试用标准类库的话,只要调用luaL_openlibs(L)函数就打开标准类库就可以了。标准类库被分别封装在不同的包中,当你需要使用的时候再引入到代码中,这样做的好处是可以使Lua尽可能的小(嵌入式语言必须要小),从而可以方便嵌入到其他语言中去。当Lua运行时状态和标准类库都准备完成后,就可以调用luaL_dofile(L,"test.lua")函数来执行Lua脚本。运行结束后,需要调用lua_close(L)来关闭Lua运行时状态。

2.Lua和C的数据交换

当我们在C中调用Lua的API的时候(比如把变量保存在Lua的数据结构中),Lua需要读取并保存C的数据。但问题是C和Lua是两种不同的语言:前者是静态的,手动管理内存的语言;而后者是动态的,自动管理内存的语言,所以Lua在运行的时候维护了一个自己的stack用来和C做数据交换。这个stack中的每个槽可以是任意的Lua类型,当你需要从Lua中请求一个值而调用Lua的API的时候,这个值会被push到stack中去;当你想传值给Lua的时候,你必须先把这个值push到stack中去,然后再调用Lua的API。默认情况下Lua的stack有20格槽可以使用,任何时候push值到stack都必须保证stack是有可用空间的,所以如果程序有可能会使stack溢出的时候就需要调用lua_checkstack函数来检查stack的空间是否还有可用空间。

3.在C中使用Lua的table

Lua中的table是非常好用的数据结构,有点像Java里的Map。

C代码:

  1. #include <stdio.h>
  2. #include "lua.h"
  3. #include "lauxlib.h"
  4. #include "lualib.h"
  5. int main(){
  6. lua_State *L = luaL_newstate(); /* opens Lua */
  7. luaL_openlibs(L); /* opens the standard libraries */
  8. lua_newtable(L); /* creates a new table */
  9. lua_pushstring(L, "test");
  10. lua_pushstring(L, "Hello World");
  11. lua_settable(L, -3); /* t["test"] = "Hello World" */
  12. lua_pushstring(L, "test");
  13. lua_gettable(L, -2); /* pushes t["test"] onto the stack top */
  14. const char *str = lua_tostring(L, -1);
  15. printf("%s", str);
  16. lua_close(L);
  17. return 0;
  18. }

编译运行:

  1. $ gcc -o test test.c -I/usr/local/Cellar/lua/5.1.5/include -llua
  2. $ ./test
  3. Hello World

在C中试用Lua的table还是非常简单的,最主要的就是对stack的pop和push操作。上面这段代码首先会创建一个空的table并且push到stack中,然后再push两格字符串(一个作为key,一个作为value)到stack中。注意,Lua的下标是从1开始的,所以在调用lua_settable函数的时候,table的index值就是-3(从上往下数的index是负数)。lua_settable函数调用完成后会pop掉key和value,这样的话stack只剩下table,要取table里的值必须在push一遍key值,这样我们就能取到对应的value值了。

4.总结

如今Lua已经越来越多地被应用到与类C语言(C/C++/Objective C)配合开发,看重就是Lua小巧,速度快,动态语言的特性。使用Lua就可以为应用程序提供灵活的扩展和定制功能,极大地提高了应用程序的扩展性。

参考文档

[1] Lua 5.1 Reference Manual

C调Lua的更多相关文章

  1. Lua与C++互相调用(上)

    int main1(int argc, const char * argv[]) { lua_State* L = luaL_newstate();//创建栈 luaopen_base(L); lua ...

  2. Lua和C之间的交互

    转自:http://blog.csdn.net/sumoyu/article/details/2592693 (一) Lua 调C函数 什么样类型的函数可以被Lua调用   typedef int ( ...

  3. 解释型语言和编译型语言如何交互?以lua和c为例

    转自http://my.oschina.net/mayqlzu/blog/113528 问题: 最近lua很火,因为<愤怒的小鸟>使用了lua,ios上有lua解释器?它是怎么嵌入大ios ...

  4. C++与lua交互

    项目开发的脚本层用的是Lua,引擎用的是C++.但是经理不给开放引擎层的代码.刚好最近项目空闲,安排了学习C++跟Lua的通信. 一.C++与Lua数据交互 数据交互主要是通过C API来实现 首先, ...

  5. 转让lua性能executeGlobalFunction

    没有其他的,搞搞cocos2dx的lua文字,话lua这件事情在几年前学过一段时间.还曾对自己c++介面,我已经做了一些小东西.只是时间的流逝,模糊记忆. 拿起点功夫和成本.下面是我的一些经验. co ...

  6. lua与C交互 具体

    什么样类型的函数可以被Lua调用 typedef int (*lua_CFunction) (lua_State *L); 符合类型的函数怎样处理后才可以被Lua调用 使用lua_register或者 ...

  7. lua 源码阅读 5.3.5 笔记

    记录下吧,断断续续读了几周,收益还是很多的. 推荐阅读顺序: 1) 基础数据类型 lstring.c ltable.c lobject.c lfunc.c lstate.c 2)  标准库(这个相对简 ...

  8. golang通过cgo调用lua

    目录 1.前期准备 2.测试go代码 3.完成的一个学习项目 4.总结 1.前期准备 1.第三方库:https://github.com/aarzilli/golua 2.下载lua源码:https: ...

  9. skynet的火焰图

    之前搞过一下systemtap(systemtap折腾笔记),可惜很快琐事缠身,没有继续搞下去.最近偷空搞了一下,有点意思. 章大大的思路,是用perl生成systemtap脚本,从/proc/$pi ...

随机推荐

  1. nginx try_files命令

    location / { index index.html index.htm index.php l.php; autoindex on; try_files $uri $uri/ /index.p ...

  2. centos7 nginx用systemctl方式管理的脚本

    vim /usr/lib/systemd/system/nginx.service [Unit] Description=nginx - high performance web server Doc ...

  3. vs2012 智能提示消失解决办法

    一般你可以重启vs就可以解决问题,最蛋疼的是你重启也没用.只能重置,再不行就重装vs,再不行你就重装系统......扯淡了... 重置Visual Studio可以解决此问题, 方法:开始->M ...

  4. 一个C++类的注释:

    #ifndef __RUNTIMEPARA__HPP#define __RUNTIMEPARA__HPP #include <string> //后面会有介绍 #include <m ...

  5. 每日一练(写不出心得体会了!毕竟哪有那么多心得好写。然后看github上有很多不错的题目。分享一下!)

    第一题: 问题描述:写一个reverseWords函数 调用方式:console.log(reverseWords('Hello World')); 期望输出:World Hello 第二题: 问题描 ...

  6. js实现剪切、复制、粘贴——clipBoard.js

    摘要: 最近项目上要实现一个点击按钮复制链接的功能,刚开始查找了一些资料,找了几款插件,ZeroClipboard是通过flash实现的复制功能,随着越来越多的提议废除flash,于是就想能不能通过j ...

  7. HNU 12826 Balloons Colors

    题目链接:http://acm.hnu.cn/online/?action=problem&type=show&id=12826&courseid=268 #include&l ...

  8. [Unity3D]图形渲染优化、渲染管线优化、图形性能优化

    原地址:http://blog.sina.com.cn/s/blog_5b6cb9500101dmh0.html 转载请留下本文原始链接,谢谢.本文会不定期更新维护,最近更新于2013.11.09   ...

  9. UIView 注意问题

    1. UIView.userInteractionEnabled UIView.userInteractionEnabled默认值是YES http://blog.csdn.net/studyreco ...

  10. 在服务器上远程链接另一台服务器的数据库的方法how to connet the database from the other host

    iwangzheng.com 16:57 [root@a02.cmsapi]$ mysql -u<username> -p<password> -h10.103.xx.xx W ...