转载:lua和c的交互

 1 extern "C" {
 2 #include "lua.h"
 3 #include "lualib.h"
 4 #include "lauxlib.h"
 5 }
 6
 7 #include <iostream>
 8 #include <string>
 9 using namespace std;
10
11 int main()
12 {
13     //Lua示例代码
14     char *szLua_code =
15         "r = string.gsub(c_Str, c_Mode, c_Tag) --宿主给的变量 "
16         "u = string.upper(r)";
17     //Lua的字符串模式
18     char *szMode = "(%w+)%s*=%s*(%w+)";
19     //要处理的字符串
20     char *szStr = "key1 = value1 key2 = value2";
21     //目标字符串模式
22     char *szTag = "<%1>%2</%1>";
23
24     lua_State *L = luaL_newstate();
25     luaL_openlibs(L);
26
27     //把一个数据送给Lua
28     lua_pushstring(L, szMode);
29     lua_setglobal(L, "c_Mode");
30     lua_pushstring(L, szTag);
31     lua_setglobal(L, "c_Tag");
32     lua_pushstring(L, szStr);
33     lua_setglobal(L, "c_Str");
34
35     //执行
36     bool err = luaL_loadbuffer(L, szLua_code, strlen(szLua_code),
37                 "demo") || lua_pcall(L, 0, 0, 0);
38     if(err)
39     {
40         //如果错误,显示
41         cerr << lua_tostring(L, -1);
42         //弹出栈顶的这个错误信息
43         lua_pop(L, 1);
44     }
45     else
46     {
47         //Lua执行后取得全局变量的值
48         lua_getglobal(L, "r");
49         cout << "r = " << lua_tostring(L,-1) << endl;
50         lua_pop(L, 1);
51
52         lua_getglobal(L, "u");
53         cout << "u = " << lua_tostring(L,-1) << endl;
54         lua_pop(L, 1);
55     }
56     lua_close(L);
57     return 0;
58 }

这段代码把字符串中的key=value字符串全部转换成XML格式<key>value</key>
    在这个例子中,C++程序通过调用lua_pushstring把C字符串压入栈顶,lua_setglobal的作用是把栈顶的数据传到Lua环境中作为全局变量。
    执行代码完成后,使用lua_getglobal从Lua环境中取得全局变量压入栈顶,然后使用lua_tostring把栈顶的数据转成字符串。由于lua_tostring本身没有出栈功能,所以为了平衡(即调用前与调用后栈里的数据量不变),使用lua_pop弹出由lua_setglobal压入的数据。
    从上面的例子可以看出,C++和Lua之间一直围绕着栈在转,可见栈是极为重要的。有必要列出一些Lua C API中的主要栈操作先,它们的作用直接可以从函数名中看出。
压入元素到栈里

void lua_pushnil (lua_State *L);
void lua_pushboolean (lua_State *L, int bool);
void lua_pushnumber (lua_State *L, double n);
void lua_pushlstring (lua_State *L, const char *s, size_t length);
void lua_pushstring (lua_State *L, const char *s);
void lua_pushcfunction (lua_State *L, lua_CFunction fn);

查询栈里的元素

lua_isnil (lua_State *L, int index);
lua_isboolean (lua_State *L, int index);
int lua_isnumber (lua_State *L, int index);
int lua_isstring (lua_State *L, int index);
int lua_isfunction (lua_State *L, int index);
int lua_istable (lua_State *L, int index);
int lua_isuserdata (lua_State *L, int index);
lua_islightuserdata (lua_State *L, int index);
lua_isthread (lua_State *L, int index);

转换栈里的元素

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);
const char *    lua_tolstring (lua_State *L, int idx, size_t *len);
size_t            lua_strlen (lua_State *L, int index);
lua_CFunction   lua_tocfunction (lua_State *L, int idx);
void *          lua_touserdata (lua_State *L, int idx);
lua_State *     lua_tothread (lua_State *L, int idx);

Lua栈的维护

int  lua_gettop (lua_State *L);
    取得栈顶元素的索引,即栈中元素的个数
void lua_settop (lua_State *L, int index);
    设置栈顶索引,即设置栈中元素的个数,如果index<0,则从栈顶往下数,下同
void lua_pushvalue (lua_State *L, int 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);
    从栈顶弹出元素值并将其设置到指定索引位置,栈中的数目减一
int  lua_checkstack (lua_State *L, int extra);
    确保堆栈上至少有 extra 个空位。如果不能把堆栈扩展到相应的尺寸,函数返回 false 。这个函数永远不会缩小堆栈。
int  lua_pop(L,n)
    从栈顶弹出n个元素,它是一个lua_settop的包装:#define lua_pop(L,n)  lua_settop(L, -(n)-1)

表的操作
上面的列表中并没有lua_pushtable和lua_totable,那么怎样取得或设置Lua中的table数据呢?
在Lua中,table是一个很重要的数据类型,在table中不仅可以象C中的数据一样放一组数据,还可以象map一样以key=value的方式存放数据,如Lua代码中的:

tb = {"abc",12,true,x=10,y=20,z=30}

前三个数据可以用tb[1]~tb[3]取得
    而后三个数据通过tb.x, tb.y, tb.z取得
尽管看起来很牛叉,不过剥开神奇的外衣,实际上Lua的table中,所有的数据都是以key=value的形式存放的,这句Lua代码也可以写成:

tb = {[1]="abc", [2]=12, [3] = true, ["x"]=10, ["y"]=20, ["z"]=30}

它的形式就是[key]=value,所谓的tb.x只是tb["x"]的语法糖而已,如果愿意,也可以用tb["x"]取得这个数据10。
我们把上面的例子改成使用表的

 1 ...
 2 int main()
 3 {
 4     //Lua示例代码,使用table
 5     char *szLua_code =
 6         "x = {} --用于存放结果的table "
 7         "x[1],x[2] = string.gsub(c.Str, c.Mode, c.Tag) --x[1]里是结果,x[2]里是替换次数 "
 8         "x.u = string.upper(x[1])";
 9     //Lua的字符串模式
10     char *szMode = "(%w+)%s*=%s*(%w+)";
11     //要处理的字符串
12     char *szStr = "key1 = value1 key2 = value2";
13     //目标字符串模式
14     char *szTag = "<%1>%2</%1>";
15
16     lua_State *L = luaL_newstate();
17     luaL_openlibs(L);
18
19     //把一个tabele送给Lua
20     lua_newtable(L);    //新建一个table并压入栈顶
21     lua_pushstring(L, "Mode");// key
22     lua_pushstring(L, szMode);// value
23     //设置newtable[Mode]=szMode
24     //由于上面两次压栈,现在table元素排在栈顶往下数第三的位置
25     lua_settable(L, -3);
26     //lua_settable会自己弹出上面压入的key和value
27
28     lua_pushstring(L, "Tag");// key
29     lua_pushstring(L, szTag);// value
30     lua_settable(L, -3);    //设置newtable[Tag]=szTag
31
32     lua_pushstring(L, "Str");// key
33     lua_pushstring(L, szStr);// value
34     lua_settable(L, -3);    //设置newtable[Str]=szStr
35
36     lua_setglobal(L,"c"); //将栈顶元素(newtable)置为Lua中的全局变量c
37
38     //执行
39     bool err = luaL_loadbuffer(L, szLua_code, strlen(szLua_code),
40                 "demo") || lua_pcall(L, 0, 0, 0);
41     if(err)
42     {
43         //如果错误,显示
44         cerr << lua_tostring(L, -1);
45         //弹出栈顶的这个错误信息
46         lua_pop(L, 1);
47     }
48     else
49     {
50         //Lua执行后取得全局变量的值
51         lua_getglobal(L, "x");
52
53         //这个x应该是个table
54         if(lua_istable(L,-1))
55         {
56             //取得x.u,即x["u"]
57             lua_pushstring(L,"u");    //key
58             //由于这次压栈,x处于栈顶第二位置
59             lua_gettable(L,-2);
60             //lua_gettable会弹出上面压入的key,然后把对应的value压入
61             //取得数据,然后从栈中弹出这个value
62             cout << "x.u = " << lua_tostring(L,-1) << endl;
63             lua_pop(L, 1);
64
65             //取得x[1]和x[2]
66             for(int i=1; i<=2; i++)
67             {
68                 //除了key是数字外,与上面的没什么区别
69                 lua_pushnumber(L,i);
70                 lua_gettable(L,-2);
71                 cout << "x[" << i <<"] = " << lua_tostring(L,-1) << endl;
72                 lua_pop(L, 1);
73             }
74         }
75
76         //弹出栈顶的x
77         lua_pop(L, 1);
78     }
79     lua_close(L);
80     return 0;
81 }

本例中用到的新Lua C API是:

void lua_newtable (lua_State *L);
    新建一个空的table并压入栈顶。
void lua_settable (lua_State *L, int idx);
    lua_settable以table在栈中的索引作为参数,并将栈顶的key和value出栈,用这两个值修改table。
void lua_gettable (lua_State *L, int idx);
    lua_gettable以table在栈中的索引作为参数,弹出栈顶的元素作为key,返回与key对应的value并压入栈顶。
最后,Lua告别针对table提供了存取函数
void lua_rawgeti (lua_State *L, int idx, int n)
    取得table[n]并放到栈顶,上例中69-70行的lua_pushnumber(L,i);lua_gettable(L,-2);可以用lua_rawgeti(L,-1)代替。
lua_getfield (lua_State *L, int idx, const char *k)
    取得table.k并放到栈顶,上例中57-59行的lua_pushstring(L,"u");lua_gettable(L,-2);可以替换成lua_getfield(L,-1,"u")。
void lua_setfield (lua_State *L, int idx, const char *k)
    把栈顶的数据作为value放入table.k中,上例中的形如lua_pushstring(L, "key");lua_pushstring(L, value);lua_settable(L, -3);可以改成lua_pushstring(L, value);lua_setfield(L,-2,"key");的形式。
void lua_rawseti (lua_State *L, int idx, int n)
    把栈顶的数据作为value放入table[n]中
时间: 2024-10-26 09:24:30

转载:lua和c的交互的相关文章

Lua与C/C++交互问题

初学lua,遇到注册C/C++交互函数问题 在lua与C/C++交互时,C/C++的注册Lua函数若是一个有返回类型(压栈)而不是获取类型的时候应该返回1而不是返回0,否则会出现在Lua中值为nil(空) 不太明白为什么事这样,如果有知道的大神,麻烦讲解下 如: 应该是 int createClass(lua_State *L) { lua_class *newLua = (lua_class*)lua_newuserdata(L , sizeof(lua_class)); new (newLu

[转载]解决flash与js交互、flash跨域交互、flash跨域提交

http://blog.csdn.net/andyxm/article/details/5219919 我们引用本地flash,实现flash与js双向交互. function thisMovie(movieName) {     if (window.document[movieName]){      return window.document[movieName];    }else if (navigator.appName.indexOf("Microsoft")==-1)

Lua脚本和C++交互(一)

现在,越来越多的C++服务器和客户端融入了脚本的支持,尤其在网游领域,脚本语言已经渗透到了方方面面,比如你可以在你的客户端增加一个脚本,这个脚本将会帮你在界面上显示新的数据,亦或帮你完成某些任务,亦或帮你查看别的玩家或者NPC的状态...如此等等. 但是我觉得,其实脚本语言与C++的结合,远远比你在游戏中看到的特效要来的迅猛.它可以运用到方方面面的领域,比如你最常见的应用领域.比如,你可以用文本编辑器,写一个脚本语言,然后用你的程序加载一下,就会产生出很绚丽的界面.亦或一两句文本语言,就会让你的

lua与C++的交互

参考文档地址: Lua 与C交互 项目名字:SimFrame 项目语言:C++,lua(5.1) 项目框架:Cocos2d-x 2.2.3 一.创建项目 首先 cd到cocos2d-x包下的tools中的project-creator目录,输入 ./create_project.py -project SimFrame -package com.zyl.test -language lua 在projects目录下会有一个SimFrame的项目,打开SimFrame.xcodeproj(我用的是

Lua与C的交互

Lua 与 C 的交互 Lua是一个嵌入式的语言,它不仅可以是一个独立运行的程序,也可以是一个用来嵌入其它应用的程序库. C API是一个C代码与Lua进行交互的函数集,它由以下几部分构成: 1.  读写Lua全局变量的函数: 2.  调用Lua函数的函数: 3.  运行Lua代码片段的函数: 4.  注册C函数后可以在Lua中被调用的函数: 在C和LUA之间交互的关键在于一个虚拟栈(virtual stack),数据交互通过栈进行.操作数据时,首先将数据拷贝到栈上,然后获取数据,栈中的每个数据

lua和C++的交互(1)

/* 以前听的一个故事,当年Java的创造者讲课的时候,一开始先拿一个简单的不能简单的小例子, 不断的扩展,最后成为一个复杂而完美的程序. 一个重要之重要的概念,就是栈.Lua与别的语言交互以及交换数据,是通过栈完成的. */ #include <iostream> using namespace std; extern "C" //这部分按C语言进行编译而不是C++ { #include "lua.h" #include "lualib.h&

Lua 跟 C++ 的交互

Lua 和 C++ 是这样交互的 乱七八糟的前戏: 1. 到官网下载 Lua 文件  可參考 ->  Lua 下载与配置 2. 设置环境  可參考  ->  VS 配置Lua环境 交互过程有: 1. C++ 訪问 Lua 的变量 2. C++ 调用 Lua 的函数 3. Lua 訪问 C++ 的变量 4. Lua 訪问 C++ 的函数 No code say a j8 C++ 调用 Lua #include <iostream> #include <string> //

Lua 与C/C++ 交互系列:注册枚举enum到Lua Code中

在Lua Code中注册C/C++的枚举非常容易,就像注册全局变量一样.我们使用枚举名称作为命名空间,来避免注册的枚举发生冲突.注册的枚举存储在全局环境(线程环境)中. 当在Lua Code中访问枚举时,通过名称来访问对应的值. sample_9.cpp   c++代码如下: //在Lua Code中注册的enum,为了避免冲突,以名称作为enumTable来存储 enum Week { Monday, Tuesday, Wednesday, Thursday, Friday, Saturday

Lua 与C/C++ 交互系列:Light userdata翻译

利用零碎的时间,先把以后用的知识点提前准备好.最近比较忙,正在准备一篇绑定C++对象到Lua中.但是,不想轻易下手,希望做足准备. 这篇翻译来自于lua-users.org   ,原文地址. Light User Data Light userdata, like heavy userdata, are a form of userdata, which is one of the basic data types in Lua .Light userdata are characterized