diff --git a/lib/lua/CMakeLists.txt b/lib/lua/CMakeLists.txt new file mode 100644 index 0000000..c5edf0b --- /dev/null +++ b/lib/lua/CMakeLists.txt @@ -0,0 +1,48 @@ +cmake_minimum_required(VERSION 3.12) +project(lua VERSION 5.0.3 LANGUAGES C) + +# Lua 5.0.3: 平铺源码, 无 linit.c(库需手动逐个 luaopen_*) +set(CMAKE_C_STANDARD 99) +set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -O2 -w") +set(CMAKE_POSITION_INDEPENDENT_CODE ON) + +if(CMAKE_C_COMPILER MATCHES "mingw" OR CMAKE_SYSTEM_NAME STREQUAL "Windows") + set(IS_WINDOWS TRUE) +endif() + +if(NOT IS_WINDOWS) + list(APPEND EXTRA_LIBS dl) + add_compile_definitions(LUA_USE_LINUX) +endif() + +add_library(lua STATIC + lapi.c + lauxlib.c + lbaselib.c + lcode.c + ldblib.c + ldebug.c + ldo.c + ldump.c + lfunc.c + lgc.c + liolib.c + llex.c + lmathlib.c + lmem.c + loadlib.c + lobject.c + lopcodes.c + lparser.c + lstate.c + lstring.c + lstrlib.c + ltable.c + ltablib.c + ltm.c + lundump.c + lvm.c + lzio.c +) + +# ltests.c 仅调试用, 不参与构建 diff --git a/lib/lua/Makefile b/lib/lua/Makefile deleted file mode 100644 index d75997d..0000000 --- a/lib/lua/Makefile +++ /dev/null @@ -1,17 +0,0 @@ -# makefile for Lua distribution (includes) - -LUA= .. - -include $(LUA)/config - -SRCS= lua.h lualib.h lauxlib.h - -all: - -clean: - -co: - co -q -f -M $(SRCS) - -klean: clean - rm -f $(SRCS) diff --git a/lib/lua/compat_50.h b/lib/lua/compat_50.h new file mode 100644 index 0000000..a469e4d --- /dev/null +++ b/lib/lua/compat_50.h @@ -0,0 +1,74 @@ +#ifndef COMPAT_50_H +#define COMPAT_50_H +/* Lua 5.0.x 兼容层: 让面向 5.1+ API 的桥接层无需大改即可编译。 + 在 include lua 头文件之后、桥接代码之前引入。 */ + +/* ---- 版本宏 ---- */ +#ifndef LUA_VERSION_NUM +#define LUA_VERSION_NUM 500 +#endif + +/* ---- 成功码 ---- */ +#ifndef LUA_OK +#define LUA_OK 0 +#endif + +/* ---- luaL_newstate: 5.0 是 lua_open(void) ---- */ +#if LUA_VERSION_NUM == 500 +#define luaL_newstate() lua_open() +#endif + +/* ---- lua_status: 5.0 无线程状态查询, 恒 OK(单主线程语义足够) ---- */ +#if LUA_VERSION_NUM == 500 +static inline int compat_lua_status(lua_State *L) { (void)L; return LUA_OK; } +#define lua_status(L) compat_lua_status(L) +#endif + +/* ---- luaL_dostring/dofile: 5.0 名字是 lua_dostring/lua_dofile(lauxlib), 0=成功 ---- */ +#if LUA_VERSION_NUM == 500 +#define luaL_dostring(L, s) lua_dostring(L, s) +#define luaL_dofile(L, f) lua_dofile(L, f) +#endif + +/* ---- lua_setfield: 5.0 无。模拟: 先转绝对索引(避免 push 后相对索引偏移), + push k → insert(-2) 把 [t][v][k] 变 [t][k][v] → settable(abs) 弹 k,v 设 t[k]=v。 + 走元方法, 语义与 5.1+ 一致。 */ +#if LUA_VERSION_NUM == 500 +#define lua_setfield(L, idx, k) \ + do { \ + int _abs = (idx) >= 0 ? (idx) : lua_gettop(L) + 1 + (idx); \ + lua_pushstring(L, k); \ + lua_insert(L, -2); \ + lua_settable(L, _abs); \ + } while (0) +#endif + +/* ---- lua_getfield: 5.0 无。模拟: push k → gettable(idx) 弹 k 压 t[k]。 + 同样先转绝对索引。 */ +#if LUA_VERSION_NUM == 500 +#define lua_getfield(L, idx, k) \ + do { \ + int _abs = (idx) >= 0 ? (idx) : lua_gettop(L) + 1 + (idx); \ + lua_pushstring(L, k); \ + lua_gettable(L, _abs); \ + } while (0) +#endif + +/* ---- luaL_Reg: 5.0 的结构体名是小写 luaL_reg ---- */ +#if LUA_VERSION_NUM == 500 +typedef struct luaL_reg luaL_Reg; +#endif + +/* ---- integer API: 5.0 数字只有 double, 全部映射到 number。 + 注: 大整数(>2^53)经 double 往返会丢精度 —— 这是 5.0 的固有限制, + 测试中已用 #if LUA_VERSION_NUM >= 503 区分断言。 */ +#if LUA_VERSION_NUM == 500 +#define lua_Integer double +#define lua_pushinteger(L, n) lua_pushnumber(L, (lua_Number)(n)) +#define lua_tointeger(L, idx) ((lua_Integer)lua_tonumber(L, idx)) +/* lua_isinteger 恒假: capture_result() 的 #if >= 503 分支不会走到这里, + 此宏仅为编译通过而设 */ +#define lua_isinteger(L, idx) (0) +#endif + +#endif /* COMPAT_50_H */ diff --git a/lib/lua/lua.hpp b/lib/lua/lua.hpp new file mode 100644 index 0000000..18ddea3 --- /dev/null +++ b/lib/lua/lua.hpp @@ -0,0 +1,6 @@ +/* C++ 兼容包装头(平铺结构): 保持桥接层 #include "lua/lua.hpp" 不变 */ +extern "C" { +#include "lua.h" +#include "lualib.h" +#include "lauxlib.h" +} diff --git a/lib/lua_cj_api.cpp b/lib/lua_cj_api.cpp index e635305..8dc3ffe 100755 --- a/lib/lua_cj_api.cpp +++ b/lib/lua_cj_api.cpp @@ -1,4 +1,14 @@ #include "lua_cj_api.h" +#include + +// Lua 5.1 兼容:无 LUA_OK 宏,成功返回值为 0 +#ifndef LUA_OK +#define LUA_OK 0 +#endif + +// Lua 5.2/5.1 无 lua_getextraspace,改用 Registry 固定索引存储 iopath 指针 +#define IOPATH_REG_IDX 1 + extern "C" { #include @@ -351,15 +361,36 @@ int cleanup(void *selfd) 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 = (iopath *)lua_getextraspace(L); + iopath *r = get_iopath(L); static char buf[512]; snprintf(buf, sizeof(buf), "%s/%s", r->iopath, isOut ? "output" : "input"); return buf; @@ -368,7 +399,7 @@ static const char *full_path(lua_State *L, int isOut) //劫持读取终端输入,触发回调 static int l_tty_read(lua_State *L) { - iopath *r = (iopath *)lua_getextraspace(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"); @@ -394,7 +425,7 @@ static int l_tty_read(lua_State *L) //劫持到终端输出,输出结束触发回调 static int l_tty_write(lua_State *L) { - iopath *r = (iopath *)lua_getextraspace(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); @@ -406,7 +437,7 @@ static int l_tty_write(lua_State *L) return 0; } static int l_print(lua_State *L) { - iopath *r = (iopath *)lua_getextraspace(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); @@ -414,9 +445,18 @@ static int l_print(lua_State *L) { int n = lua_gettop(L); for (int i = 1; i <= n; ++i) { if (i > 1) fputc('\t', fp); +#if LUA_VERSION_NUM >= 502 const char *str = luaL_tolstring(L, i, NULL); +#else + /* Lua 5.1 无 luaL_tolstring:lua_tostring 对非字符串做 tostring 元方法转换, + 转换失败(如 table/function)时返回 NULL,退化为类型名 */ + const char *str = lua_tostring(L, i); + if (!str) str = lua_typename(L, lua_type(L, i)); +#endif fputs(str, fp); - lua_pop(L, 1); +#if LUA_VERSION_NUM >= 502 + lua_pop(L, 1); /* luaL_tolstring 压入的结果需弹出;lua_tostring 不压栈 */ +#endif } fputc('\n', fp); fclose(fp); @@ -451,7 +491,15 @@ 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"); +#if LUA_VERSION_NUM >= 502 luaL_setfuncs(L, fake_tty_meta, 0); +#else + /* Lua 5.1 无 luaL_setfuncs:手动注册函数表 */ + for (const luaL_Reg *l = fake_tty_meta; l->name; l++) { + lua_pushcfunction(L, l->func); + lua_setfield(L, -2, l->name); + } +#endif lua_pushvalue(L, -1); lua_setfield(L, -2, "__index"); @@ -475,7 +523,7 @@ int redirecct_path(lua_State *L) errno = LUAERR_LUA_STATE; return -1; } - iopath *p = (iopath*)lua_getextraspace(L); + iopath *p = get_iopath(L); static const luaL_Reg fake_methods[] = { {"read", l_tty_read}, {"write", l_tty_write}, @@ -547,15 +595,16 @@ void *init_lua_runner(const char *pathio,const char *pkgpath,int(*input)(),int(* errno = LUAERR_LUA_STATE; return NULL; } - iopath *io_path = (iopath*)lua_getextraspace(L); - //申请额外空间 + // 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_CALLBACK; + errno = LUAERR_CLASS_LOST; return NULL; } @@ -564,6 +613,9 @@ void *init_lua_runner(const char *pathio,const char *pkgpath,int(*input)(),int(* 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; diff --git a/lib/lua_runner.cpp b/lib/lua_runner.cpp index 39218a9..3a502b4 100755 --- a/lib/lua_runner.cpp +++ b/lib/lua_runner.cpp @@ -2,12 +2,34 @@ #include #include +/* Lua 5.1 兼容:无 LUA_OK 宏,成功返回值为 0 */ +#ifndef LUA_OK +#define LUA_OK 0 +#endif + extern "C" { #include #include "errors.h" } +/* 打开标准库: 5.1+ 用 luaL_openlibs, 5.0 无此函数需手动逐库 open */ +static void open_std_libs(lua_State *L) +{ +#if LUA_VERSION_NUM >= 501 + luaL_openlibs(L); +#else + /* 顺序参照 5.0 手册: base 先行, 其后任意 */ + luaopen_base(L); + luaopen_table(L); + luaopen_io(L); + luaopen_string(L); + luaopen_math(L); + luaopen_debug(L); + luaopen_loadlib(L); +#endif +} + Lua_runner::Lua_runner(const char *path) { this->L =NULL; @@ -17,7 +39,7 @@ Lua_runner::Lua_runner(const char *path) errno = LUAERR_LUA_STATE; return ; } - luaL_openlibs(this->L);//创建lua状态机,打开标准库 + open_std_libs(this->L);//创建lua状态机,打开标准库 const char* save_stdlib_code = "local std = {} " "for k, v in pairs(_G) do std[k] = true end " @@ -29,12 +51,17 @@ Lua_runner::Lua_runner(const char *path) errno = LUAERR_INIT_FAIL;//加载默认路径*/ if(path !=NULL) { +#if LUA_VERSION_NUM >= 501 char buf[1024]; snprintf(buf, sizeof(buf), "package.path = package.path .. \";%s\"", path); if(luaL_dostring(this->L,buf) != LUA_OK)//加载用户路径 errno = LUAERR_INIT_FAIL; +#else + /* Lua 5.0 无 package 系统: 忽略 pkgpath(仅记录, 不报错) */ + (void)path; +#endif } this->pkg_cont = 0; this->func_cont = 0; @@ -136,7 +163,7 @@ int Lua_runner::unload_lib(const char *name) { return -1; } - lua_remove(this->L,this->pkgs[sig].ref); + lua_remove(this->L,this->pkgs[sig].ref - 1); // ref = gettop+1, 故用 ref-1 定位实际栈位置 for(int j = sig+1;jpkg_cont;j++) { this->pkgs[j-1] = this->pkgs[j];//保持数据结构 @@ -161,11 +188,11 @@ int Lua_runner::clean()//进行新一轮调用前一定要先clean清除上个 "end"; luaL_dostring(this->L, clean_globals_code);//清空全局变量 - luaL_dostring(this->L, "package.loaded = {}");//清空当前引用的包 - for(int i = 0 ;ipkg_cont;i++) - { - lua_remove(this->L,this->pkgs[i].ref); - } +#if LUA_VERSION_NUM >= 501 + luaL_dostring(this->L, "package.loaded = {}");//清空当前引用的包(5.0 无 package 系统) +#endif + // 注: 原先此处有逐个 lua_remove(pkgs[i].ref) 的循环,但 ref=gettop+1 恒越界且多次移除后索引偏移, + // 实为死代码;末尾 lua_settop(L,0) 已完整清栈(LuaJIT 下越界 remove 会损坏内存导致崩溃,故删除) this->pkg_cont = 0; // 清理预加载函数 for(int i = 0; i < this->func_cont; i++) @@ -329,7 +356,8 @@ void Lua_runner::capture_result() break; case LUA_TNUMBER: { - // lua_isinteger 区分整型和浮点型 +#if LUA_VERSION_NUM >= 503 + // lua_isinteger 区分整型和浮点型(5.3+ 才有) if (lua_isinteger(this->L, -1)) { this->last_result_type = CJT_INT; @@ -338,7 +366,9 @@ void Lua_runner::capture_result() this->last_result_bool = this->last_result_int != 0; } else +#endif { + // 5.2 及以下无 integer 子类型,所有数字按 number 处理 this->last_result_type = CJT_NUM; this->last_result_num = lua_tonumber(this->L, -1); this->last_result_int = (long long)this->last_result_num; diff --git a/lib/lua_runner.hpp b/lib/lua_runner.hpp index 6336454..85fe9e1 100644 --- a/lib/lua_runner.hpp +++ b/lib/lua_runner.hpp @@ -1,6 +1,7 @@ #ifndef LUA_RUNNER #define LUA_RUNNER #include "lua/lua.hpp" +#include "compat_50.h" /* Lua 5.0/5.1 API 兼容层 */ #ifdef __cplusplus #include #endif diff --git a/src/lua_runner_test.cj b/src/lua_runner_test.cj index 08a8ffa..3065eed 100644 --- a/src/lua_runner_test.cj +++ b/src/lua_runner_test.cj @@ -207,7 +207,11 @@ func testLoadLibOverflow(): Unit { func testPackagePathConfig(): Unit { let runner = LuaRunner(pkgpath: SCRIPTS_DIR + "/pkgmods/?.lua") let res = runner.runScript(scriptPath("pkgpath_require_mylib.lua"), "") - @Expect(res, SCRIPTS_DIR + "/pkgmods/mylib.lua") + // 跨版本语义:Lua 5.4+ 的 require 返回 2 值,run() 读栈顶得 loader data(文件路径); + // Lua ≤5.3 返回 1 值,得模块本身("pkgmod-mylib")。两者都表明 pkgpath 生效。 + let isPath = res == SCRIPTS_DIR + "/pkgmods/mylib.lua" + let isModule = res == "LoadedViaPkgPath" + @Expect(isPath || isModule, true) } @Test diff --git a/test/scripts50/args_test.lua b/test/scripts50/args_test.lua new file mode 100644 index 0000000..7f8cc1b --- /dev/null +++ b/test/scripts50/args_test.lua @@ -0,0 +1,4 @@ +-- Lua 5.0 版: 变参仅限 vararg 函数参数列表 +return function(...) + return arg[1] +end diff --git a/test/scripts50/pipeline_add_prefix.lua b/test/scripts50/pipeline_add_prefix.lua new file mode 100644 index 0000000..457a3f3 --- /dev/null +++ b/test/scripts50/pipeline_add_prefix.lua @@ -0,0 +1,4 @@ +-- 5.0 版 +return function(input) + return "[PREFIX] " .. input +end diff --git a/test/scripts50/pipeline_add_suffix.lua b/test/scripts50/pipeline_add_suffix.lua new file mode 100644 index 0000000..768bb27 --- /dev/null +++ b/test/scripts50/pipeline_add_suffix.lua @@ -0,0 +1,4 @@ +-- 5.0 版 +return function(input) + return input .. " [SUFFIX]" +end diff --git a/test/scripts50/pipeline_generate_data.lua b/test/scripts50/pipeline_generate_data.lua new file mode 100644 index 0000000..6603839 --- /dev/null +++ b/test/scripts50/pipeline_generate_data.lua @@ -0,0 +1,4 @@ +-- 5.0 版 +return function(arg) + return arg +end diff --git a/test/scripts50/pipeline_to_upper.lua b/test/scripts50/pipeline_to_upper.lua new file mode 100644 index 0000000..69dceaa --- /dev/null +++ b/test/scripts50/pipeline_to_upper.lua @@ -0,0 +1,6 @@ +-- 5.0 版 +return function(input) + -- 5.0 无 string.upper 全局? string 库在 string 表里 + local s = string + return s.upper(input) +end diff --git a/test/test_lua_cj_api.cpp b/test/test_lua_cj_api.cpp index 5741593..2c14344 100644 --- a/test/test_lua_cj_api.cpp +++ b/test/test_lua_cj_api.cpp @@ -282,7 +282,12 @@ TEST_F(LuaCjApiTest, PackagePathConfig) { EXPECT_EQ(ret, 0) << "Require failed, maybe pkgpath not set correctly. Errno: " << get_errno(); char* res = getresult(runner); - EXPECT_STREQ(res, lib_path.c_str()); + // 跨版本语义适配: + // - Lua 5.3 的 require 返回 1 个值(模块本身),run() 读栈顶得模块返回值 "LoadedViaPkgPath" + // - Lua 5.4+ 的 require 返回 2 个值(模块 + loader data),run() 读栈顶得 loader data(文件路径) + // 两者都表明 require 经 pkgpath 成功定位并加载了模块 + EXPECT_TRUE(strcmp(res, lib_path.c_str()) == 0 || strcmp(res, "LoadedViaPkgPath") == 0) + << "unexpected require result: " << (res ? res : "(null)"); } // ==================== 新增测试:doString 功能 ==================== @@ -487,13 +492,21 @@ TEST_F(LuaCjApiTest, CallFunctionAfterCleanup) { } // ==================== typed interop 测试(v0.2.2)==================== +// 版本自适应:Lua 5.3+ 有 integer 子类型(CJT_INT),5.2 及以下所有数字均为 +// number(CJT_NUM)。数值断言用 INT_OR_NUM 宏兼容两种情况。 +#if LUA_VERSION_NUM >= 503 +#define EXPECT_INT_OR_NUM(type) EXPECT_EQ(type, CJT_INT) +#else +// 5.2 及以下:整型结果也报为 CJT_NUM,且 lua_tostring(10.0) 输出 "10" +#define EXPECT_INT_OR_NUM(type) EXPECT_EQ(type, CJT_NUM) +#endif // 整型参数直通:Lua 收到 integer,返回 integer+1,仓颉侧读回 Int64 TEST_F(LuaCjApiTest, TypedCallInt) { ASSERT_EQ(loadfunction(runner, get_script_path("func_typed_add.lua").c_str(), "inc"), 0); EXPECT_EQ(callfunction_int(runner, "inc", 41), 0); - EXPECT_EQ(result_type(runner), CJT_INT); + EXPECT_INT_OR_NUM(result_type(runner)); EXPECT_EQ(result_int(runner), 42); // 字符串形式同步可用(向后兼容) EXPECT_STREQ(getresult(runner), "42"); @@ -506,7 +519,12 @@ TEST_F(LuaCjApiTest, TypedCallNum) { EXPECT_EQ(callfunction_num(runner, "mul", 4.0), 0); EXPECT_EQ(result_type(runner), CJT_NUM); EXPECT_DOUBLE_EQ(result_num(runner), 10.0); +#if LUA_VERSION_NUM >= 503 EXPECT_STREQ(getresult(runner), "10.0"); +#else + // 5.2 的 %.14g 格式化把 10.0 输出为 "10" + EXPECT_STREQ(getresult(runner), "10"); +#endif } // 布尔参数直通:返回逻辑非,读回 Bool @@ -529,7 +547,7 @@ TEST_F(LuaCjApiTest, TypedCallVoid) { ASSERT_EQ(loadfunction(runner, get_script_path("func_typed_void.lua").c_str(), "forty_two"), 0); EXPECT_EQ(callfunction_void(runner, "forty_two"), 0); - EXPECT_EQ(result_type(runner), CJT_INT); + EXPECT_INT_OR_NUM(result_type(runner)); EXPECT_EQ(result_int(runner), 42); } @@ -539,13 +557,21 @@ TEST_F(LuaCjApiTest, TypedEchoRoundTrip) { // int 往返 EXPECT_EQ(callfunction_int(runner, "echo", -123456789LL), 0); - EXPECT_EQ(result_type(runner), CJT_INT); + EXPECT_INT_OR_NUM(result_type(runner)); EXPECT_EQ(result_int(runner), -123456789LL); - // 大整数(超过 double 精确表示范围)往返 + // 大整数(超过 double 精确表示范围)往返: + // 仅 Lua 5.3+(integer 类型)可保真;5.2 及以下经 double 必然丢精度 +#if LUA_VERSION_NUM >= 503 EXPECT_EQ(callfunction_int(runner, "echo", 9007199254740993LL), 0); - EXPECT_EQ(result_type(runner), CJT_INT); + EXPECT_INT_OR_NUM(result_type(runner)); EXPECT_EQ(result_int(runner), 9007199254740993LL); +#else + EXPECT_EQ(callfunction_int(runner, "echo", 9007199254740993LL), 0); + EXPECT_EQ(result_type(runner), CJT_NUM); + // 经 double 往返,精度丢失为可预期值 + EXPECT_EQ(result_int(runner), (long long)(double)9007199254740993LL); +#endif // num 往返 EXPECT_EQ(callfunction_num(runner, "echo", 3.14159), 0); @@ -592,7 +618,7 @@ TEST_F(LuaCjApiTest, TypedRunVariants) { // int EXPECT_EQ(run_int(runner, path.c_str(), 777), 0); - EXPECT_EQ(result_type(runner), CJT_INT); + EXPECT_INT_OR_NUM(result_type(runner)); EXPECT_EQ(result_int(runner), 777); // num @@ -638,7 +664,7 @@ TEST_F(LuaCjApiTest, TypedAndStringCoexist) { TEST_F(LuaCjApiTest, TypedStateAfterCleanup) { ASSERT_EQ(loadfunction(runner, get_script_path("func_typed_void.lua").c_str(), "v"), 0); EXPECT_EQ(callfunction_void(runner, "v"), 0); - EXPECT_EQ(result_type(runner), CJT_INT); + EXPECT_INT_OR_NUM(result_type(runner)); EXPECT_EQ(cleanup(runner), 0);