免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 2198 | 回复: 0
打印 上一主题 下一主题

【随笔】用lua脚本扩展嵌入式linux应用程序 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2008-03-29 11:22 |只看该作者 |倒序浏览
一、前言

  Lua是一种和C/C++结合非常紧密的脚本语言,效率极高。一般是对时间要求比较高的地方用C++写,而经常需要改动的地方用Lua写。
  偶最近在学习Lua, 所以写出心得和大家共享. Lua是一种完全免费的脚本语言,它的官方网站在
http://www.lua.org
.在网站上可以下载到lua的源码, 没有可执行版本, 不过不用担心, 因为lua源码可以在任何一种C/C++的编译器上编译.

  平台:       PowerPC AMCC 440ep
  交叉编译器:  ppc_440ep-gcc
  交叉编译环境:Debian/Ubuntu

二、下载 lua 源码包

  这里可以下载到所有的版本
http://www.lua.org/ftp/
  注:本文所用版本为 lua-5.0

三、使 lua-5.0 支持16进制数
   
  由于我需要保存16进制数值,而只有lua-5.1 之后才支持16进制数,所以我们需要下载补丁。这个补丁也是我从网上搜的可以使lua-5.0版本支持table中用16进制数保存数值
   

文件:
lua-5.0-support_hex.tar.gz
大小:
185KB
下载:
下载

四、熟悉语法
   
  网上可以很容易的搜到关于lua语法的文章,如果想了解更加详细的介绍可以下载
《Progamming in Lua》。

五、交叉编译移植lua

  由于我得程序最终要在PowerPC上跑,所以需要交叉编译lua并移植到开发板上。其实用lua扩展自己的应用程序需要的只是lua的头文件和编译出来的静态库。
  解压缩,并将补丁打入源码包:
  tar zxvf lua-5.0.tar.gz               
  tar zxvf lua-5.0-support_hex.tar.gz
  cp lua-5_0-hex_patch lua-5.0                ;将补丁拷贝到lua源码根目录下
  patch -p1

  修改配置文件设置交叉编译环境:
  vi config
  修改如下几行

  CC= ppc_440ep-gcc                           ;交叉编译工具
  STRIP= ppc_440ep-strip                      ;同上
  INSTALL_ROOT= /home/work/lxg/usr/local      ;安装路径(这个路径是我自己建立的)

  交叉编译并安装到制定目录
  make
  make install

  安装结束后会在/home/work/lxg/usr/local下生成四个文件夹:
  bin lib include man
  将 lib 和 include 下所有文件拷贝到交叉编译工具链的库和头文件的路径下(可以设置INSTALL_ROOT 然后 make install 直接安装 )

六、用lua扩展你的程序

  在《Progamming in Lua》中第25章讲解了简单的扩展C程序的方法,所以我这里就不再说了,下面我只介绍下几个比较有用的扩展:
  1、如何编译Lua扩展后的C程序?
  2、Lua如何向Lua传递表格?
  3、函数如何向Lua脚本中的函数传递表格?
  4、C函数如何调用Lua脚本中的函数?
  5、Lua脚本如何调用C语言中的函数?

  1如何编译Lua扩展后的C程序?

  Lua扩展程序所用的API都是靠两个静态库实现的,因此编译的时候需要增加库链接的参数,另外还需要编译器的math库
  首先程序中必须包含Lua的三个头文件
  #include
  #include
  #include

     
  其次,编译的时候需要链接库

  $(CC) $(CFLAGS) -o $@ $

  2、Lua如何向Lua传递表格?
      
  问题概要:用lua写了个函数,返回的是一个表。需要在C里对返回的表里元素做二次处理。在C里我们可以通过lua_gettable()或者lua_rawget()来获取表里元素值,但使用这两个接口的前提是你得知道key,它才能给你value. 当然对于顺序下标倒无所谓,但恰巧这次我用到的是关联数组,下标是无规则字符串.这时候如何遍历出表里元素就是个问题.
lua_next()就成了比较合适的选择.下图对整个逻辑做了解释
file:///d://1.jpg
  上图对简单的表遍历做了介绍, 但事实上的情况是我返回了一个二维表,如果你了解了lua_next()的处理过程,那下面的代码看起来就没什么问题了.
  例如定义一个lua脚本 test.lua   
   
table_1 = {0x00,0x11,0x22,0x33}
table_2 = {0x44,0x55,0x66,0x77}
   
  下面的函数可以直接得到表中的16进制数

lua_State *L;
int main(void)
{
  int t_idx;
   
  //打开句柄
  L= lua_open();     
  //加载各个库
  luaopen_base(L);   
  luaopen_io(L);
  luaopen_string(L);
  luaopen_math(L);
  //打开lua脚本
  if(luaL_loadfile(L, "test.lua") || lua_pcall(L, 0, 0,0))
    printf("error!!!!!!!!!!!\r\n");
  
  //将table_2的名字压入堆栈
  lua_getglobal(L, "table_2");
  if(!lua_istable(L, -1))
  {
    printf("is not a table \r\n");
    return -1;
  }
  //将nil压栈
  lua_pushnil(L);
   
  //以nill作为索引取下一个值
  while (lua_next(L, -2) != 0)
  {
    if(lua_isnumber(L,-1)) //判断元素类型,也可能是string
    {   
      t_idx=lua_tonumber(L, -1);//获取元素的值
      printf("0x%x \r\n",t_idx);
      lua_remove(L,-1); //移除栈顶数
    }
  }
  lua_remove(L,-1);//删除NIL
  lua_close(L);
  return 0;
}

  上面的函数可以得到脚本中table_2中的每一个值,这样配合lua脚本可以轻松的定义和得到16进制数组。

  3、函数如何向Lua脚本中的函数传递表格?
  
  例如下面的test.lua脚本中定义了一个函数,该函数是从C程序中得到一个固定的参数n和多个参数。
  注:"..."代表的多参数被默认保存在arg[]中,脚标从1开始。
  
command = {}
function checkSum(n,...)
        arg[7]=math.mod((arg[2]+arg[3]+arg[4]+arg[5]+arg[6]),256)
        for i=1,n+1 do
            command=arg
        end
    return command
end

  注:checkSum(n,...) 这样定义可以定义一个固定参数和多个参数

  下面的函数就是将一个数组的成员个数和每个成员传递给lua的函数。
int checkSum(lua_State *L,int command_num,unsigned char *str)
{
    int i;
   
    lua_getglobal(L, "checkSum");
    lua_pushnumber(L,command_num);
   
    for(i=0;i

  4、C函数如何调用Lua脚本中的函数?
     
  见《 Progamming in Lua 》第25章第2节

  5、Lua脚本如何调用C语言中的函数?
   
  其实所有lua与C语言的数据交换都遵循堆栈FILO的规则,因此lua调用C语言中的函数在参数传递方面和上面讲到的方法相似。
  例如lua中不支持位运算,我们可以在C中定义为lua所用的位运算函数。

int luaBitRshift(lua_State *L)
{
  unsigned char data,num,result;
  //lua调用的时候:luaBitRshift(arg1,arg2)  arg1:数值 arg2:位移的位数
  //得到的结果栈顶第一个数位arg2
  if(!lua_isnumber(L, -1))
  {
    printf("luaBitRshift:[arg2] is not a number\n");
    return -1;
  }        
  num=((int)lua_tonumber(L, -1));
   
  if(!lua_isnumber(L, -2))
  {
    printf("luaBitRshift:[arg1]    is not a number\n");
    return -1;
  }   
  data=((int)lua_tonumber(L, -2));
  result=data>>num;
  lua_pushnumber(L, result);
  return 1;
}
  另外,还需为lua注册这个函数,让lua解释器知道这个函数。
  
  lua_register(L, "luaBitRshift", luaBitRshift);

  这样,在lua函数中就可以直接调用这个函数了。

command = {}
function checkSum(n,...)
    local value = arg[1];
    for i = 2, 7 do
        value = luaBitXor(value,arg);
    end;
    arg[8] = math.mod(value, 256);
    for i=1,n+1 do
            command=arg
        end
    return command
end

更新中......



本文来自ChinaUnix博客,如果查看原文请点:http://blog.chinaunix.net/u2/64853/showart_511247.html
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP