■ util
■ lua_type
SYNTAX
int lua_type (lua_State *s, int index );
DESC
index で指定した値の型を返す。
LUA_TNIL
LUA_TNUMBER
LUA_TBOOLEAN
LUA_TSTRING
LUA_TTABLE
LUA_TFUNCTION
LUA_TUSERDATA
LUA_TTHREAD
LUA_TLIGHTUSERDATA
■ lua_typename
SYNTAX
const char *lua_typename (lua_State *L, int tp);
DESC
lua_type で取得した型から型名を返す。
int t = lua_type( s, idx );
printf( "%d %s", idx, lua_type(s, t) );
■ lua_gettop
SYNTAX
int lua_gettop (lua_State *)
DESC
スタックトップのインデックスを返す。
インデックスは1から始まるのでスタックサイズを取得できる。
■ スタック操作
POINT
1つの関数内で使用できる, stack の大きさは 256 程度
limits.h MAXSTACK で変更できる。
■ lua_pop
SYNTAX
void lua_pop (lua_State *L, int n);
DESC
stack 上位から [ N個 ]の要素を取り除く.
POINT
stack 数以上を削除すると, 空になる
■ lua_remove
SYNTAX
void lua_remove (lua_State *s, int index);
DESC
指定した有効なインデックスの要素を取り除き、 上の要素をずらして隙間を埋める
疑似インデックスは、実際のスタック位置でないため指定できない
■ lua_settop
SYNTAX
lua_settop( lua_State *, int index );
DESC
index 番目の要素を top にして それより上を削除 ( メタファは上を刈り取る )
余計な値を除去する時に使う。
現在値より上段を指定すると nil で埋められる。
// index 0 を指定するとスタックは空( というかインデックス位置が移動するため無効 )になる
< - 現在地( 3 )
------- -------
A
------- -------
B
------- ------- < - ( 0 番目 )
lua_settop( s, 2 );
-------- --------
key -->
-------- --------
table
-------- --------
bbb bbb < -- 2 番目をトップに指定
-------- --------
ccc ccc
-------- --------
■ スタックからの取得
POINT
Lua から C の関数を呼ぶときに
Lua で引数を指定して
C 側からスタックに積まれた引数を取得。
スタックの要素の位置は +- で指定できる。
-2 というのは stack 上位から2 番目の要素
+ : 下から N 番目
- : 上から N 番目
[ ] < - -1
[ ]
[ ]
[ ] < - 1
仮想スタックは Lua と Host が data を交換する Object
Lua が C の関数をコールする際は, 以前のスタックを破壊しないように, 新規stackを作成する.
スタックは関数ごとに用意される. ( というより, Arg 以下が隠される. )
lua_gettop() で確認できる。
stack は関数ごとに用意される.
[ 関数の中では ] [ stack が 1 から利用 ]される. -> ( 厳密には 不要な部分が隠蔽される )
3 param, 2 ret
// prm
---
3
---
2
---
1
---
// ret ( 終わった時点で stack にのっている点に注意. )
---
2
---
1
---
■ lua_tonumber
SYNTAX
lua_Number lua_tonumber (lua_State *L, int index);
DESC
index の位置にある値を lua_Number 型に変換して返す。
数値 または 数値に変換できる文字列である必要がある。
値を参照するだけで、スタックの数は変わらない。
RET
0 : 変換できなかった。
STACK
[-0, +0, -]
-- 1番目の引数から順番にスタックにつまれる。
add( 100, 200 );
----------
200
----------
100
----------
// C 側は引数をスタックから取得して何かの処理をして、必要なら結果をスタックにのせる。
int l_add( lua_State *s ) {
int arg0 = lua_tonumber( s, -2 ); // 上から 2 番目をとる
int arg1 = lua_tonumber( s, -1 ); // 上から 1 番目をとる
int ret = arg0 + arg1;
lua_pushnumber( ret ); // スタックに結果をつむ
return 1; // 結果の数を Lua に教える
}
■ lua_touserdata
SYNTAX
void *lua_touserdata (lua_State *L, int index);
DESC
指定 index 値がフルユーザーデータ( または lightuserdata )であれば
そのブロックのアドレスを返す
lightuserdata であれば、そのポインタを返す
どちらでもなければ null
-- Window のポインタを受け取り、
w = CreateWindow();
-- ポインタ経由で操作してもらう。
SetWindowText( w, "test" );
SetWindowSize( w, 600, 400 );
local w, h = GetWindowSize( w );
l_createWindow( lua_State *) {
lua_newuserdata( s );
Window p = new Window();
return 1;
}
l_setWindowText( lua_State *) {
lua_touserdata( s, -2 );
lua_tostring ( s, -1 );
p->setText( s )
}
■ lua_tostring
SYNTAX
const char *lua_tostring (lua_State *L, int index);
DESC
lua_tolstring を呼ぶのと同じ
WARNING
Lua -> C への 文字列の受け渡し( adress )は Lua の GC によって回収される可能性がある
POINT
逆に C -> Lua ( lua_pushstring() ) は 文字列をコピーするので
C 側での文字列のメモリは開放、変更をしてもよい。
■ lua_tolstring
SYNTAX
const char *lua_tolstring (lua_State *L, int index, size_t *len);
DESC
指定 index がさす値を 文字列に変換する.( stack 内が変化する )
index は [ 文字列 | 数値 ] を指す必要あり
len != NULL: 文字数をセット.
WARNING
stack 内部の alignment された pointer をかえす
( GC される可能性あり )
■ lua_getglobal
SYNTAX
void lua_getglobal( lua_State *s, const char *name );
DESC
lua_getfield の限定版
グローバル変数 name の値をスタックに積む。
STACK
[-0, +1, e]
POINT
マクロとして定義されている。
#define lua_getglobal(L,s) lua_getfield(L, LUA_GLOBALSINDEX, s)
POINT
ブロック外で定義した Var, Fn はすべて TblGlobal に存在する.
-->
-------- --------
fn | var
-------- --------
string string
-------- --------
-- lua
config = {
width = 600,
height = 400,
};
// cpp
{
lua_getglobal( s, "config" );
lua_getfield( s, -1, "width" );
int v = luaL_checknumber( s, -1 );
}
■ 生成
■ lua_createtable
SYNTAX
void lua_createtable (lua_State *L, int narr, int nrec);
STACK
[-0, +1, m]
DESC
空のテーブルを作成してスタックに追加。
The new table has space pre-allocated for narr array elements
and nrec non-array elements.
This pre-allocation is useful
when you know exactly how many elements the table will have.
■ lua_newuserdata
SYNTAX
void *lua_newuserdata (lua_State *, size_t size);
STACK
[-0, +1, m]
DESC
指定 size の メモリをわりあて, そのアドレスをもつ fulluserdata をスタックにつむ。
fulluserdata は メモリブロックをあらわし, 独自の[ metatable ] を持つことができる。
table も metatable を持つことができる。
WARNING
Lua が解放するので free() 禁止.
GC 回収の際に memory address を変更する場合もあるかも
POINT
TblGbl , Tbl に値をセットしておくことで, [ 使用中 ]の扱いになるので, 解放はされない.
local 変数だと問題がある。
data が必要なくなった場合は, [ __gc ] に指定する MetaMethod を利用する.
-------- --------
userdata
-------- --------
number --> number
-------- --------
int create_rgb( lua_state *s )
{
char *data;
// 4 Byte 確保. ( Lua 版 malloc と同じ )
data = (char *)lua_newuserdata( s, 4 );
memsset( data, 0, 4 );
return 1;
}
■ lua_newtable
SYNTAX
void lua_newtable (lua_State *s);
DESC
新しい空のテーブルを作ってスタックに積む
lua_createtable(L, 0, 0) と同じ。
-------- --------
table
-------- --------
number --> number
-------- --------
■ lua_pushinteger
SYNTAX
void lua_pushinteger (lua_State *s, lua_Integer n);
DESC
値 n を持つ数値をスタックに積む
■ lua_pushnumber
SYNTAX
void lua_pushnumber (lua_state *s, lua_Number n);
desc
n を stack top へ積む。
WARNING
うけとる文字列は, Lua 側でGCされる可能性あり
-------- --------
number
-------- --> --------
string string
-------- --------
■ lua_pushnil
SYNTAX
void lua_pushnil (lua_State *s);
desc
nil 値を stack に積む.
■ lua_pushvalue
SYNTAX
void lua_pushvalue (lua_State *L, int index);
DESC
指定した有効なインデックスにある要素の[ コピー ]をスタックに積む
有効な index top でなくても OK
STACK
[-0, +1, -]
lua_pushvalue( s, -1 );
-------- --------
table
-------- --> --------
table table
-------- --------
■ lua_setfield
SYNTAX
void lua_setfield (lua_State *L, int index, const char *key);
STACK
[-1, +0, e]
DESC
index で指定したテーブルに key の名前でスタック最上段の値を登録する。
値はポップされる。
table[ key ] = value という設定をする。
Lua の中では, newindex meta method が呼ばれる可能性がある.
Tbl に G を指定すれば, VarGbl にも指定可能.
As in Lua,
this function may trigger a metamethod for the "newindex" event
lua_pushnumber( s, 10 );
lua_setfield( s, -2, "test" );
-------- --------
10 -->
-------- --------
table table( test=10 )
-------- --------
■ lua_settable
SYNTAX
void lua_settable (lua_State *L, int index);
DESC
スタック最上位に値、キーをつみ、
index で指定したテーブルの位置にフィールドを追加する。
POINT
lua_setfield() は特殊系
-------- --------
val -->
-------- --------
key
-------- --------
table table
-------- --------
POINT
newindex event の MetaMethod を呼ぶ.
■ lua_rawset
SYNTAX
void lua_rawset (lua_State *L, int index);
DESC
lua_settable と同じだが 生の代入である点が異なる (メタメソッドを呼ばない)。
index は table を指す index
stack から { KEY, VAL } == {下, 上}は pop される. --> field と同じと考えよう ^ ^/
VAL
---
KEY
これと同じ
t = {a=10, b=20};
lua_rawset( s, LUA_ENVIRONINDEX );
lua_rawset( s, -3 ); // stack top から 3番目の table へアクセス
■ lua_rawget
SYNTAX
void lua_rawget (lua_State *L, int index);
DESC
lua_gettable と同じ。
スタック最上段につんだキーの値で index が指すテーブルから値をとる。
metamethod は起動しない。
t = {a=10, b=20}; Lua でやっていることを, LuaAPI でしているだけ
lua_rawset( s, LUA_ENVIRONINDEX );
lua_rawset( s, -3 ); // stack top から 3番目の table へアクセス
POINT
指定した KEY がない場合は,
nil をスタックトップへ返す。
■ lua_rawgeti
SYNTAX
void lua_rawgeti (lua_State *s, int idxTbl, int n );
DESC
lua_rawget のキーの値を整数の n に限定した関数。
table[ n ] の結果をスタックへ積む。
( MetaMethod はよばれない )
STACK
[-0, +1, -]
POP
tbl[n];
lua_rawgeti( s, -2, 1 );
-------- --------
value
-------- --------
string --> string
-------- --------
table table
-------- --------
■ lua_getfield
SYNTAX
void lua_getfield (lua_State *L, int index, const char *k);
desc
index が指す table["k"] の値を stack top へ積む。
key は stack top の値
field 名を指定できるのが point
lua_rawset( s, LUA_ENVIRONINDEX );
POP
KEY の値に対応する VAL
POINT
指定した KEY がない場合は nil を返す。
-->
-------- --------
number
-------- --------
tbl tbl
-------- --------
// グローバルテーブルにアクセス
lua_getfield( s, LUA_GLOBALSINDEX, nameKey );
■ lua_gettable
SYNTAX
void lua_gettable (lua_State *L, int index);
DESC
キーとなる値をスタックトップへつむ
index が指す テーブル["key"] の値をスタックが積まれ、
キーの値はスタックから捨てられる。
( また MetaMethod の index イベントがトリガーされる )
STACK
[-1, +1, e]
Ex.
lua_rawset( s, LUA_ENVIRONINDEX );
POINT
lua_getfield() は lua_gettable() のキーの型を文字列に限定した関数
指定した KEY がない場合は nil を返す.
-->
-------- --------
key value
-------- --------
table table
-------- --------
void lua_arraygeti( lua_state *s, int tblindex, int i )
{
// stack 最上位に 配列の index をセット
lua_pushnumber( s, i );
lua_gettable( s, tblindex );
}
■ lua_insert
SYNTAX
void lua_insert (lua_State *L, int index);
STACK
[-1, +1, -]
DESC
スタック最上段の値を index の位置へ移動する。
index の位置より上の値は上へシフトする。
-->
-------- --------
string number
-------- --------
number string
-------- --------
table table
-------- --------
■ lua_setglobal
SYNTAX
void lua_setglobal (lua_State *L, const char *name);
DESC
スタック最上段の値を指定した名前でグロバール変数として登録する。
登録する値はスタックからポップされる。
関数がpushされていれば関数に名前をつけて公開することになる。
STACK
[-1, +0, e]
#define lua_setglobal(L,s) lua_setfield(L, LUA_GLOBALSINDEX, s)
lua_setglobal( "testfunc" )
-------- --------
function -->
-------- --------
table table
-------- --------
■ lua_pushcfunction
SYNTAX
void lua_pushcfunction (lua_State *L, lua_CFunction f);
STACK
[-0, +1, m]
DESC
関数へのポインタを受け取り、関数型のLua値をスタックに積む
関数のシグネーチャは一致させること。
POINT
lua_pushcclosure(L, f, 0) と同等
これによって、Lua Script 内の任意の場所から関数呼び出しができる。
POINT
#define lua_pushcfunction(L,f) lua_pushcclosure(L,f,0)
#define lua_register(L,n,f) (lua_pushcfunction(L, f), lua_setglobal(L, n))
■ lua_register
DESC
C の関数を lua の関数として登録する
lua_register( s, l_func, "func");
■ lua_pushcclosure
SYNTAX
void lua_pushcclosure (lua_State *L, lua_CFunction fn, int n );
STACK
[-n, +1, m]
DESC
Cのクロージャをスタックへつむ。
このとき関連した値を設定できる。
関連づける値は先にスタックへ積んでおく。
クロージャが作成されるとこの値はスタックからポップされる。
lua_pushcclosure ( s, fn, 2 );
-------- --------
arg1 -->
-------- --------
arg0 --> function(arg0, arg1)
-------- --------
table table
-------- --------
aaa aaa
-------- --------
■ lua_pushlightuserdata
SYNTAX
void lua_pushlightuserdata (lua_state *s, void *p);
DESC
lightuserdata(ポインタ)をスタックに積む
POINT
lightuserdata とは host object のポインタのこと
作成はせず、メタテーブルも持たず、(作成しないので) 回収もされない
// C 側で Window をつくり
int CreateWindow( lua_State *s )
{
void *p = new Window( 1 );
lua_pushlightuserdata( s, p );
return 1;
}
// 操作させる
int SetWindowSize( lua_State *s )
{
Window* p = (Window *)lua_touserdata(s, -1);
int i = lua_tonumber(s, -2);
p->setSize( i );
}
-- lua
local p = CreateWindow();
SetWindowSize( p, 100 );
■ C Closures
C の関数を作るときに、特定の値を関連づけることができる。
これらは upvalue と呼ばれる。
upvalue は関数をコールされたときに参照できる。
参照へのインデックス( 最大 256 )は lua_upvalueindex を利用する。
■ メタテーブル
通常のテーブルと同じだが、
メタテーブルのキーに対して, 関数などを設定することで + などの演算を上書きして
独自の動作をさせることができる
C++ での operator +() と同じ。
Lua の各値はメタテーブルをもつ。
クラスのインスタンスを作ったときに メタテーブルを設定しておくと
+ などで独自の設定ができる。
メタテーブルのキーは getmetatable() でリストできる。
Every value in Lua can have a metatable.
This metatable is an ordinary Lua table that
defines the behavior of the original value
under certain special operations.
You can change several aspects of the behavior of operations over a value
by setting specific fields in its metatable.
For instance,
when a non-numeric value is the operand of an addition,
Lua checks for a function in the field "__add" in its metatable.
If it finds one,
Lua calls this function to perform the addition.
We call the keys in a metatable events and the values metamethods.
In the previous example,
the event is "add" and the metamethod is the function that performs the addition.
You can query the metatable of any value
through the getmetatable function.
You can replace the metatable of tables
through the setmetatable function.
You cannot change the metatable of other types from Lua (except by using the debug library);
you must use the C API for that.
Tables and full userdata have individual metatables
(although multiple tables and userdata can share their metatables).
Values of all other types share one single metatable per type; that is,
there is one single metatable for all numbers, one for all strings, etc.
A metatable controls how an object behaves in arithmetic operations,
order comparisons,
concatenation,
length operation,
and indexing.
A metatable also can define a function to be called
when a userdata is garbage collected.
For each of these operations Lua associates a specific key called an event.
When Lua performs one of these operations over a value,
it checks whether this value has a metatable with the corresponding event.
If so, the value associated with that key (the metamethod) controls
how Lua will perform the operation.
Metatables control the operations listed next.
Each operation is identified by its corresponding name.
The code shown here in Lua is only illustrative;
the real behavior is hard coded in the interpreter
and it is much more efficient than this simulation.
All functions used in these descriptions (rawget, tonumber, etc.) are described in §5.1.
In particular,
to retrieve the metamethod of a given object,
we use the expression
metatable(obj)[event]
■ lua_setmetatable
SYNTAX
int lua_setmetatable (lua_State *L, int index);
DESC
index で指定したオブジェクトにスタック最上段のテーブルをメタテーブルとして設定する。
最上段のテーブルはPOPされる。
lua_setmetatable( s, -2 );
-------- --------
table -->
-------- --------
userdata userdata(table)
-------- --------
aaa aaa
-------- --------
■ luaL_newmetatable
SYNTAX
int luaL_newmetatable (lua_State *L, const char *tname);
DESC
registory( table ) に KEY [ tname ] があれば, 0 を返す.
そうでなければ, userdata の metatable として使う 新しい table を作る.
registory tname に関連づいた値( VAL )を stack に積む.
■ lua_getmetatable
SYNTAX
int lua_getmetatable (lua_State *L, int index);
DESC
index がさすオブジェクトが持つ metatable を stacktop へつむ.
RET
0 : 失敗。index が無効。または 指定したオブジェクトが metatable をもっていない。
■ 型チェック
WARNING
[ 型を調べる ]ことで適切な処理をする
スタックの操作を間違えると処理がとまる。
■ lua_isstring
■ lua_isfunction
■ lua_istable
SYNTAX
int lua_istable (lua_State *L, int index);
DESC
指定した index のさす値がテーブルであれば1、そうでなければ0を返す
■ lua_isnil
SYNTAX
int lua_isnil (lua_State *L, int index);
DESC
指定 index の値が nil ならば 1 else 0
■ luaL_checkstring
SYNTAX
const char *luaL_checkstring (lua_State *L, int narg);
DESC
関数の第 narg 引数が文字列であるかをチェックし
その文字列を返す
チェックに不合格ながらエラーをなげる。
POINT
Lua -> C
■ luaL_checknumber
SYNTAX
lua_Number luaL_checknumber (lua_State *L, int narg);
DESC
関数の第 narg 引数が数値であるかをチェックし
その数値を返す
stack から値を取得するので, 関数呼び出しでなくても利用可能.
この場合は stack 全体を index 指定することになる.
関数の引数は指定した順番に stack にのる。
POINT
スクリプトの引数のチェックができる
-> number expected, got string
■ luaL_typerror
SYNTAX
int luaL_typerror (lua_State *L, int narg, const char *tname);
DESC
次の message を出力する
型に対してアサートする。
< location>: bad argument < narg> to < function> (< tname> expected, got < realt>)
■ luaL_checkudata
SYNTAX
void *luaL_checkudata (lua_State *L, int narg, const char *tname);
DESC
関数の第 narg 引数が [ 型 tname ] のユーザーデータであるかチェックする
■ その他
■ lua_error
SYNTAX
int lua_error (lua_State *L);
STACK
[-1, +0, v]
DESC
Lua のエラーを発生させる
スタックトップの値がエラーメッセージに使われる。
long jump を利用しないため、戻ることはない。
■ luaL_dofile
SYNTAX
void luaL_dofile( s, const char *path );
DESC
path から lua file を読み込む.
function は [ load ] する && 実行文は そのまま[ 実行 ]
-> LUA_GLOBALSINDEX がさす table に格納される
= { "nameFunction", funcbody };
関数 はたぶん reload される ?
-> table の要素数を取得すれば OK
#define luaL_dofile(L, fn) (luaL_loadfile(L, fn) || lua_pcall(L, 0, 0, 0))
■ luaL_dostring
SYNTAX
luaL_dostring( s, "code...");
DESC
C言語から Lua interpreter 呼んで, 処理をする。
RET
0 : 成功
!0 : 失敗
POINT
Lua での制御タイミングを提供する。
■ luaL_loadfile
SYNTAX
int luaL_loadfile(lua_State *L, const char *filename);
DESC
ファイルから LuaChunk をロードして compile した Chunk を Stack に積む
■ lua_call
SYNTAX
void lua_call(lua_State *s, int nrArg, int nrRet );
DESC
Lua 関数を C からコールする。
コールする関数と引数の順番にスタックへ積む。
関数の戻値は順番通りに (最初の戻値が最初に) スタックに積まれる
PUSH
返値( nrArg で指定 , LUA_MULTRET の場合は, すべての返値がかえる )
// 引数と関数がポップされて、結果がスタックにのる。
lua_call( s, 2, 1 );
-------- --------
arg -->
-------- --------
arg
-------- --------
function ret
-------- --------
POINT
nrArg : Lua は nrArg + 1 に関数があることを知る. ( 間違えると落ちる. )
func( arg1, arg2 ) には順番に Stk からセットされる.
nrRet : Lua に 何個の返値を Stk に積むか教える. ( -> 嘘つくと nil がつまれる )
// 以下の Lua Code と等価なことを C でやってみる.
// Lua の関数は LUA_GLOBALSINDEX に登録されている
lua_getfield(s, LUA_GLOBALSINDEX, "f");
lua_getglobal( s, "f" ); // これは同じ
// 第一引数をセット
lua_pushstring(s, "test");
// table も LUA_GLOBALSINDEX にある
lua_getfield(s, LUA_GLOBALSINDEX, "t");
lua_getfield(s, -1, "x"); /* t.xの結果(2番目の引数)を積む */
lua_remove(s, -2); /* スタックから `t' を取り除く */
// 第3引数
lua_pushinteger(s, 14);
// 3個の引数と1個の戻値で関数をコール
lua_call(s, 3, 1);
// Lua は global 変数は table[ KEY = VAL ] という特性をうまく利用している.
// グローバル変数 a に代入
lua_setfield(s, LUA_GLOBALSINDEX, "ret");
■ lua_pcall
SYNTAX
int lua_pcall(lua_State *s, int nrArg, int nrRet, int errfunc);
DESC
Protected Mode で関数をコールする。
エラーがなければ, lua_call と同じ処理。
エラーが発生すると、エラーメッセージをスタックへ積みエラーコードを返す。
errfunc で指定したエラーハンドラー関数があればエラーメッセージを引数に呼ばれる。
スタックトレースなどの追加情報をいれるために使う。
RET
0 : 成功
N : 失敗( lua.h )
POINT
失敗した場合は, lua_pop() する
■ lua_replace
SYNTAX
void lua_replace (lua_State *L, int index);
DESC
スタックトップの要素を指定した位置に移動する. ( 他の要素は変わらない点に注意. )
------ ------
string
------ ------
20 20
------ ------
30 string
------ ------
lua_repalce( s, 1 );
■ lua_getfenv
SYNTAX
void lua_getfenv (lua_State *s, int index);
desc
指定した index の値の環境テーブルをスタックに積む
PUSH
指定 index がさす table
■ lua_setfenv
SYNTAX
int lua_setfenv (lua_State *s, int index);
DESC
index が指す値が 関数, thread, userdata ならば, stacktop の
環境テーブルを新しい環境として set する.
POP
stacktop の EnvTable
■ luaL_openlibs
SYNTAX
void luaL_openlibs (lua_state *s);
DESC
指定したステートにすべての標準Luaライブラリを開く
String.print() などに利用すること
C SRT で実装されている.
■ luaL_getmetatable
SYNTAX
void luaL_getmetatable (lua_State *L, const char *tname);
DESC
registory( == table )の名前 tname に関連付けられたメタテーブルをスタックに積む
PUSH
tname に関連つけられた metatable
■ luaL_register
SYNTAX
void luaL_register( lua_State *L, const char *libname, const luaL_Reg *l);
DESC
stack top にその table をおく
libname がNULLでなければ新しいテーブル t を作成し、
それをグローバル変数 libname の値として設定し
POINT
Lua関数名 が KEY, Host関数 が VAL の Table
■ lua_rawequal
SYNTAX
int lua_rawequal (lua_State *L, int index1, int index2);
DESC
index1 と index2 がプリミティブに等しい
(つまりメタメソッドを呼ばない) とき1を返す。
そうでなければ0を返す。
どちらかのインデックスが有効でないときも0を返す。