2010-05-02 11 views
11

Ganz-wahrscheinlich eine dumme Frage, wie ich über Java/Jython/JRuby/Bytecode viel weiß es nicht, aber ..Verwenden von JRuby/Jython für die Ruby/Python-Interoperabilität?

ich auf _why's unholy heute wieder gestolpert .. Es ermöglicht Ihnen, Ausgabe Python-Bytecode von Ruby-Code ..

Jython gibt Java Bytecode aus, genau wie JRuby. Da diese beiden auf denselben Bytecode kompilieren, bedeutet das, dass Sie möglicherweise jede Python-Bibliothek von Ruby und Ruby verwenden können Bibliotheken von Python?

+0

+1 für eine interessante Frage ... – ChristopheD

+1

BTW: dass "mythische VM, die alle Sprachen läuft", die am Ende der unheiligen README erwähnt wird, * ist * die Parrot VM, die ich in meiner Antwort erwähnte. Und glücklicherweise ist es jetzt nicht mehr mythisch: Die große 1.0.0-Veröffentlichung war vor über einem Jahr, und seitdem hat das Parrot-Team eine stabile Veröffentlichung pro Monat wie ein Uhrwerk produziert und kam vor zwei Wochen auf (aktuell) 2.3.0 . Natürlich bedeutet das nicht, dass es tatsächlich einen * Compiler * für jede Sprache gibt (insbesondere ist der Cardinal Ruby Compiler bei weitem nicht produktionsbereit), nur dass die VM existiert und stabil ist. –

Antwort

7

Nein, das wird nicht funktionieren. Jedenfalls nicht so wie du denkst.

Die Interoperabilität zwischen Jython und JRuby funktioniert genauso wie zwischen CPython und YARV: Sie laufen beide auf derselben Plattform, sodass sie über diese Plattform miteinander kommunizieren können. Im Falle von CPython und YARV ist diese Plattform C/POSIX, so dass sie über C-Structs, int s, char* s und C-Funktionsaufrufe miteinander kommunizieren können. Im Fall von Jython und JRuby ist diese Plattform die JVM, sodass sie über JVM-Objekte, JVM-Klassen, JVM-Schnittstellen, JVM-Typen und JVM-Methoden miteinander kommunizieren können.

In beiden Fällen sehen diese Plattform-Primitive nichts wie Python oder Ruby-Objekte.

Für JRuby ist Jython nur ein weiteres Java-Programm. Für Jython ist JRuby nur ein weiteres Java-Programm.

Zum Beispiel: In Ruby können Sie Methoden jederzeit dynamisch hinzufügen, entfernen und neu definieren. Auf der JVM ist die kleinste Code-Einheit, die dynamisch hinzugefügt und entfernt werden kann, eine Klasse. Eine Ruby-Methode wird also nicht als Java-Methode dargestellt.Es wird als Java Klasse dargestellt. Und logisch wird ein Ruby-Objekt mit ein paar Methoden als ein Java-Objekt ohne Methoden dargestellt, nur ein Dictionary<String, RubyMethod> Feld. IOW: es ist von Java völlig unbrauchbar, und da Jython aus JRubys Sicht nur Java ist, ist es auch von Jython unbrauchbar.

Jetzt, dort sind Möglichkeiten, dies ein wenig besser zu machen. Sie könnten tatsächliche Java-Typen verwenden, um zwischen den beiden Implementierungen zu kommunizieren. Beide Implementierungen haben eine große Interoperabilität mit Java. Statt einen Ruby-Hash an Python oder ein Python-Wörterbuch an Ruby zu übergeben, würden Sie also ein Java Map aus Ruby und Python verwenden. Beachten Sie jedoch, dass dazu Ihr Ruby- und Python-Code speziell für die Arbeit auf der JVM geschrieben werden muss. IOW: Sie können nicht einfach irgendeine Python- oder Ruby-Bibliothek benutzen, die Sie im Internet finden, und darum bitten Sie.

Eine weitere Möglichkeit ist diejenige, die @duncan in seiner Antwort erwähnt: Binden Sie Jython oder JRuby als Skript-Engine in Ihre Ruby- oder Python-Anwendung ein. Aber auch das beantwortet nicht wirklich Ihre Frage nach der Verwendung beliebiger Python-Bibliotheken aus Ruby oder umgekehrt.

Also, was ist das Problem hier?

Das Problem ist, dass, um die zwei Laufzeiten zu kommunizieren, sie die gleiche "Sprache" sprechen müssen. Und in diesem speziellen Fall ist die einzige Sprache, die die beiden Laufzeiten gemeinsam haben, Java oder eine stark verkrüppelte Java-Untergruppe.

Also müssen wir eine gemeinsame Sprache finden. Eine Möglichkeit, eine solche Sprache zu definieren, wäre, dass beide Laufzeiten das Meta-Object-Protocol (MOP) des jeweils anderen verstehen.

Ein MOP ist im Grunde ein Objektmodell für das Objektmodell der Sprache. Ähm, das ist verwirrend, weil wir das Wort "Objektmodell" für zwei verschiedene Dinge verwenden. Lassen Sie mich das umformulieren:

Ein MOP ist im Grunde ein Domänenmodell für das Objektsystem der Sprache. Genau wie ein Domänenmodell für ein Bankensystem Objekte enthält, die reale Kunden, Konten, Bilanzen, Hauptbücher usw. darstellen, und Methoden, die reale Aktionen wie Geldüberweisungen, Abhebungen usw. darstellen, enthält ein MOP Objekte, die repräsentieren Sprachklassen, Methoden, Variablen, Objekte und Methoden, die Sprachaktionen darstellen, wie das Nachschlagen einer Variablen, das Aufrufen einer Methode, das Erben von einer Klasse, das Konstruieren einer Instanz einer Klasse.

Normalerweise behält jede Runtime ihr MOP privat und jede Runtime hat ihr eigenes MOP.

Wenn JRuby und Jython ausgesetzt ihre MOPs miteinander und verstanden sich MOPs des anderen (oder besser sogar noch: sie ihre MOPs der JVM ausgesetzt und beide verwendet die gleiche MOP), dann könnten Sie einer von denen, passieren verrückte JRuby Methode Taschen zu Jython, und es würde wissen, wie man die Methoden, die zu diesem Objekt gehören, und wie man sie nennt, weil es JRuby's MOP einfach fragen kann, wie man es macht.

Es gibt tatsächlich ein Projekt, um ein solches MOP für die JVM zu erstellen: Das dynalang MOP ist ein Projekt für ein gemeinsames, standardisiertes MOP für dynamische Sprachen, die auf der JVM laufen. Es wurde von Attila Szegedi, dem Betreuer der Mozilla Rhino ECMAScript-Engine, erstellt. Im Moment verwendet keine der großen Sprachimplementierungen es, aber mindestens Rhino, JRuby, Jython und Groovy arbeiten zusammen, um sicherzustellen, dass dynalang generisch genug ist, um alle Objektmodelle der verschiedenen Sprachen zu unterstützen.

Wenn Sie einen Blick darauf werfen möchten, wie eine Welt mit einem solchen geteilten MOP aussehen würde, können Sie sich die Dynamic Language Runtime (DLR) von Microsoft ansehen. Der DLR enthält genau ein solches MOP und alle Laufzeiten, die das DLR unterstützen (welches neben den üblichen Verdächtigen wie IronRuby, IronPython, IronJS und IronScheme jetzt auch C# 4 und Visual Basic.NET 10 beinhaltet) können nahezu nahtlos mit jedem zusammenarbeiten andere.

Eine weitere ähnliche Plattform ist die Parrot Virtual Machine, die speziell entwickelt wurde, damit mehrere dynamische Sprachen auf der gleichen Laufzeitplattform zusammenarbeiten können. Es gibt Implementierungen von Python (Pynie) und Ruby(), aber vor allem ist Cardinal noch weit davon entfernt, eine remote abgeschlossene Ruby-Implementierung zu sein.

5

Es gibt zwei Möglichkeiten, dies zu tun. Beide bieten die Möglichkeit, Code statisch zu kompilieren und aus dem Skript eine echte Java-Klasse zu erzeugen. Jython AFAIK erzeugt in diesem Fall Java-Quellcode und ruft dann javac über ein jythonc-Skript auf. Aber das erfordert Kompilierung.

Für beide Interpreter können Sie Java-Code von Skripten aufrufen, und Sie können den Interpreter in eine Java-Anwendung einbetten.

Zum Beispiel Java von Python zu nennen:

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

JRuby-Interpreter in Java einzubetten, die Sie tun können (beachten Sie, gibt es eine JSR223 basiert zu, das ist der Kern ein):

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(); 
    } 

Sie das gleiche von Jyton tun könnte (ich glaube, man würde die jruby Pfade korrekt geben müssen):

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

Das Gleiche kann auch andersherum gemacht werden.

Sie werden nicht die gesamte ruby ​​stdlib in den Python-Interpreter exportieren, indem Sie einen Import durchführen. Sie müssten rubys stdlib vorab mit Bytecode vorkompilieren.

Mit der oben beschriebenen Technik und einigen Hilfsskripten und definierten Schnittstellen können Sie jedoch bestimmte Funktionen von einer Sprache zur anderen überbrücken.

Verwandte Themen