mirror of
https://gitcode.com/JianFeeeee/LuaCangjia_api.git
synced 2026-09-19 16:42:48 +00:00
- lib/lua 替换为 Lua 5.2.4 官方源码; CMakeLists 补 lbitlib.c(5.2 linit 注册 bit32)、删 lutf8lib.c(5.2 无此文件) - I/O 重定向机制改造: 5.2 无 lua_getextraspace → iopath 指针存入 Registry 固定索引(IOPATH_REG_IDX=1), 回调经 get_iopath() 取回, free_lua 时释放 —— 该方案同样适用于更低版本 - typed interop 版本自适应: capture_result() 的 lua_isinteger 分支用 #if LUA_VERSION_NUM >= 503 包裹, 5.2 及以下所有数字统一 CJT_NUM - 测试跨版本适配: PackagePathConfig 接受 require 的两种返回语义; typed 数值断言 EXPECT_INT_OR_NUM 宏兼容有无 integer 子类型; 大整数保真断言仅对 5.3+ 生效(5.2 经 double 必然丢精度) - 验证: GTest 44/44 通过
606 lines
17 KiB
C++
Executable File
606 lines
17 KiB
C++
Executable File
#include "lua_cj_api.h"
|
||
#include <new>
|
||
|
||
// Lua 5.2/5.1 无 lua_getextraspace,改用 Registry 固定索引存储 iopath 指针
|
||
#define IOPATH_REG_IDX 1
|
||
|
||
extern "C"
|
||
{
|
||
#include <string.h>
|
||
#include "errors.h"
|
||
}
|
||
|
||
using namespace std;
|
||
|
||
bool check_luastatue(lua_State *L)
|
||
{
|
||
/*检查lua状态机状况*/
|
||
if(L == NULL)
|
||
{
|
||
errno = LUAERR_LUA_STACK;
|
||
return false;
|
||
}
|
||
//分为两部分写,防止空指针访问
|
||
if(lua_status(L) != LUA_OK)
|
||
{
|
||
errno = LUAERR_LUA_STATE;
|
||
return false;
|
||
}
|
||
return true;
|
||
}
|
||
|
||
int get_errno(void) { return errno; }//获取错误码
|
||
|
||
// 同步 typed 结果:把 Lua_runner 的 last_result_* 拷贝到外层 lua_runner 结构体
|
||
static void sync_typed_result(lua_runner *self, Lua_runner *runner)
|
||
{
|
||
self->tresult_type = runner->last_result_type;
|
||
self->tresult_int = runner->last_result_int;
|
||
self->tresult_num = runner->last_result_num;
|
||
self->tresult_bool = runner->last_result_bool;
|
||
}
|
||
|
||
/// @brief 加载lua文件到lua虚拟栈
|
||
/// @param self 使用init_lua_runner初始化的lua_runner结构体指针
|
||
/// @param path 需要加载的脚本的位置
|
||
/// @param name module命名(卸载库时指定)
|
||
/// @return 0代表正常结束,-1表示异常退出
|
||
int load_lib(void *selfd,const char *path,const char *name)
|
||
{
|
||
lua_runner* self = (lua_runner*)selfd;
|
||
Lua_runner *runner = (Lua_runner*)self->lua_obj;//还原对象
|
||
if(runner == NULL)
|
||
{
|
||
errno = LUAERR_LUA_STATE;
|
||
return -1;
|
||
}
|
||
if(runner->load_lib(path,name)==-1)
|
||
return -1;
|
||
return 0;
|
||
}
|
||
/// @brief 卸载lua虚拟栈中的lua文件
|
||
/// @param self 使用init_lua_runner初始化的lua_runner结构体指针
|
||
/// @param name module命名(loadlib时的name)
|
||
/// @return 0代表正常结束,-1表示异常退出
|
||
int unload_lib(void *selfd,const char *name)
|
||
{
|
||
lua_runner* self = (lua_runner*)selfd;
|
||
Lua_runner *runner = (Lua_runner*)self->lua_obj;//还原对象
|
||
if(runner == NULL)
|
||
{
|
||
errno = LUAERR_LUA_STATE;
|
||
return -1;
|
||
}
|
||
if(runner->unload_lib(name)==-1)
|
||
return -1;
|
||
return 0;
|
||
}
|
||
|
||
/// @brief 运行脚本(可指定入参)
|
||
/// @param self 使用init_lua_runner初始化的lua_runner结构体指针
|
||
/// @param path 脚本路径
|
||
/// @param arg 脚本的入参
|
||
/// @return 0代表正常结束,-1表示异常退出
|
||
int run(void *selfd,const char *path,const char *arg)
|
||
{
|
||
lua_runner* self = (lua_runner*)selfd;
|
||
//重定向输入到回调函数
|
||
Lua_runner *runner = (Lua_runner*)self->lua_obj;//还原对象
|
||
if(runner == NULL)
|
||
{
|
||
errno = LUAERR_LUA_STATE;
|
||
return -1;
|
||
}
|
||
if(runner->run(path,arg)==-1)
|
||
{
|
||
snprintf(self->result,MAX_RESULT,"%s",runner->reslt.c_str());
|
||
return -1;
|
||
}
|
||
snprintf(self->result,MAX_RESULT,"%s",runner->reslt.c_str());
|
||
return 0;
|
||
}
|
||
|
||
/// @brief 预加载lua文件到内存:加载文件、执行顶层代码、捕获返回的函数并存入 Registry,供后续 callfunction 多次调用
|
||
/// @param selfd init_lua_runner返回的void指针
|
||
/// @param path 需要加载的文件路径
|
||
/// @param name 函数名称(callfunction/unloadfunction时使用)
|
||
/// @return 0代表正常结束,-1表示异常退出
|
||
int loadfunction(void *selfd,const char *path,const char *name)
|
||
{
|
||
lua_runner* self = (lua_runner*)selfd;
|
||
Lua_runner *runner = (Lua_runner*)self->lua_obj;//还原对象
|
||
if(runner == NULL)
|
||
{
|
||
errno = LUAERR_LUA_STATE;
|
||
return -1;
|
||
}
|
||
if(runner->loadfunction(path,name)==-1)
|
||
return -1;
|
||
return 0;
|
||
}
|
||
|
||
/// @brief 卸载预加载的函数(释放 Registry 引用)
|
||
/// @param selfd init_lua_runner返回的void指针
|
||
/// @param name loadfunction加载时的函数名称
|
||
/// @return 0代表正常结束,-1表示异常退出
|
||
int unloadfunction(void *selfd,const char *name)
|
||
{
|
||
lua_runner* self = (lua_runner*)selfd;
|
||
Lua_runner *runner = (Lua_runner*)self->lua_obj;//还原对象
|
||
if(runner == NULL)
|
||
{
|
||
errno = LUAERR_LUA_STATE;
|
||
return -1;
|
||
}
|
||
if(runner->unloadfunction(name)==-1)
|
||
return -1;
|
||
return 0;
|
||
}
|
||
|
||
/// @brief 按名称调用已预加载的函数(从 Registry 取出,不消耗该函数,可重复调用)
|
||
/// @param selfd init_lua_runner返回的void指针
|
||
/// @param name loadfunction加载时的函数名称
|
||
/// @param arg 传递给函数的单参数(可为NULL)
|
||
/// @return 成功返回0,失败返回-1,并将lua出错原因拷贝至result中
|
||
int callfunction(void *selfd,const char *name,const char *arg)
|
||
{
|
||
lua_runner* self = (lua_runner*)selfd;
|
||
Lua_runner *runner = (Lua_runner*)self->lua_obj;
|
||
if(runner == NULL)
|
||
{
|
||
errno = LUAERR_LUA_STATE;
|
||
return -1;
|
||
}
|
||
if(runner->callfunction(name,arg)==-1){
|
||
snprintf(self->result,MAX_RESULT,"%s",runner->reslt.c_str());
|
||
return -1;
|
||
}
|
||
snprintf(self->result,MAX_RESULT,"%s",runner->reslt.c_str());
|
||
sync_typed_result(self, runner);
|
||
return 0;
|
||
}
|
||
|
||
/*-------------typed interop(v0.2.2)------------------------*/
|
||
|
||
int callfunction_int(void *selfd,const char *name,long long val)
|
||
{
|
||
lua_runner* self = (lua_runner*)selfd;
|
||
Lua_runner *runner = (Lua_runner*)self->lua_obj;
|
||
if(runner == NULL)
|
||
{
|
||
errno = LUAERR_LUA_STATE;
|
||
return -1;
|
||
}
|
||
if(runner->callfunction_int(name,val)==-1){
|
||
snprintf(self->result,MAX_RESULT,"%s",runner->reslt.c_str());
|
||
return -1;
|
||
}
|
||
snprintf(self->result,MAX_RESULT,"%s",runner->reslt.c_str());
|
||
sync_typed_result(self, runner);
|
||
return 0;
|
||
}
|
||
|
||
int callfunction_num(void *selfd,const char *name,double val)
|
||
{
|
||
lua_runner* self = (lua_runner*)selfd;
|
||
Lua_runner *runner = (Lua_runner*)self->lua_obj;
|
||
if(runner == NULL)
|
||
{
|
||
errno = LUAERR_LUA_STATE;
|
||
return -1;
|
||
}
|
||
if(runner->callfunction_num(name,val)==-1){
|
||
snprintf(self->result,MAX_RESULT,"%s",runner->reslt.c_str());
|
||
return -1;
|
||
}
|
||
snprintf(self->result,MAX_RESULT,"%s",runner->reslt.c_str());
|
||
sync_typed_result(self, runner);
|
||
return 0;
|
||
}
|
||
|
||
int callfunction_bool(void *selfd,const char *name,int val)
|
||
{
|
||
lua_runner* self = (lua_runner*)selfd;
|
||
Lua_runner *runner = (Lua_runner*)self->lua_obj;
|
||
if(runner == NULL)
|
||
{
|
||
errno = LUAERR_LUA_STATE;
|
||
return -1;
|
||
}
|
||
if(runner->callfunction_bool(name,val)==-1){
|
||
snprintf(self->result,MAX_RESULT,"%s",runner->reslt.c_str());
|
||
return -1;
|
||
}
|
||
snprintf(self->result,MAX_RESULT,"%s",runner->reslt.c_str());
|
||
sync_typed_result(self, runner);
|
||
return 0;
|
||
}
|
||
|
||
int callfunction_void(void *selfd,const char *name)
|
||
{
|
||
lua_runner* self = (lua_runner*)selfd;
|
||
Lua_runner *runner = (Lua_runner*)self->lua_obj;
|
||
if(runner == NULL)
|
||
{
|
||
errno = LUAERR_LUA_STATE;
|
||
return -1;
|
||
}
|
||
if(runner->callfunction_void(name)==-1){
|
||
snprintf(self->result,MAX_RESULT,"%s",runner->reslt.c_str());
|
||
return -1;
|
||
}
|
||
snprintf(self->result,MAX_RESULT,"%s",runner->reslt.c_str());
|
||
sync_typed_result(self, runner);
|
||
return 0;
|
||
}
|
||
|
||
int run_int(void *selfd,const char *path,long long val)
|
||
{
|
||
lua_runner* self = (lua_runner*)selfd;
|
||
Lua_runner *runner = (Lua_runner*)self->lua_obj;
|
||
if(runner == NULL)
|
||
{
|
||
errno = LUAERR_LUA_STATE;
|
||
return -1;
|
||
}
|
||
if(runner->run_int(path,val)==-1){
|
||
snprintf(self->result,MAX_RESULT,"%s",runner->reslt.c_str());
|
||
return -1;
|
||
}
|
||
snprintf(self->result,MAX_RESULT,"%s",runner->reslt.c_str());
|
||
sync_typed_result(self, runner);
|
||
return 0;
|
||
}
|
||
|
||
int run_num(void *selfd,const char *path,double val)
|
||
{
|
||
lua_runner* self = (lua_runner*)selfd;
|
||
Lua_runner *runner = (Lua_runner*)self->lua_obj;
|
||
if(runner == NULL)
|
||
{
|
||
errno = LUAERR_LUA_STATE;
|
||
return -1;
|
||
}
|
||
if(runner->run_num(path,val)==-1){
|
||
snprintf(self->result,MAX_RESULT,"%s",runner->reslt.c_str());
|
||
return -1;
|
||
}
|
||
snprintf(self->result,MAX_RESULT,"%s",runner->reslt.c_str());
|
||
sync_typed_result(self, runner);
|
||
return 0;
|
||
}
|
||
|
||
int run_bool(void *selfd,const char *path,int val)
|
||
{
|
||
lua_runner* self = (lua_runner*)selfd;
|
||
Lua_runner *runner = (Lua_runner*)self->lua_obj;
|
||
if(runner == NULL)
|
||
{
|
||
errno = LUAERR_LUA_STATE;
|
||
return -1;
|
||
}
|
||
if(runner->run_bool(path,val)==-1){
|
||
snprintf(self->result,MAX_RESULT,"%s",runner->reslt.c_str());
|
||
return -1;
|
||
}
|
||
snprintf(self->result,MAX_RESULT,"%s",runner->reslt.c_str());
|
||
sync_typed_result(self, runner);
|
||
return 0;
|
||
}
|
||
|
||
int run_void(void *selfd,const char *path)
|
||
{
|
||
lua_runner* self = (lua_runner*)selfd;
|
||
Lua_runner *runner = (Lua_runner*)self->lua_obj;
|
||
if(runner == NULL)
|
||
{
|
||
errno = LUAERR_LUA_STATE;
|
||
return -1;
|
||
}
|
||
if(runner->run_void(path)==-1){
|
||
snprintf(self->result,MAX_RESULT,"%s",runner->reslt.c_str());
|
||
return -1;
|
||
}
|
||
snprintf(self->result,MAX_RESULT,"%s",runner->reslt.c_str());
|
||
sync_typed_result(self, runner);
|
||
return 0;
|
||
}
|
||
|
||
int result_type(void *selfd){lua_runner*self =(lua_runner*)selfd;return self->tresult_type;}
|
||
long long result_int(void *selfd){lua_runner*self =(lua_runner*)selfd;return self->tresult_int;}
|
||
double result_num(void *selfd){lua_runner*self =(lua_runner*)selfd;return self->tresult_num;}
|
||
int result_bool(void *selfd){lua_runner*self =(lua_runner*)selfd;return self->tresult_bool;}
|
||
/*-------------typed interop------------------------*/
|
||
|
||
/// @brief 执行单句lua语句
|
||
/// @param selfd init_lua_runner返回的void指针
|
||
/// @param target 执行语句(字符串类型)
|
||
/// @return 成功返回0,失败返回-1,并将lua出错原因拷贝至result中
|
||
int dostring(void *selfd,const char *target){
|
||
lua_runner* self = (lua_runner*)selfd;
|
||
//重定向输入到回调函数
|
||
Lua_runner *runner = (Lua_runner*)self->lua_obj;//还原对象
|
||
if(runner == NULL)
|
||
{
|
||
errno = LUAERR_LUA_STATE;
|
||
return -1;
|
||
}
|
||
if(runner->dostring(target)==-1){
|
||
snprintf(self->result,MAX_RESULT,"%s",runner->reslt.c_str());
|
||
return -1;
|
||
}
|
||
snprintf(self->result,MAX_RESULT,"%s",runner->reslt.c_str());
|
||
return 0;
|
||
}
|
||
|
||
/// @brief 清理lua状态机缓存,虚拟栈,加载的包等
|
||
/// @param self 使用init_lua_runner初始化的lua_runner结构体指针
|
||
/// @return 0代表正常结束,-1表示异常退出
|
||
int cleanup(void *selfd)
|
||
{
|
||
lua_runner* self = (lua_runner*)selfd;
|
||
Lua_runner *runner = (Lua_runner*)self->lua_obj;//还原对象
|
||
if(runner == NULL)
|
||
{
|
||
errno = LUAERR_LUA_STATE;
|
||
return -1;
|
||
}
|
||
if(runner->clean()==-1)
|
||
return -1;
|
||
return 0;
|
||
}
|
||
|
||
/// @brief 释放lua状态机资源
|
||
/// @param self 使用init_lua_runner初始化的lua_runner结构体指针
|
||
/// @return 0代表正常结束,-1表示异常退出
|
||
int free_lua(void *selfd)
|
||
{
|
||
lua_runner* self = (lua_runner*)selfd;
|
||
// 释放 Registry 中的 iopath(若存在)
|
||
Lua_runner *runner = (Lua_runner*)self->lua_obj;
|
||
if (runner != NULL) {
|
||
lua_State *L = runner->get_lua_State();
|
||
if (L != NULL) {
|
||
lua_rawgeti(L, LUA_REGISTRYINDEX, IOPATH_REG_IDX);
|
||
iopath *p = (iopath*)lua_touserdata(L, -1);
|
||
lua_pop(L, 1);
|
||
delete p; // NULL 也安全
|
||
}
|
||
}
|
||
delete((Lua_runner*)self->lua_obj);
|
||
free(self);
|
||
return 0;
|
||
}
|
||
|
||
/*-------------重定向io操作------------------------*/
|
||
/* Lua 5.2/5.1 无 lua_getextraspace,改用 Registry 固定索引存储 iopath 指针 */
|
||
|
||
static iopath *get_iopath(lua_State *L)
|
||
{
|
||
lua_rawgeti(L, LUA_REGISTRYINDEX, IOPATH_REG_IDX);
|
||
iopath *r = (iopath *)lua_touserdata(L, -1);
|
||
lua_pop(L, 1);
|
||
return r;
|
||
}
|
||
|
||
static const char *full_path(lua_State *L, int isOut)
|
||
{
|
||
iopath *r = get_iopath(L);
|
||
static char buf[512];
|
||
snprintf(buf, sizeof(buf), "%s/%s", r->iopath, isOut ? "output" : "input");
|
||
return buf;
|
||
}
|
||
|
||
//劫持读取终端输入,触发回调
|
||
static int l_tty_read(lua_State *L)
|
||
{
|
||
iopath *r = get_iopath(L);
|
||
if (r->funcs.io_input) r->funcs.io_input();
|
||
const char *fname = full_path(L, 0);
|
||
FILE *fp = fopen(fname, "rb");
|
||
if (!fp) return luaL_error(L, "tty read open fail: %s", fname);
|
||
fseek(fp, 0, SEEK_END);
|
||
size_t sz = ftell(fp);
|
||
fseek(fp, 0, SEEK_SET);
|
||
char *tmp = (char*)lua_newuserdata(L, sz);
|
||
if(0 ==fread(tmp, 1, sz, fp))
|
||
return luaL_error(L, "tty fail to read input: %s", fname);
|
||
|
||
fclose(fp);
|
||
if(remove(fname) != 0)
|
||
{
|
||
errno = LUAERR_RESET_INPUT_FILE;
|
||
return luaL_error(L, "fail to reset input file: %s", fname);
|
||
}
|
||
lua_pushlstring(L, tmp, sz);
|
||
return 1;
|
||
}
|
||
|
||
|
||
//劫持到终端输出,输出结束触发回调
|
||
static int l_tty_write(lua_State *L)
|
||
{
|
||
iopath *r = get_iopath(L);
|
||
const char *fname = full_path(L, 1);
|
||
FILE *fp = fopen(fname, "a");
|
||
if (!fp) return luaL_error(L, "tty write open fail: %s", fname);
|
||
int n = lua_gettop(L);
|
||
for (int i = 1; i <= n; ++i)
|
||
if (lua_isstring(L, i)) fputs(lua_tostring(L, i), fp);
|
||
fclose(fp);
|
||
if (r->funcs.io_output) r->funcs.io_output();
|
||
return 0;
|
||
}
|
||
static int l_print(lua_State *L) {
|
||
iopath *r = get_iopath(L);
|
||
const char *fname = full_path(L, 1); // 输出到 output 文件
|
||
FILE *fp = fopen(fname, "a");
|
||
if (!fp) return luaL_error(L, "print redirect open fail: %s", fname);
|
||
|
||
int n = lua_gettop(L);
|
||
for (int i = 1; i <= n; ++i) {
|
||
if (i > 1) fputc('\t', fp);
|
||
const char *str = luaL_tolstring(L, i, NULL);
|
||
fputs(str, fp);
|
||
lua_pop(L, 1);
|
||
}
|
||
fputc('\n', fp);
|
||
fclose(fp);
|
||
|
||
if (r->funcs.io_output) r->funcs.io_output();
|
||
return 0;
|
||
}
|
||
|
||
/*空实现*/
|
||
static int l_tty_flush(lua_State *L)
|
||
{
|
||
(void)L;
|
||
return 0;
|
||
}
|
||
|
||
static int l_tty_close(lua_State *L)
|
||
{
|
||
(void)L;
|
||
return 0;
|
||
}
|
||
/*空实现(不需要)*/
|
||
|
||
static int l_tty_call(lua_State *L)
|
||
{
|
||
// 当尝试调用tty对象时,返回自身或执行某些操作
|
||
lua_pushvalue(L, 1); // 返回对象自身
|
||
return 1;
|
||
}
|
||
|
||
static void push_tty_file(lua_State *L, int isout, const luaL_Reg *fake_tty_meta)
|
||
{
|
||
lua_newuserdata(L, sizeof(int));
|
||
luaL_newmetatable(L, isout ? "tty_out" : "tty_in");
|
||
|
||
luaL_setfuncs(L, fake_tty_meta, 0);
|
||
lua_pushvalue(L, -1);
|
||
lua_setfield(L, -2, "__index");
|
||
|
||
// 添加__call元方法
|
||
lua_pushcfunction(L, l_tty_call);
|
||
lua_setfield(L, -2, "__call");
|
||
|
||
// 添加__tostring
|
||
lua_pushstring(L, isout ? "TTY_OUT" : "TTY_IN");
|
||
lua_setfield(L, -2, "__tostring");
|
||
|
||
lua_setmetatable(L, -2);
|
||
}
|
||
|
||
|
||
|
||
|
||
int redirecct_path(lua_State *L)
|
||
{
|
||
if(!check_luastatue(L)){
|
||
errno = LUAERR_LUA_STATE;
|
||
return -1;
|
||
}
|
||
iopath *p = get_iopath(L);
|
||
static const luaL_Reg fake_methods[] = {
|
||
{"read", l_tty_read},
|
||
{"write", l_tty_write},
|
||
{"flush", l_tty_flush},
|
||
{"close", l_tty_close},
|
||
{NULL, NULL}
|
||
};
|
||
|
||
/* 1. 把 io.output() 换成 tty 替身 */
|
||
push_tty_file(L, 1,fake_methods);
|
||
lua_getglobal(L, "io");
|
||
lua_pushvalue(L, -2);
|
||
lua_setfield(L, -2, "output"); /* io.output = 替身 */
|
||
lua_pop(L, 2);
|
||
|
||
/* 2. 把 io.input() 换成 tty 替身 */
|
||
push_tty_file(L, 0,fake_methods);
|
||
lua_getglobal(L, "io");
|
||
lua_pushvalue(L, -2);
|
||
lua_setfield(L, -2, "input"); /* io.input = 替身 */
|
||
lua_pop(L, 2);
|
||
lua_pushcfunction(L, l_print);
|
||
lua_setglobal(L, "print");
|
||
lua_getglobal(L, "io");
|
||
lua_pushcfunction(L, l_tty_read);
|
||
lua_setfield(L, -2, "read");
|
||
lua_pushcfunction(L, l_tty_write);
|
||
lua_setfield(L, -2, "write");
|
||
lua_pop(L, 1);
|
||
|
||
return 0;
|
||
}
|
||
/*----------------重定向io操作------------------------*/
|
||
|
||
//获取对象中的返回值
|
||
char *getresult(void *selfd){lua_runner*self =(lua_runner*) selfd;return self->result;}
|
||
|
||
|
||
/// @brief 初始化lua解释器
|
||
/// @param pathio 重定向io目录
|
||
/// @param pkgpath 用户包搜索目录
|
||
/// @param input 输入回调函数
|
||
/// @param output 输出回调函数
|
||
/// @return 0正常结束,-1异常退出
|
||
void *init_lua_runner(const char *pathio,const char *pkgpath,int(*input)(),int(*output)())//该函数挂载到cj构造函数中执行
|
||
{
|
||
//分配内存
|
||
lua_runner *self = (lua_runner*)malloc(sizeof(lua_runner));
|
||
// typed interop 字段初始化
|
||
self->tresult_type = CJT_NIL;
|
||
self->tresult_int = 0;
|
||
self->tresult_num = 0.0;
|
||
self->tresult_bool = 0;
|
||
//创建对象
|
||
self->lua_obj = (void*)new Lua_runner(pkgpath);
|
||
if(errno != 0)
|
||
return NULL;
|
||
if(self->lua_obj == NULL)
|
||
{
|
||
errno = LUAERR_CLASS_LOST;
|
||
return NULL;
|
||
}
|
||
//提取对象
|
||
Lua_runner *runner = (Lua_runner*)self->lua_obj;
|
||
//提取lua状态机
|
||
lua_State *L = runner->get_lua_State();
|
||
|
||
if(!check_luastatue(L)){
|
||
errno = LUAERR_LUA_STATE;
|
||
return NULL;
|
||
}
|
||
// Lua 5.2/5.1 无 extraspace:new 一个 iopath 存入 Registry
|
||
iopath *io_path = new (std::nothrow) iopath();
|
||
if(pathio == NULL)
|
||
{
|
||
delete io_path;
|
||
goto WITHOUT_REDIRECT;
|
||
}
|
||
|
||
if(io_path == NULL){
|
||
errno = LUAERR_CLASS_LOST;
|
||
return NULL;
|
||
}
|
||
|
||
//装载重定向函数
|
||
io_path->funcs.io_input = input;
|
||
io_path->funcs.io_output = output;
|
||
//装载重定向路径
|
||
strcpy(io_path->iopath,pathio);
|
||
//存入 Registry 固定索引供回调取用
|
||
lua_pushlightuserdata(L, (void*)io_path);
|
||
lua_rawseti(L, LUA_REGISTRYINDEX, IOPATH_REG_IDX);
|
||
//注册重定向
|
||
if(redirecct_path(L)==-1){
|
||
errno = LUAERR_LUA_STATE;
|
||
return NULL;
|
||
}
|
||
WITHOUT_REDIRECT:
|
||
return (void*)self;
|
||
}
|
||
|