Lua luaopen_io 调用失败(转)

转自 http://wangjunle23.blog.163.com/blog/static/117838171201122233310573/

 

当我练习这一部分的时候,发现了一个问题——直接调用luaopen_io会使C程序crash。我使用VC++ 2005编译C代码,使用由lua-5.1.4生成的DLL。

    我查了Lua5.1参考手册,上面有几处涉及到了这个问题:

    To have access to these libraries, the C host program should call the luaL_openlibs function, which opens all standard libraries. Alternatively, it can open them individually by calling luaopen_base(for the basic library), ... and luaopen_debug (for the debug library). These functions are declared in  lualib.h and should not be called directly: you must call them like any other Lua C function, e.g., by using lua_call. 

        ...

        The luaopen_* functions (to open libraries) cannot be called directly, like a regular C function. They must be called through Lua, like a Lua function.

    大体意思就是说,你不能直接调用luaopen_*这些用来打开标准库的函数,你必须通过Lua来调用它们,比如使用lua_call。

    没有具体例子。那就靠自己琢磨了。

    之后我尝试用lua_pcall来修改对luaopen_io的直接调用,方法如下:

    lua_getglobal(L, "luaopen_io");

    lua_pcall(L, 0, 0, 0);

    但是结果令我很失望,lua_pcall返回2,即LUA_ERRRUN:运行时错误。

    然后我又尝试使用lua_cpcall,方法如下:

    lua_cpcall(L, luaopen_io, NULL);

    让人欣喜的是,它可以顺利运行。

    我不满足于现状,又翻出源码来看。在lua-5.1.4的源码中,linit.c这个文件里实现了luaL_openlibs这个函数,具体如下:

    static const luaL_Reg lualibs[] = {      

 {"", luaopen_base},       

{LUA_LOADLIBNAME, luaopen_package},      

{LUA_TABLIBNAME, luaopen_table},      

{LUA_IOLIBNAME, luaopen_io},      

{LUA_OSLIBNAME, luaopen_os},      

{LUA_STRLIBNAME, luaopen_string},      

{LUA_MATHLIBNAME, luaopen_math},      

{LUA_DBLIBNAME, luaopen_debug},      

{NULL, NULL}     };

 

    LUALIB_API void luaL_openlibs (lua_State *L)

{

      const luaL_Reg *lib = lualibs;      

for (; lib->func; lib++) {        

lua_pushcfunction(L, lib->func);        

lua_pushstring(L, lib->name);        

lua_call(L, 1, 0);       }    

}

    有源码,自然一切一目了然。

使用lua_call来间接调用luaopen_*的方法就是彩色字体显示的,

先将函数压栈,再将参数(库的名字)压栈,

最后调用lua_call(一个参数,0个返回值)。

 

首先,官方文档里面提到不要直接调用luaopen_*这些函数,那么就不要直接调用了。
不能直接调用的原因,我也不清楚。表面看来就是liolib.c中的luaopen_io函数的实现里调用了三个newfenv和一个lua_setfenv,它们创建并设置了新的环境。但是为什么新的环境就使程序crash了呢?以我现在的能力还无法给出解释。 使用lua_call、lua_pcall、lua_cpcall来间接调用这些函数。
具体3种方法:

      1. lua_cpcall(L, luaopen_io, NULL);

      2. lua_pushcfunction(L, luaopen_io);          lua_pushstring(L, LUA_IOLIBNAME);          lua_pcall(L, 1, 0, 0);      

      3. lua_pushcfunction(L, luaopen_io);          lua_pushstring(L, LUA_IOLIBNAME);          lua_call(L, 1, 0);

 

posted @   曦花  阅读(2924)  评论(0编辑  收藏  举报
编辑推荐:
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现
点击右上角即可分享
微信分享提示