代码之家  ›  专栏  ›  技术社区  ›  dbr

使用jruby/jython实现ruby/python互操作性?

  •  11
  • dbr  · 技术社区  · 14 年前

    很可能是个愚蠢的问题,因为我对Java/Jython/JuRube/字节码了解不多,但是…

    我偶然发现 _why's unholy 今天又来了..它允许您从ruby代码输出python字节码。基本上允许它们产生相同的字节码。

    Jython输出Java字节码,JRube也一样。因为它们都编译成相同的字节码,这是否意味着您可以使用来自ruby的任何python库,以及来自python的ruby库?

    2 回复  |  直到 14 年前
        1
  •  7
  •   Jörg W Mittag    14 年前

    不,那不行。至少不是你想的那样。

    jython和jruby之间的互操作性与cpython和yarv之间的工作方式相同:它们都运行在同一个平台上,因此它们可以使用该平台相互通信。

    在cpython和yarv的情况下,该平台是c/posix,因此它们可以使用c结构相互通信, int S char* s和c函数调用。在jython和jruby的例子中,这个平台是jvm,因此它们可以使用jvm对象、jvm类、jvm接口、jvm类型和jvm方法相互通信。

    在这两种情况下,这些平台原语看起来 没有什么 比如python或ruby对象。

    对于JRuBy,Jython只是另一个Java程序。对于Jython,JRube只是另一个Java程序。

    例如:在ruby中,可以随时动态地添加、删除和重新定义方法。在jvm上,可以动态添加和删除的最小代码单元是一个类。因此,Ruby方法实际上并没有被表示为Java方法。它被表示为Java。 . 逻辑上,一个具有两种方法的Ruby对象被表示为没有任何方法的Java对象,只是一个 Dictionary<String, RubyMethod> 字段。IOW:Java是完全不可用的,因为从JRuBy的观点来看,Jython只是Java,它也不能从Jython中使用。

    现在,那里 让事情变得更好的方法。可以使用实际的Java类型在两者之间进行通信——这两种实现都与Java具有很强的互操作性。因此,不要将一个Ruby散列传递给Python或Python字典到露比,而使用Java Map 来自ruby和python。但请注意这需要 二者都 您的ruby和python代码是专门为在jvm上工作而编写的。注意:你不能仅仅使用你在网上找到的任何python或ruby库,这正是你想要的。

    另一种可能性是@duncan在他的回答中提到的:将jython或jruby作为脚本引擎嵌入到ruby或python应用程序中。但是,这并不能真正回答您使用ruby中任意python库的问题,反之亦然。

    那么,这里有什么问题?

    问题是,为了让这两个运行时进行通信,它们需要说相同的“语言”。在这种特殊情况下,两个运行时唯一的共同语言是Java,或者说是一个严重受损的Java子集。

    所以,我们需要找到一种共同的语言。定义这种语言的一种方法是让两个运行时理解彼此的元对象协议(MOP)。

    mop基本上是语言对象模型的对象模型。嗯,这很让人困惑,因为我们用“对象模型”这个词来表示两种不同的东西。让我重新表述一下:

    mop基本上是语言对象系统的域模型。正如银行系统的域模型包含表示真实世界的客户、帐户、余额、分类账等的对象,以及表示真实世界的操作(如转账、取款等)的方法一样,MOP包含表示语言类、方法、变量的对象。表示语言操作的表、对象和方法,如查找变量、调用方法、从类继承、构造类的实例。

    通常,每个运行时都保持其mop私有,并且每个运行时都有自己的mop。

    如果jruby和jython将它们的mop公开给对方,并理解对方的mop(或者,更好的是:它们将mop公开给jvm,并且两者都使用 相同的 mop),然后您可以将其中一个疯狂的jruby方法包传递给jython,它将知道如何找到属于该对象的方法以及如何调用这些方法,因为它可以直接询问jruby的mop如何执行。

    实际上有一个项目可以为jvm创建这样一个mop: dynalang MOP 是一个项目,用于在jvm上运行的动态语言的共享、标准化mop。它是由mozilla rhino ecmascript引擎的维护者attila szegedi创建的。目前,没有一个大型语言实现使用它,但至少rhino、jruby、jython和groovy之间正在进行协作,以确保dynalang足够通用,能够支持所有不同语言的对象模型。

    如果你想偷看一下这样一个共享mop的世界会是什么样子,你可以看看微软的动态语言运行库(dynamic language runtime,dlr)。dlr只包含这样一个mop和所有支持dlr的运行时(除了通常的怀疑,例如 IronRuby , IronPython , IronJS IronScheme 现在还包括c 4和visual basic.net 10)几乎可以无缝地互操作。

    另一个类似的平台是 Parrot Virtual Machine ,它是专门为允许多个动态语言在同一运行时平台上进行互操作而设计的。有python的实现( Pynie )还有鲁比( Cardinal )可用,但特别是cardinal还远远不是一个远程完整的ruby实现。

        2
  •  5
  •   duncan    14 年前

    有两种方法。它们都提供静态编译代码并从脚本生成真正的Java类的能力。Jython AFAIK在这种情况下生成Java源代码,然后通过JythOC脚本调用JavaC。但这需要编译。

    对于两个解释器,可以从脚本调用Java代码,并且可以将解释器嵌入到Java应用程序中。

    例如,从Python调用Java:

    >>> from java.util import Random
    >>> r = Random()
    >>> r.nextInt()
    501203849
    

    在爪哇中嵌入JRube解释器,可以(注意,基于JSR223的方式也是这样,这是核心之一):

    package vanilla;
    
    import org.jruby.embed.ScriptingContainer;
    
    public class HelloWorld {
    
        private HelloWorld() {
            ScriptingContainer container = new ScriptingContainer();
            container.runScriptlet("puts Hello world");
        }
    
        public static void main(String[] args) {
            new HelloWorld();
        }
    

    您可以从jyton执行同样的操作(我想您需要正确地给出jruby路径):

    import org.jruby.embed.ScriptingContainer
    container = ScriptingContainer()
    container.runScriptlet("puts Hello world")
    

    同样的事情也可以反过来做。

    通过导入,您将无法将整个ruby stdlib导出到python解释器。您需要提前将ruby的stdlib预编译为字节码。

    但是,使用上面描述的技术,并添加两个助手脚本和定义的接口,您可以将特定功能从一种语言连接到另一种语言。