C语言和Lua交互(一)
来源:互联网 发布:js自定义弹出框 编辑:程序博客网 时间:2024/05/16 04:12
Lua可作为扩展性语言(Lua可以作为程序库用来扩展应用的功能),同时也是个可扩展的语言(Lua程序中可以注册由其他语言实现的函数)。
Lua和C通信的主要方法是通过一个虚拟栈来完成,lua提供了C API对栈进行操作。几乎所有的API调用都是对栈上的值进行操作,所有C与Lua之间的数据交换也都通过这个栈来完成。另外,你也可以使用栈来保存临时变量。
C API是一个C代码与Lua进行交互的函数集。他由以下部分组成:读写Lua全局变量的函数、调用Lua函数的函数、运行Lua代码片断的函数、注册C函数然后可以在Lua中被调用的函数,等等。
API用索引来访问栈中的元素,堆栈索引可以是正数也可以是负数。
区别是:正数索引1永远表示栈底,负数索引-1永远表示栈顶。
Lua以一个严格的LIFO规则(后进先出;也就是说,始终存取栈顶)来操作栈:
(1)C调用Lua时,返回结果只会改变栈顶部分。
(2)编写C代码比较自由,可以查询栈上的任何元素,在任何一个位置插入和删除元素。
在调用C API时有几个重要的头文件,这几个头文件都是lua源代码,可以直接下载使用:
(1)lua.h:Lua基础函数库,对栈的基本操作都在里面实现,lua_前缀
(2)lauxlib.h:辅助库,luaL_前缀,利用lua.h实现的更高层的抽象
(3)lualib.h:为了保持Lua的苗条,所有的标准库以单独的包提供,所以如果你不需要就不会强求你使用它们。头文件lualib.h定义了打开这些库的函数。例如,调用luaopen_io,以创建io table并注册I/O函数(io.read,io.write等等)到Lua环境中。
C API参考手册:http://www.lua.org/manual/5.3/
云风翻译中文手册:http://cloudwu.github.io/lua53doc/contents.html
常用辅助函数:
lua_State *luaL_newstate (void);//创建一个新环境(新的Lua状态)void luaL_openlibs (lua_State *L);//打开指定状态机中的所有 Lua 标准库。如:print,pcallint luaL_loadstring (lua_State *L, const char *s); //将一个字符串加载为 Lua 代码块。int luaL_loadfile (lua_State *L, const char *filename);//把一个文件加载为 Lua 代码块。 int luaL_loadfilex (lua_State *L, const char *filename,const char *mode);int luaL_loadbuffer (lua_State *L,const char *buff,size_t sz,const char *name);int luaL_loadbufferx (lua_State *L,const char *buff,size_t sz,const char *name,const char *mode);
常用的基础函数:
压入栈元素
void lua_pushnil (lua_State *L);//将空值压栈。void lua_pushboolean (lua_State *L, int bool);void lua_pushnumber (lua_State *L, double n);//把一个值为 n 的浮点数压栈。void lua_pushlstring (lua_State *L, const char *s, size_t length);void lua_pushstring (lua_State *L, const char *s);//将指针 s 指向的零结尾的字符串压栈。 因此 s 处的内存在函数返回后,可以释放掉或是立刻重用于其它用途。 返回内部副本的指针。
检查一个元素能否被转换成指定的类型。
int lua_isnil (lua_State *L, int index);//当给定索引的值是 nil 时,返回 1 ,否则返回 0 。 int lua_isnumber (lua_State *L, int index);//当给定索引的值是一个数字,或是一个可转换为数字的字符串时,返回1,否则返回 0 。 int lua_isstring (lua_State *L, int index);//当给定索引的值是一个字符串或是一个数字 (数字总能转换成字符串)时,返回 1 ,否则返回 0 。 int lua_istable (lua_State *L, int index);//当给定索引的值是一张表时,返回 1 ,否则返回 0 。 int lua_isboolean (lua_State *L, int index);//当给定索引的值是一个布尔量时,返回 1 ,否则返回 0 。 int lua_isfunction (lua_State *L, int index);//当给定索引的值是一个函数( C 或 Lua 函数均可)时,返回 1 ,否则返回0 。
从栈中获得值。即使给定的元素类型不正确,调用这些函数也没问题。
int lua_toboolean (lua_State *L, int index);double lua_tonumber (lua_State *L, int index);const char * lua_tostring (lua_State *L, int index);
Lua_tostring函数返回一个指向字符串的内部拷贝的指针。你不能修改它(使你想起那里有一个const)。只要这个指针对应的值还在栈内,Lua会保证这个指针一直有效。当一个C函数返回后,Lua会清理他的栈,所以,有一个原则:永远不要将指向Lua字符串的指针保存到访问他们的外部函数中。
size_t lua_strlen (lua_State *L, int index);//返回字符串的实际长度。 int lua_checkstack(lua_State *L, int sz);//检查栈空间。默认有20个空闲的记录,lua.h中的LUA_MINSTACK宏定义了这个常量。 int lua_type (lua_State *L, int idx);//返回栈中元素的类型; const char* lua_typename(lua_State *L, int tp);//返回type对应的名字字符串,第二个参数为lua_type返回的类型 void luaL_checktype (lua_State *L, int arg, int t);//返回参数arg是否是类型t,第三个参数为lua_type的取值。
在lua.h头文件中,每种类型都被定义为一个常量:LUA_TNIL、LUA_TBOOLEAN、LUA_TNUMBER、LUA_TSTRING、LUA_TTABLE、LUA_TFUNCTION、LUA_TUSERDATA以及LUA_TTHREAD。
int lua_gettop (lua_State *L);//返回栈中元素个数,它也是栈顶元素的索引。 void lua_settop (lua_State *L, int index);//设置栈顶元素的索引,相当于设置栈的大小。如果开始的栈顶高于新的栈顶,顶部的值被丢弃。否则,为了得到指定的大小这个函数压入相应个数的空值(nil)到栈上。lua_settop(L,0):清空堆栈。 #define lua_pop(L,n) lua_settop(L, -(n)-1);//宏定义,弹出n个元素。 void lua_pushvalue (lua_State *L, int index);//压入堆栈上指定索引的一个抟贝到栈顶,等于拷贝index处的元素,然后添加到栈顶。 void lua_remove (lua_State *L, int index);//移除指定索引的元素,并将其上面所有的元素下移来填补这个位置的空白。 void lua_insert (lua_State *L, int index);//移动栈顶元素到指定索引的位置,并将这个索引位置上面的元素全部上移至栈顶被移动留下的空隔。 void lua_replace (lua_State *L, int index);//从栈顶弹出元素值并将其设置到指定索引位置,没有任何移动操作。
Lua和C简单交互代码:
#include <stdio.h>#include <string.h>#include "lua.h"#include "lauxlib.h"#include "lualib.h"int main(void){ char buff[256]; int error; lua_State *L = luaL_newstate(); //打开Lua,创建一个新环境(新的Lua状态) luaL_openlibs(L); //打开标准库, 如: print, pcall //接收用户输入lua代码, 并编译解析 while(fgets(buff,sizeof(buff),stdin)!=NULL){ error = luaL_loadbuffer(L,buff,strlen(buff),"line")||lua_pcall(L,0,0,0);//luaL_loadbuffer编译Lua代码(没有错误则压入栈),lua_pcall执行 if(error){ //执行或编译错误lua_tostring打印错误信息 fprintf(stderr,"%s\n",lua_tostring(L,-1)); lua_pop(L,1); //从栈中弹出错误消息 } } lua_close(L);//关闭lua状态 return 0;}
编译代码
gcc -lm -g -o testlua testlua.c /usr/local/lib/liblua.a -ldl
运行程序,输入lua代码
例如: print “aaaaa”
Lua和C++简单交互代码:
#include <iostream>#include <string.h>using namespace std;//告诉编译器要采用c编译的方式,而不是c++编译的方式。extern "C"{ #include "lua.h" #include "lauxlib.h" #include "lualib.h"}int main(void){ char buff[256]; int error; lua_State *L = luaL_newstate(); //打开Lua,创建一个新环境(新的Lua状态) luaL_openlibs(L); //打开标准库, 如: print, pcall //接收用户输入lua代码, 并编译解析 while(fgets(buff,sizeof(buff),stdin)!=NULL){ error = luaL_loadbuffer(L,buff,strlen(buff),"line")||lua_pcall(L,0,0,0);//luaL_loadbuffer编译Lua代码(没有错误则压入栈),lua_pcall执行 if(error){ //执行或编译错误lua_tostring打印错误信息 fprintf(stderr,"%s\n",lua_tostring(L,-1)); lua_pop(L,1); //从栈中弹出错误消息 } } lua_close(L);//关闭lua状态 return 0;}
主要区别是extern “C”
由于lua源码是C编写的,所以需要告知编译器编译时使用C的方式编译,而不是C++的方式编译
编译代码:
g++ -lm -g -o testlua1 testlua1.cpp /usr/local/lib/liblua.a -ldl
运行程序,输入lua代码
例如: print “aaaaa”
- C语言和Lua交互(一)
- Lua和C语言的交互(一)
- Lua和C语言的交互(一)
- Lua和C语言的交互
- Lua和C语言的交互详解
- C语言和Lua交互(二)
- C语言和Lua交互(三)
- C语言和Lua交互(四)
- C语言和Lua交互(五)
- C语言和Lua交互(六)
- C语言和Lua交互(七)
- Lua和C语言的交互详解
- C和lua交互
- lua和C交互
- c语言与lua交互(capi)介绍, lua调用C语言函数详解(一)
- lua与c交互 一
- Lua和C语言的交互(二)
- Lua和C语言的交互(三)
- android sqlite中String日期查询转换操作
- 排序之冒泡排序(数组)
- 关于Windows主机的性能监控
- Java7:Fork-Join框架
- linux下动态库的使用
- C语言和Lua交互(一)
- TTY之struct consw
- cocos-Lua中的class与require机制(小积累)
- 公牛和母牛竞猜游戏《c++程序设计原理与实践》第5章习题12,13
- etcd 安装部署及常见使用场景
- TTY之struct console
- 【C/C++开发】值得学习的C语言开源项目
- 多线程简介
- JavaScript 发送短信案例