lua5.1.4でカスタムrequireを実現するloader関数

4724 ワード

最初は単純に自分のC関数をpackageに置き換えるだけだと思っていた.loaders[2](インデックス2はluaのファイルローダ)ではOKですが、実際にはそうですが、このような代価はファイル検索ですね.判断の山は自分でしなければなりません.これらのlua自体はすでに実現しているので、必ず直接持ってきて使います.しかし問題が来て、直接簡単なpackageを発見しました.loaders[2]=myloadfuncは失敗した.このエラーが投げ出されます.
luaL_error(L, LUA_QL("package.%s") "must be a string", pname);
環境、これまでこのものの概念がずっとはっきりしていなかったので、私もすぐに理解したくありませんでした.そこでGoogleは、検索できる唯一の役に立つものは雲風ブログの文章で、関数の環境を先に取得してから、自分の関数に設定すると言っていました....全然わかりません.簡単すぎます.結局、私たち入門級の選手は全然考えていません.APIを探して、getfenvがあることを発見して、それから便利なために直接dostringで設定してみて、結果は失敗しました.印刷すると、何を取得しても環境は同じテーブルであることがわかります.仕方なく环境の概念を理解して、たぶん理解して、そこでその概念によって、どうしても得られないようで、结局あなたは関数の中でやっと环境を得ることができて、あるいは1つの闭包に戻ってやっと関数の中の环境を得ることができます.しかし、やはり雲風のやり方を考えて、CAPIが環境表を手に入れることができるかどうかを試してみたほうがいいです.答えは肯定的で、CAPIはpackageを得ることができます.loaders[2]の環境テーブル.しかしCAPIの操作が下手で、半日やってもうまくいかなかったので、実はtableの設置方法を間違えて、自分のCFunctionをキーとしてloadersの中に入れてしまいました.半日探して、以前やった操作を見て、やっと原因を見つけました.変更後、ファイルを繰り返しロードするエラーが発生し、半日デバッグしたところ、自分がファイル名を書き間違えたことに気づき、低級なエラーが発生しました.ついにすべてが正常になり、涙があふれた.カスタマイズされたrequireがあり、以前に実装されたluaを加えます.Readerは、暗号化されたluaファイルを完全に解析できます.
ネット上でluaに関する資料が少なすぎることを考慮して、出してみんなで分かち合います.
luajit2.0.1汎用
typedef int (*manual_load_file_func)(lua_State* L, const char* filename);
typedef int (*readable_func)(const char* filename);
static manual_load_file_func manul_load_file = NULL;
static readable_func readablefunc = NULL;

static void loaderror(lua_State *L, const char *filename)
{
	luaL_error(L, "error loading module " LUA_QS " from file " LUA_QS ":
\t%s", lua_tostring(L, 1), filename, lua_tostring(L, -1)); } static const char *pushnexttemplate(lua_State *L, const char *path) { const char *l; while (*path == *LUA_PATHSEP) path++; /* skip separators */ if (*path == '\0') return NULL; /* no more templates */ l = strchr(path, *LUA_PATHSEP); /* find next separator */ if (l == NULL) l = path + strlen(path); lua_pushlstring(L, path, (size_t)(l - path)); /* template */ return l; } static const char *searchpath (lua_State *L, const char *name, const char *path, const char *sep, const char *dirsep) { luaL_Buffer msg; /* to build error message */ luaL_buffinit(L, &msg); if (*sep != '\0') /* non-empty separator? */ name = luaL_gsub(L, name, sep, dirsep); /* replace it by 'dirsep' */ while ((path = pushnexttemplate(L, path)) != NULL) { const char *filename = luaL_gsub(L, lua_tostring(L, -1), LUA_PATH_MARK, name); lua_remove(L, -2); /* remove path template */ if (readablefunc && readablefunc(filename)) /* does file exist and is readable? */ return filename; /* return that file name */ lua_pushfstring(L, "
\tno file " LUA_QS, filename); lua_remove(L, -2); /* remove file name */ luaL_addvalue(&msg); /* concatenate error msg. entry */ } luaL_pushresult(&msg); /* create error message */ return NULL; /* not found */ } static const char *findfile(lua_State *L, const char *name, const char *pname) { const char *path; lua_getfield(L, LUA_ENVIRONINDEX, pname); path = lua_tostring(L, -1); if (path == NULL) luaL_error(L, LUA_QL("package.%s") " must be a string", pname); return searchpath(L, name, path, ".", LUA_DIRSEP); } static int lua_file_from_manual_func(lua_State *L) { const char *filename; const char *name = luaL_checkstring(L, 1); filename = findfile(L, name, "path"); if (filename == NULL) return 1; /* library not found in this path */ if (manul_load_file && manul_load_file(L, filename) != 0) loaderror(L, filename); return 1; /* library loaded successfully */ } void InitManualFunction(lua_State *L, manual_load_file_func loadfilefunc, readable_func readalbefunc_in ) { manul_load_file = loadfilefunc; readablefunc = readalbefunc_in; lua_getglobal(L,"package"); lua_getfield(L,-1,"loaders");//package.loaders lua_pushnumber(L, 2); lua_gettable(L, -2);//package.loaders[2] lua_pushnumber(L,2);// , C lua_pushcfunction(L,lua_file_from_manual_func);// C lua_getfenv(L,-3);// int ret=lua_setfenv(L,-2);// lua_settable(L,-4);// lua_pop(L,3);// }

次の操作を行います.
	lua_State* L = luaL_newstate();
	luaL_openlibs(L);

	InitManualFunction(L, my_load_file, readable);
	int status =luaL_dofile(L,"Test.lua");
	if (status && !lua_isnil(L, -1))
	{
		const char* error = lua_tostring(L, -1);
		printf("      ,    :%s
",error); lua_pop(L, 1); } lua_close(L);