Python 通过 lupa 调用 lua,传入 table 类型,报错 cannot mix objects

2018-02-27 10:56:31 +08:00
 3t

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 = _G[func_name](params)
        return result
    end
    is_true,result= pcall(sandBox,func_name,params)
    return result
end


test.py

# -*-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 的版本都试过了,都报同一个错。。。
第一次发帖就提问。。不知道也可以留个言。。
2557 次点击
所在节点    Python
5 条回复
shuax
2018-02-27 11:08:14 +08:00
如果是我就用 json 传参数,管你两边是什么数据类型。
enenaaa
2018-02-27 12:08:17 +08:00
不懂 lupa。 但是两个 lua 环境肯定不能直接传递表对象的吧, 就好像两个进程不能相互传递指针一样。 传递数据需要先序列化。

userdata 是进程内的一块连续内存,table 是 lua 环境下的表结构,两个不同的数据类型, 不能直接转换。想把 userdata 里的数据读出来的话, 需要自定义元表方法。
3t
2018-02-27 15:09:16 +08:00
@enenaaa 今天了解到,两个 python 进程间共享内存的还是 RPC。。。。想确认一件事,“自定义元表方法"可以用纯 lua 实现吗?还是中间还需要 C 语言??
enenaaa
2018-02-27 15:46:33 +08:00
@3t 操作 userdata 用 C
3t
2018-02-27 16:17:54 +08:00
@shuax
@enenaaa

想到一个方法,python 通过 rpc 共享 json,lue 调用 rpc 拿 json 数据。。。
感觉还不如 redis。。

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/433026

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX