読者です 読者をやめる 読者になる 読者になる

Flat Leon Works

アプリやゲームを作ってます。

【Lua組み込み】Luaスクリプトのファイル分割を独自のファイルロード処理で行う方法

require関数やdofile関数のファイルロード処理はカスタマイズできない

Luaスクリプトを書いていてファイル分割をしたくなった場合、Lua標準のrequire関数やdofile関数を使うと思います。

dofile( 'common.lua' )
dofile( 'util.lua' )

-- いろんな処理

問題なのはファイルロード処理を独自の方法で行いたい場合です。require関数やdofile関数はファイルロードにC標準関数のfopenを使うようになっており、ファイルロードをカスタマイズする仕組みも特に用意されていません。なので、ファイルのロード処理をfopenではなく別の方法で行わせたい場合はLuaソースコードを書き換えるしかありません。面倒くさいですね。

自分でファイルロード処理を行う関数を登録する

よく考えてみると、require関数やdofile関数にこだわる必要はありません。ファイルをロードしLuaスクリプトを実行するC関数を自分で作ってLuaに登録すればいいのです。

例えば、自作する関数の名前をincludeとした場合Luaスクリプト側はこうなります。

include( 'common.lua' )
include( 'util.lua' )

-- いろんな処理

このinclude関数の実装は以下のようになるでしょう。

// グルー関数の定義
int lua_include_glue( lua_State* p_luaState )
{
    const char* p_fileName = lua_tostring( p_luaState, -1 ); // include関数の引数を取得
    const char* p_luaCode = MyFileLoad( p_fileName ); // 独自のファイルロード処理
    luaL_dostring( p_luaState, p_luaCode ); // 文字列をLuaスクリプトとして実行
    lua_settop( p_luaState, 0 ); // スタックをクリア
    return 0; // Luaへの戻り値は無し
}
// グルー関数のLuaへの登録
lua_register( p_luaState, "include", lua_include_glue );

ポイントはluaL_dostringを使うことです。この関数を使うことでLuaにファイルロードさせるのではなく、自分でロードしたスクリプト文字列を実行させることができます。

まとめ

独自のファイルロード処理でLuaスクリプトをファイル分割したい場合は、自分で関数を作ってしまいましょう。