IT練習ノート

IT関連で調べたこと(実際は嵌ったこと)を書いています。

attempt to index global 'XXX' (a nil value)

attempt to index global 'XXX' (a nil value)はスコープの指定がわるいため。

エラーになる場合

> Foo = {
>>   Bar = {[1]="Bar-1", [2]="Bar-2"} 
>> ,[1] = "Foo-1" 
>> ,[2] = "Foo-2"
>>  , bazz = function(v) return Bar[v] end
>> }
> = type(Foo.bazz)
function
> = Foo.bazz(1)
stdin:5: attempt to index global 'Bar' (a nil value)
stack traceback:
    stdin:5: in function <stdin:5>
    (...tail calls...)
    [C]: in ?

Barがみえないので、Foo.Barと指定する。

> Foo = { 
>> Bar = {[1]="Bar-1", [2]="Bar-2"}
>> ,[1] = "Foo-1"
>> ,[2] = "Foo-2"  
>>  , bazz = function(v) return Foo.Bar[v] end
>> }
> = Foo.bazz(1)
Bar-1
>

lua - Attempt to index global 'object' (a nil value) - Stack Overflow

Luaのメタテーブル

普通の計算

>
> = 1 + 1
2
> x = 2
> = 1 + x
3

テーブルを足し算。当然エラーになる。

> y = {}
> = 1 + y
stdin:1: attempt to perform arithmetic on global 'y' (a table value)
stack traceback:
    stdin:1: in main chunk
    [C]: in ?

メタテーブルに特別な関数を設定すると、エラーにならない。

> setmetatable(y, {__add = function() return 3 end})
> = 1 + y
3
>

luaのテーブル

luaのテーブルはfunctionを持つことができます。

> AnyType = {
>>    [1] = "SCALAR"
>>   ,[2] = "OBJECT"
>>   ,[3] = "ARRAY"
>> }
>
> Any = {
>>     [1] = {attr = "required" , type = "Type"   , name = "Any.type" , tag = 1}
>>   , [2] = {attr = "optional" , type = "Scalar" , name = "scalar"   , tag = 2}
>>   , [3] = {attr = "optional" , type = "Object" , name = "obj"      , tag = 3}
>>   , [4] = {attr = "optional" , type = "Array"  , name = "array"    , tag = 4}
>>   , type_fun = function(v) return AnyType[v] end
>> }
>
> = Any[1];
table: 0x7fc353d03050
> return  Any.type_fun
function: 0x7fc353d02b40
> return  Any.type_fun(1)
SCALAR
> return  Any.type_fun(2)
OBJECT
> return  Any.type_fun(3)
ARRAY
> return  Any["type_fun"](3)
ARRAY
>

Wireshark plugin 開発メモ

情報源

Wiresharkの解析プラグインを作る ssmjp 201409

macos - How to port a Wireshark Lua dissector Script to Mac OSX? - Stack Overflow

http://www.ainoniwa.net/ssp/wp-content/uploads/2013/06/wireshark_dissector_with_lua.pdf

第269号(2016年11月2日発行) 技術レポート「Wiresharkの活用法 その2 〜専用プロトコルを表示させる〜」|ソフテックだより|株式会社ソフテック

Wireshark で独自プロトコルを解析 (dissector with Lua) - Qiita

https://sharkfest.wireshark.org/sharkfest.09/DT06_Bjorlykke_Lua%20Scripting%20in%20Wireshark.pdf

Global Configuration

$ ls -al /Applications/Wireshark.app/Contents/Resources/share/wireshark/
...
-rw-rw-r--    1 root  admin    18119 12  1 20:37 init.lua
...
$

Personal configuration

$ ls -al ~/.config/wireshark
total 392
drwxr-xr-x  10 foo  staff     340 12  1 21:28 .
drwx------   9 foo  staff     306 11  7 20:49 ..
-rw-r--r--   1 foo staff     575 12  1 21:28 cfilters
...
$

Luaのtableの自己参照

luaのテーブルはオブジェクトのように扱えますが、下の例のように自己参照はできません。

> Any = {
>>   AnyType = {
>>      [1] = "SCALAR"
>>     ,[2] = "OBJECT"
>>     ,[3] = "ARRAY"
>>   }
>>   , [1] = {attr = "required" , type = "Type"   , name = "Any.type" , tag = 1, convert = Any.enum_fun} -- ここで自分自身の関数を参照したい
>>   , [2] = {attr = "optional" , type = "Scalar" , name = "scalar"   , tag = 2}
>>   , [3] = {attr = "optional" , type = "Object" , name = "obj"      , tag = 3}
>>   , [4] = {attr = "optional" , type = "Array"  , name = "array"    , tag = 4}
>>   , enum_fun = function(v) return AnyType[v] end
>> }
stdin:7: attempt to index global 'Any' (a nil value)
stack traceback:
    stdin:7: in main chunk
    [C]: in ?
>

当然thisはない。

> Any = {
>>   AnyType = {
>>      [1] = "SCALAR"
>>     ,[2] = "OBJECT"
>>     ,[3] = "ARRAY"
>>   }
>>   , [1] = {attr = "required" , type = "Type"   , name = "Any.type" , tag = 1, convert = this.enum_fun}
>>   , [2] = {attr = "optional" , type = "Scalar" , name = "scalar"   , tag = 2}
>>   , [3] = {attr = "optional" , type = "Object" , name = "obj"      , tag = 3}
>>   , [4] = {attr = "optional" , type = "Array"  , name = "array"    , tag = 4}
>>   , enum_fun = function(v) return AnyType[v] end
>> }
stdin:7: attempt to index global 'this' (a nil value)
stack traceback:
    stdin:7: in main chunk
    [C]: in ?
>

一旦定義を作っておいて、後から追加すれば、それ相当のことができる。

> Any = {
>>   AnyType = {
>>      [1] = "SCALAR"
>>     ,[2] = "OBJECT"
>>     ,[3] = "ARRAY"
>>   }
>>   , [1] = {attr = "required" , type = "Type"   , name = "Any.type" , tag = 1}
>>   , [2] = {attr = "optional" , type = "Scalar" , name = "scalar"   , tag = 2}
>>   , [3] = {attr = "optional" , type = "Object" , name = "obj"      , tag = 3}
>>   , [4] = {attr = "optional" , type = "Array"  , name = "array"    , tag = 4}
>>   , enum_fun = function(v) return AnyType[v] end
>> }
> Any[1].convert = Any.enum_fun
> = Any[1]
table: 0x7fc353f017f0
> return  Any[1].attr
required
> return  Any[1].type
Type
> return  Any[1].name
Any.type
> return  Any[1].tag
1
> return  Any[1].convert
function: 0x7fc353f016d0

参考

How to reference lua table member from table member? - Stack Overflow

luaの型

luaに型がある。typeファンクションで確認ができる。

number

> type(1)
> = type(1)
number
> return  type(1) == 'number'
true

function

> type (function() print("hello") end)
> = type (function() print("hello") end)
function
> return  type (function() print("hello") end) == "function"
true

table

> type ({})
> = type ({})
table

alienのインストール

alienがあるか確認

> require "alien"
stdin:1: module 'alien' not found:
    no field package.preload['alien']
    no file '/usr/local/share/lua/5.2/alien.lua'
    no file '/usr/local/share/lua/5.2/alien/init.lua'
    no file '/usr/local/lib/lua/5.2/alien.lua'
    no file '/usr/local/lib/lua/5.2/alien/init.lua'
    no file './alien.lua'
    no file '/usr/local/lib/lua/5.2/alien.so'
    no file '/usr/local/lib/lua/5.2/loadall.so'
    no file './alien.so'
stack traceback:
    [C]: in function 'require'
    stdin:1: in main chunk
    [C]: in ?

残念ながらデフォルトでは入っていないようです。

パッケージマネージャluarocksの確認

知らない間に入っていました。

$ luarocks

LuaRocks 2.3.0, a module deployment system for Lua

NAME
    /usr/local/bin/luarocks - LuaRocks main command-line interface

SYNOPSIS
    /usr/local/bin/luarocks [--from=<server> | --only-from=<server>] [--to=<tree>] [VAR=VALUE]... <command> [<argument>]

...

alienのインストール1回目

$ luarocks install alien
Installing https://luarocks.org/alien-0.7.1-2.src.rock...
Using https://luarocks.org/alien-0.7.1-2.src.rock... switching to 'build' mode
./bootstrap && ./configure LUA=/usr/local/bin/lua CPPFLAGS='-I/usr/local/include -I/usr/include' LDFLAGS=-L/usr/lib --prefix=/usr/local/lib/luarocks/rocks-5.2/alien/0.7.1-2 --libdir=/usr/local/lib/luarocks/rocks-5.2/alien/0.7.1-2/lib --datadir=/usr/local/lib/luarocks/rocks-5.2/alien/0.7.1-2/lua && make clean && make
bootstrap: running: glibtoolize --quiet

...

checking for ffi/ffi.h... yes
checking for ffi_closure_alloc in -lffi... no
configure: error: in `/tmp/luarocks_alien-0.7.1-2-4392/alien':
configure: error: cannot find new enough libffi
See `config.log' for more details

Error: Build error: Failed building.

libffiがないのでエラーになります。

libdiffのインストール

$ brew install libffi
Updating Homebrew...
==> Auto-updated Homebrew!
Updated 4 taps (caskroom/cask, homebrew/core, homebrew/php, homebrew/services).
==> New Formulae
apm-server                   dislocker                    go-jira                      homebrew/php/php72-xdebug    kubeless                     restic
asciidoctor                  dnsdist                      heartbeat                    htslib                       libxo                        sceptre

...

For compilers to find this software you may need to set:
    LDFLAGS:  -L/usr/local/opt/libffi/lib
For pkg-config to find this software you may need to set:
    PKG_CONFIG_PATH: /usr/local/opt/libffi/lib/pkgconfig

==> Summary
🍺  /usr/local/Cellar/libffi/3.2.1: 16 files, 301.6KB

Homebrewでビールのアイコンでるのなんなんでしょう。禁酒中の私にとってはムカつくだけです。

alienのインストール2回目

$ luarocks install alien
Installing https://luarocks.org/alien-0.7.1-2.src.rock...
Using https://luarocks.org/alien-0.7.1-2.src.rock... switching to 'build' mode
./bootstrap && ./configure LUA=/usr/local/bin/lua CPPFLAGS='-I/usr/local/include -I/usr/include' LDFLAGS=-L/usr/lib --prefix=/usr/local/lib/luarocks/rocks-5.2/alien/0.7.1-2 --libdir=/usr/local/lib/luarocks/rocks-5.2/alien/0.7.1-2/lib --datadir=/usr/local/lib/luarocks/rocks-5.2/alien/0.7.1-2/lua && make clean && make
bootstrap: running: glibtoolize --quiet
bootstrap: running: autoreconf --symlink --install
configure.ac:11: installing 'build-aux/ar-lib'

configure: error: in `/tmp/luarocks_alien-0.7.1-2-5849/alien':
configure: error: cannot find new enough libffi
See `config.log' for more details

Error: Build error: Failed building.

libffiが見つからなくてエラーになります。

libffiの確認

$ ls /usr/local/opt/libffi/
ChangeLog       INSTALL_RECEIPT.json    LICENSE         README          lib         share

インストールは出来ているようです。

alienのインストール3回目

libffiの場所を指定してインストールします。

$ CFLAGS='-L/usr/local/opt/libffi/lib' luarocks install alien
Installing https://luarocks.org/alien-0.7.1-2.src.rock...
Using https://luarocks.org/alien-0.7.1-2.src.rock... switching to 'build' mode
./bootstrap && ./configure LUA=/usr/local/bin/lua CPPFLAGS='-I/usr/local/include -I/usr/include' LDFLAGS=-L/usr/lib --prefix=/usr/local/lib/luarocks/rocks-5.2/alien/0.7.1-2 --libdir=/usr/local/lib/luarocks/rocks-5.2/alien/0.7.1-2/lib --datadir=/usr/local/lib/luarocks/rocks-5.2/alien/0.7.1-2/lua && make clean && make
bootstrap: running: glibtoolize --quiet

...

/Applications/Xcode.app/Contents/Developer/usr/bin/make  all-am
  CC       src/alien.lo
clang: warning: argument unused during compilation: '-L/usr/local/opt/libffi/lib'
src/alien.c:550:12: warning: implicit declaration of function 'ffi_closure_alloc' is invalid in C99 [-Wimplicit-function-declaration]
  ac->fn = ffi_closure_alloc(sizeof(ffi_closure), &ac->ffi_codeloc);
           ^
src/alien.c:550:10: warning: incompatible integer to pointer conversion assigning to 'void *' from 'int' [-Wint-conversion]
  ac->fn = ffi_closure_alloc(sizeof(ffi_closure), &ac->ffi_codeloc);
         ^ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
src/alien.c:565:14: warning: implicit declaration of function 'ffi_prep_closure_loc' is invalid in C99 [-Wimplicit-function-declaration]
    status = ffi_prep_closure_loc(ac->fn, &(ac->cif), &alien_callback_call, ac, ac->ffi_codeloc);
             ^
src/alien.c:567:5: warning: implicit declaration of function 'ffi_closure_free' is invalid in C99 [-Wimplicit-function-declaration]
    ffi_closure_free(ac->fn);
    ^
4 warnings generated.
  CCLD     src/alien_c.la
markdown doc/alien.md > doc/alien.html
/bin/sh: markdown: command not found
make[1]: *** [doc/alien.html] Error 127
make: *** [all] Error 2

Error: Build error: Failed building.

ワーニングとエラーが出ています。ワーニングはalienのインストールで出ています。エラーの方はalien理由ではなさそうです。どうもmarkdownがないのでエラーが出ているようです。これってドキュメントを作るだけなので、これがエラーでインストールできないのもどうなんでしょうか。

markdownのインストール

$ brew install markdown
==> Downloading https://homebrew.bintray.com/bottles/markdown-1.0.1.yosemite.bottle.tar.gz
######################################################################## 100.0%
==> Pouring markdown-1.0.1.yosemite.bottle.tar.gz
🍺  /usr/local/Cellar/markdown/1.0.1: 2 files, 35.6KB

alienのインストール4回目

$ CFLAGS='-L/usr/local/opt/libffi/lib' luarocks install alien
Installing https://luarocks.org/alien-0.7.1-2.src.rock...
Using https://luarocks.org/alien-0.7.1-2.src.rock... switching to 'build' mode
./bootstrap && ./configure LUA=/usr/local/bin/lua CPPFLAGS='-I/usr/local/include -I/usr/include' LDFLAGS=-L/usr/lib --prefix=/usr/local/lib/luarocks/rocks-5.2/alien/0.7.1-2 --libdir=/usr/local/lib/luarocks/rocks-5.2/alien/0.7.1-2/lib --datadir=/usr/local/lib/luarocks/rocks-5.2/alien/0.7.1-2/lua && make clean && make

...

Updating manifest for /usr/local/lib/luarocks/rocks-5.2
No existing manifest. Attempting to rebuild...
alien 0.7.1-2 is now built and installed in /usr/local (license: MIT/X11)

できました。

確認

$ /usr/local/bin/lua
Lua 5.2.4  Copyright (C) 1994-2015 Lua.org, PUC-Rio
> require "alien"