V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
推荐学习书目
Learn Python the Hard Way
Python Sites
PyPI - Python Package Index
http://diveintopython.org/toc/index.html
Pocoo
值得关注的项目
PyPy
Celery
Jinja2
Read the Docs
gevent
pyenv
virtualenv
Stackless Python
Beautiful Soup
结巴中文分词
Green Unicorn
Sentry
Shovel
Pyflakes
pytest
Python 编程
pep8 Checker
Styles
PEP 8
Google Python Style Guide
Code Style from The Hitchhiker's Guide
3t
V2EX  ›  Python

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

  •  
  •   3t · 2018-02-27 10:56:31 +08:00 · 2530 次点击
    这是一个创建于 2221 天前的主题,其中的信息可能已经有所发展或是发生改变。

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

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

    想到一个方法,python 通过 rpc 共享 json,lue 调用 rpc 拿 json 数据。。。
    感觉还不如 redis。。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   3383 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 26ms · UTC 13:16 · PVG 21:16 · LAX 06:16 · JFK 09:16
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.