大话lua与c语言的桥梁之luaJIT的ffi库(下)

luaJIT的FFI库有很多有用的函数,除了上文介绍的ffi.cdef,ffi.C和ffi.load外,还有以下常用的函数,听我一一道来

1、ffi.new

  • 功能:判断一个cdata对象

  • 用法:ffi.new(ct, elem?, init?)

  • 参数:

    • ct为C语言的数据类型,可以是基本数据类型,也可以是结构体等复合类型,当然也包括一些类型别名,如uin64_t
    • elem为元素个数,一般用于数组中(可选参数)
    • init为初始化数据

如:

  1. local ffi = require 'ffi'
  2. local cdata = ffi.new('int[3]', {}) -- 相当于 int[3] = {0, 0, 0}
  3. local data = ffi.new('int[5]', {1}) -- 相当于 int[5] = {1, 1, 1, 1, 1}
  4. local sdata = ffi.new('struct student', {"2016030303", "shixinke"})

更多规则请查看:http://luajit.org/ext_ffi_semantics.html#init

2、ffi.typeof

  • 功能:创建一个ctype对象,一般适用于只需要解析一次cdecl的场景(个人认为一般作为lffi.cast的参数)

  • 用法:ffi.typeof(ct)

  • 参数:ffi.cdef中定义的数据结构类型

  • 返回值:一个ctype对象

3、ffi.cast

  • 功能:用于创建一个标量cdata对象(类似于ffi.new)

  • 用法:ffi.cast(ct, init)

  • 参数:

    • ct为一个ctype类型
    • init为初始数据(一般是一个table)

4、ffi.sizeof

  • 功能:返回ct占用的内在大小

  • 用法:ffi.sizeof(ct)

  • 参数:ct为cdef中声明的结构类型或定义的基本数据类型

如:

  1. local ffi = require 'ffi'
  2. ffi.cdef[[
  3. typedef struct Student{
  4. char no[50];
  5. char name[50];
  6. } Stu;
  7. ]]
  8. print(ffi.sizeof('struct Student'))

5、ffi.string

  • 功能:将指向ptr的数据转换成lua字符串

  • 用法:ffi.string(ptr)

  • 参数:ptr为数据对象指针

综合实例:使用ffi和内存共享字典ngx.shared.DICT实现网站访问的一个初步统计:

nginx配置添加共享内存设置如下:

  1. lua_shared_dict ipcache 10m;

lua代码:

  1. -- 第一步:要加载ffi模块
  2. local ffi = require "ffi"
  3. -- 第二步:添加C数据结构声明
  4. ffi.cdef[[
  5. typedef struct ipcache{
  6. int last_time;
  7. int clicks;
  8. } ipcache;
  9. ]]
  10. -- 第三步:使用ffi模块的相关函数
  11. local size = ffi.sizeof('ipcache') -- 计算ipcache这个结构体占用的内存大小
  12. local ptr = ffi.typeof('ipcache *')
  13. local data = ffi.new('ipcache')
  14. local now = ngx.now
  15. local dict = ngx.shared.ipcache
  16. local ip = ngx.var.remote_addr
  17. local cache = dict:get(ip)
  18. if cache then
  19. data = ffi.cast(ptr, cache)
  20. data.clicks = data.clicks+1
  21. last_time = cache.last_time
  22. else
  23. data.clicks = 1
  24. end
  25. data.last_time = now()
  26. dict:set(ip, ffi.string(data, size))
  27. last_time = last_time or now()
  28. ngx.say('您访问了'..data.clicks..'次');
  29. ngx.say('您上次访问时间是:'..last_time)