Python通过lupa调用Lua时传入table类型报错cannot mix objects如何解决
test.lua
function test1(params)
print(type(params),params)
return 'test1:'..params
end
– 入口函数,实现反射函数调用
function functionCall(func_name,params)
local is_true,result
local sandBox = function(func_name,params)
local result
result = _Gfunc_name
return result
end
is_true,result= pcall(sandBox,func_name,params)
return result
end
# -*-coding:utf-8-*-
import traceback
from lupa import LuaRuntime
import threading
class Executor(threading.Thread):
“”"
执行 lua 的线程类
“”"
lock = threading.RLock()
luaScriptContent = None
luaRuntime = None
def __init__(self,api,params):
threading.Thread.__init__(self)
self.params = params
self.api = api
def run(self):
try:
# 执行具体的函数,返回结果打印在屏幕上
luaRuntime = self.getLuaRuntime()
rel = luaRuntime(self.api, self.params)
print rel
except Exception,e:
print e.message
traceback.extract_stack()
def getLuaRuntime(self):
"""
从文件中加载要执行的 lua 脚本,初始化 lua 执行环境
"""
# 上锁,保证多个线程加载不会冲突
if Executor.lock.acquire():
if Executor.luaRuntime is None:
fileHandler = open('./test.lua')
content = ''
try:
content = fileHandler.read()
except Exception, e:
print e.message
traceback.extract_stack()
# 创建 lua 执行环境
Executor.luaScriptContent = content
luaRuntime = LuaRuntime()
luaRuntime.execute(content)
# 从 lua 执行环境中取出全局函数 functionCall 作为入口函数调用,实现 lua 的反射调用
g = luaRuntime.globals()
function_call = g.functionCall
Executor.luaRuntime = function_call
Executor.lock.release()
return Executor.luaRuntime
if name == “main”:
lua=LuaRuntime()
table_data=lua.eval(’{ a=1, b=2 }’)
print(type(table_data),table_data) #(<type ‘lupa._lupa._LuaTable’>, <Lua table at 0x2243be0>)
executor1 = Executor('test1',"hello world") #正常,python 的字符串格式,在 lua 中也是字符串,输出:string hello world
executor2 = Executor('test1',{"a":1,"b":2}) #正常,python 的字典格式转化成 lua 的 userdata 类型,输出:userdata {'a': 1, 'b': 2}
executor3 = Executor('test1',table_data) #报错,将 lua 的 table 的地址传入,输出:cannot mix objects from different Lua runtimes
executor1.start()
executor2.start()
executor3.start()
executor1.join()
executor2.join()
executor3.join()
现在是有两个问题,解决任意一个都可以。。
一个是,lua 怎么可以把,userdata 类型转化成 table 类型
另一个是,传入 table 类型的变量,为什么会报错。。
我已经把 5.1 和 5.3 的版本都试过了,都报同一个错。。。
第一次发帖就提问。。不知道也可以留个言。。
Python通过lupa调用Lua时传入table类型报错cannot mix objects如何解决
如果是我就用 json 传参数,管你两边是什么数据类型。
这个问题我遇到过。当你在Python里用lupa往Lua函数传Python字典(或者Lua那边期待table)时,如果字典里同时有字符串键和整数键,LuaJIT(lupa的后端)就会报“cannot mix objects”这个错。这是因为Lua的table实现里,数组部分(整数键)和哈希部分(其他类型键)是分开的,而lupa在转换时处理不了这种混合类型。
核心原因:Lua的table在内部对连续整数键(如1,2,3)和字符串/非连续键的处理方式不同。lupa在将Python字典转换为Lua table时,如果遇到混合键类型,内部转换逻辑会冲突。
解决方案:在传入前,把Python字典里所有的键都转成字符串(或都转成整数,但通常转字符串更安全)。下面是个例子:
import lupa
from lupa import LuaRuntime
lua = LuaRuntime(unpack_returned_tuples=True)
# 会报错的字典:混合了字符串键和整数键
problem_dict = {
"name": "test",
1: "value1", # 整数键
"key2": "value2"
}
# 解决方案:将所有键转换为字符串
safe_dict = {str(key): value for key, value in problem_dict.items()}
# 现在可以安全传递了
lua_code = """
function process_table(tbl)
print(tbl["name"])
print(tbl["1"]) -- 注意:原来的整数键1现在要用字符串"1"访问
print(tbl["key2"])
end
"""
lua.execute(lua_code)
lua_func = lua.globals().process_table
lua_func(safe_dict) # 正常执行
如果你需要保持Lua那边能用整数索引访问,那就得在构造字典时避免混合类型,或者分两个table传。
简单说:传之前把字典键全转成字符串就完事了。
不懂 lupa。 但是两个 lua 环境肯定不能直接传递表对象的吧, 就好像两个进程不能相互传递指针一样。 传递数据需要先序列化。
userdata 是进程内的一块连续内存,table 是 lua 环境下的表结构,两个不同的数据类型, 不能直接转换。想把 userdata 里的数据读出来的话, 需要自定义元表方法。
今天了解到,两个 python 进程间共享内存的还是 RPC。。。。想确认一件事,“自定义元表方法"可以用纯 lua 实现吗?还是中间还需要 C 语言??
操作 userdata 用 C
想到一个方法,python 通过 rpc 共享 json,lue 调用 rpc 拿 json 数据。。。
感觉还不如 redis。。

