[セットトップ]luaのファイルローダを変更し、luaファイルのロードをカスタマイズ


Luaは、実行ライブラリをロードするための高度なrequire関数を提供します.
1.requireはディレクトリ・ロード・ファイルを検索します
2.requireは、ファイルがロードされているかどうかを判断し、同じファイルを繰り返しロードしないようにします.
requireが使用するパスは、一般的に見られるパスとは異なり、一般的に見られるパスはディレクトリリストです.requireのパスは、虚ファイル名(requireのパラメータ)から実ファイル名に変換する方法を示すモードリストです.より明確には、各モードは、オプションの疑問符を含むファイル名である.一致するとLuaはまず疑問符を虚ファイル名に置き換え、そのようなファイルが存在するかどうかを確認します.存在しない場合は、同じ方法で2番目のモードでマッチングし続けます.たとえば、パスは次のとおりです.
?;?.lua;c:\windows\?;/usr/local/lua/?/?.lua

require「lili」を呼び出すと、これらのファイルを開いてみます.
lili
lili.lua
c:\windows\lili
/usr/local/lua/lili/lili.lua

requireが注目している問題は、セミコロン(モード間の区切り記号)と疑問符だけで、他の情報(ディレクトリ区切り記号、ファイル拡張子)はパスで定義されます.
パスを決定するために、Luaはまずグローバル変数LUA_をチェックする.PATHが文字列であるかどうかは、もしそうであれば、この列が経路であると考えられる.そうでない場合require環境変数LUA_をチェックPATHの値は、両方とも失敗した場合にrequireが固定パスを使用する(典型的な「?;?.lua」)
luaにファイルをロードするにはLUAしか構成できません.PATHの値.しかし、私たちがゲーム開発を行うとき、スクリプトのパスは千変万化する可能性があります.また、独自のファイルフォーマットにパッケージする必要がある可能性があります.このとき、オリジナルluaのロードには多くの問題が発生します.luaファイルをロードするより良い方法はありませんか.次に、この問題を解決するための方法を紹介します.
カスタムluaファイルローダ
私たちはluaファイルのローダをカスタマイズして、元のluaのローダを置き換えることができます.luaファイルをロードする方法は私たち自身で決めます.
まず、リソースファイルをロードするファイルシステムがあるはずです.なければ大丈夫です.自分でファイルをロードするインタフェースを書くことができます.次に、ファイルシステムまたは自分で書いたインタフェースを呼び出してメモリにファイルをロードするコードを書きます.
サンプルコードは次のとおりです.
/**   lua  
@param L lua     
@param name          
@return        0
*/
static int luaA_LoadFile(lua_State *L, const char *name)
{
	int status = -1;
	char filename[256];
	sprintf(filename, "%s.lua", name);
	FileSystem * pFileSystem = getFileSystem();
	if(pFileSystem != NULL)
	{
		Stream * pStream = pFileSystem->open(filename);
		if(pStream != NULL)
		{
			Uint32 nLength = pStream->getLength();
			if(nLength > 0)
			{
				//        
				char * pData = new char[nLength + 1]; pData[nLength] = 0;
				pStream->read(pData, nLength);
				//pStream->close();
				//         
				status = luaL_loadbuffer(L, pData, nLength, pData);
				delete[] pData;
			}
			pStream->release();
		}
	}
	return status;
}

上のロードファイルのコードは自分で実現できます.
次に、関数の上のロード関数をluaに設定し、luaのオリジナルローダを置き換えます.
static int luaA_SetLoader(lua_State *L, lua_CFunction fn)
{
	lua_getglobal(L, LUA_LOADLIBNAME);
	if (lua_istable(L, -1)) 
	{
		lua_getfield(L, -1, "loaders");
		if (lua_istable(L, -1))
 		{
			lua_pushcfunction(L, fn);
			lua_rawseti(L, -2, 2);
			return 0;
		}
	}
	return -1;
}


上記の2つのステップは基本的に完了しており、dofileでファイルをロードする場合もあるので、dofileにも似たような関数を書く必要があります.
static int luaA_DoFile(lua_State * L)
{
	size_t l;
	const char* sFileName = luaL_checklstring(L, 1, &l);
	if(sFileName != NULL )
	{
		luaA_LoadFile(L, sFileName);
		return 1;
	}
	return 0;
}

最後に、luaStateを初期化するときに設定すればいいです!
bool CLuaEngine::Create(bool bFromPackLoadLua)
{
	//    LUA 
	m_pLuaState = lua_open();
	if(m_pLuaState == NULL)
	{
		return false;
	}
	//          
	luaL_openlibs(m_pLuaState);
	//      Lua    
	luaA_SetLoader(m_pLuaState, luaA_LoadFile);
	//         api
	lua_register(m_pLuaState, "dofile", luaA_DoFile);
	
	return true;
}

では、luaファイルをそこに置いても、他のファイルをロードするように、luaファイルを好きなようにロードすることができます.