lua 与 C交互 学习笔记

 Lua 可以作为程序库用来扩展应用的功能,也就是Lua 可以作为扩展性语言的原因

所在。同时,Lua 程序中可以注册有其他语言实现的函数,这些函数可能由语言(或其他语言)实现,可以增加一些不容易由Lua 实现的功能。

Lua 中间有两种交互方式。

第一种,作为应用程序语言,Lua 作为一个库使用;

第二种,反过来,Lua 作为程序语言,作为库使用。这两种方式,语言都使用相同的API Lua 通信,因此Lua 交互这部分称为C API


既然CLUA的交互是通过C API进行的,那么接下来,先介绍C API


C API


C API分类

1.读写Lua 全局变量的函数,

2.调用Lua 函数的函数,

3.运行Lua 代码片断的函数,

4.注册函数然后可以在Lua 中被调用的函数 等。



一个简单的代码DEMO


1 写一个简单的解释器,代码如下: 

2 #include <stdio.h> 

3 #include <lua.h> 

4 #include <lauxlib.h> 

5 #include <lualib.h> 

6 int main (void) 

7 { 

8 char buff[256]; 

9 int error; 

10 lua_State *L = lua_open(); /* opens Lua */ 

11 luaopen_base(L); /* opens the basic library */ 

12 luaopen_table(L); /* opens the table library */ 

13 luaopen_io(L); /* opens the I/O library */ 

14 luaopen_string(L); /* opens the string lib. */ 

15 luaopen_math(L); /* opens the math lib. */ 

16 while (fgets(buff, sizeof(buff), stdin) != NULL) { 

17 error = luaL_loadbuffer(L, buff, strlen(buff), 

18 "line") || lua_pcall(L, 0, 0, 0); 

19 if (error) { 

20 fprintf(stderr, "%s", lua_tostring(L, -1)); 

21 lua_pop(L, 1);/* pop error message from the stack */ 

22 } 

23 } 

24 lua_close(L); 

25 return 0; 

26 } 


因此,如果你用方式来编译它,但用在C++中,那么你需要象下面这样来包含lua.h 头文件。

extern "C" { #include <lua.h> } 一个常用的技巧是建立一个包含上面代码的lua.hpp 头文件,并将这个新的头文件包 含进你的C++程序。


lua用一个抽象的栈在Lua 之间交换值。

    栈中的每一条记录都可以保存任何Lua 值。无论你何时想要 从Lua 请求一个值(比如一个全局变量的值),调用Lua,被请求的值将会被压入栈。无 论你何时想要传递一个值给Lua,首先将这个值压入栈,然后调用Lua(这个值将被弹 出)。

1. 压入元素

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);

int lua_checkstack (lua_State *L, int sz); //  检查栈是否有足够空间


2. 从栈中取值

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);

size_t lua_strlen (lua_State *L, int index);

int lua_is... (lua_State *L, int index);  // 判断栈中值类型

// 类型细分为: LUA_TNIL、LUA_TBOOLEAN 、LUA_TNUMBER 、LUA_TSTRING 、LUA_TTABLE 、LUA_TFUNCTION、LUA_TUSERDATA 以及LUA_TTHREAD



3. 其他栈操作

int lua_gettop (lua_State *L);

void lua_settop (lua_State *L, int index);

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);

void lua_getglobal (lua_State *L, const char *name);  // lua的全局变量放到栈顶


4. 调用lua函数

 首先,将被调用的函数入栈;

第二,依次将所有参数入栈;

第三,使用lua_pcall 调用函数;

最后,从栈中获取函数执行返回的结果。

函数调用的demo

//C code

double f (double x, double y) {

double z;

/* push functions and arguments */

lua_getglobal(L, "f"); /* function to be called */

lua_pushnumber(L, x); /* push 1st argument */

lua_pushnumber(L, y); /* push 2nd argument */

/* do the call (2 arguments, 1 result) */

if (lua_pcall(L, 2, 1, 0) != 0)

error(L, "error running function `f': %s",

lua_tostring(L, -1));

/* retrieve result */

if (!lua_isnumber(L, -1))

error(L, "function `f' must return a number");

z = lua_tonumber(L, -1);

lua_pop(L, 1); /* pop returned value */

return z;

}

-- lua code

function f (x, y)

return (x^2 * math.sin(y))/(1 - x)

End



5. 调用C函数

Lua调用函数我们必须注册函数,也就是说,我们必须把函数的地址以一个适当的方式传递给Lua 解释器。

lua_pushcfunction(l, l_sin);

lua_setglobal(l, "mysin");

第一行将类型为function 的值入栈,第二行将function 赋值给全局变量mysin。这样修改之后,重新编译Lua,你就可以在你的Lua 程序中使用新的mysin 函数了。


6.C 函数库

Lua 通过这个注册过程,就可以看到库中的C 函数。一旦一个C 函数被注册之后并

保存到Lua 中,在Lua 程序中就可以直接引用他的地址(当我们注册这个函数的时候传递给Lua 的地址)来访问这个函数了。

当你打算使用 C 函数来扩展Lua 的时候,即使你仅仅只想注册一个C 函数,将你的C 代码设计为一个库是个比较好的思想:不久的将来你就会发现你需要其他的函数。

luaL_openlib 函数接受一个C 函数的列表和他们对应的函数名,并且作为一个库在一个table 中注册所有这些函数。

首先,我们必须定义库函数

static int l_dir (lua_State *L) {

... /* as before */

}

第二步,我们声明一个数组,保存所有的函数和他们对应的名字。

static const struct luaL_reg mylib [] = {

{"dir", l_dir},

{NULL, NULL} /* sentinel */

};

第三步,我们使用luaL_openlib 声明主函数:

int luaopen_mylib (lua_State *L) {

luaL_openlib(L, "mylib", mylib, 0);

return 1;

}

第四部,你就可以在Lua 中直接使用loadlib 加载你刚才定义的函数库了,

mylib = loadlib("fullname-of-your-library", "luaopen_mylib")





评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值