2010-05-02 7 views
11

Tout-probablement une question stupide, car je ne sais pas beaucoup sur Java/Jython/JRuby/bytecode, mais ..Utilisation de JRuby/Jython pour l'interopérabilité Ruby/Python?

je suis tombé sur _why's unholy encore aujourd'hui .. Il vous permet de sortie Python bytecode à partir du code Ruby En leur permettant de produire le même bytecode ..

Jython génère le bytecode Java, tout comme JRuby. Puisque ces deux compilent au même bytecode, cela signifie-t-il que vous pourriez potentiellement utiliser n'importe quelle bibliothèque Python de Ruby, et Ruby bibliothèques de Python?

+0

+1 pour une question intéressante ... – ChristopheD

+1

BTW: que "VM mythique qui exécute toutes les langues" qui est mentionné à la toute fin de l'README impie, * est * le VM Parrot que j'ai mentionné dans ma réponse. Et heureusement, ce n'est plus mythique: la grande version 1.0.0 date d'il y a plus d'un an et depuis, l'équipe Parrot a produit une version stable par mois comme sur des roulettes, arrivant à (actuellement) 2.3.0 il y a deux semaines . Bien sûr, cela ne signifie pas qu'il existe un * compilateur * pour chaque langue (en particulier, le compilateur Cardinal Ruby est loin d'être prêt pour la production), seulement que la VM existe et est stable. –

Répondre

7

Non, cela ne fonctionnera pas. Du moins pas comme tu le penses.

L'interopérabilité entre Jython et JRuby fonctionne de la même manière qu'entre CPython et YARV: ils fonctionnent tous les deux sur la même plate-forme, ce qui leur permet de communiquer entre eux à l'aide de cette plate-forme. Dans le cas de CPython et YARV, cette plate-forme est C/POSIX, de sorte qu'ils peuvent communiquer les uns avec les autres en utilisant les structures C, int s, char* s et les appels de fonction C. Dans le cas de Jython et JRuby, cette plate-forme est la JVM, de sorte qu'ils peuvent communiquer les uns avec les autres en utilisant des objets JVM, des classes JVM, des interfaces JVM, des types JVM et des méthodes JVM. Dans les deux cas, les primitives de la plate-forme ne ressemblent pas à comme les objets Python ou Ruby.

Pour JRuby, Jython est juste un autre programme Java. Pour Jython, JRuby est juste un autre programme Java. Par exemple: dans Ruby, vous pouvez ajouter, supprimer et redéfinir dynamiquement des méthodes à tout moment. Sur la JVM, la plus petite unité de code pouvant être dynamiquement ajoutée et supprimée est une classe. Ainsi, une méthode Ruby n'est en réalité pas représentée comme une méthode Java.Il est représenté par une classe Java . Et logiquement, un objet Ruby avec quelques méthodes est représenté comme un objet Java sans méthodes, juste un champ Dictionary<String, RubyMethod>. IOW: il est totalement inutilisable depuis Java, et du point de vue de JRuby, Jython n'est que Java, il est également inutilisable depuis Jython.

Maintenant, il sont façons de faire un peu mieux. Vous pouvez utiliser les types Java réels pour communiquer entre les deux   – les deux implémentations ont une grande interopérabilité avec Java. Ainsi, au lieu de passer un hachage Ruby à Python ou un dictionnaire Python à Ruby, vous utiliseriez Java Map à partir de Ruby et de Python. Mais notez que cela nécessite que les deux votre code Ruby et Python sont spécifiquement écrits pour fonctionner sur la JVM. IOW: vous ne pouvez pas utiliser n'importe quelle bibliothèque Python ou Ruby que vous trouvez sur le web, c'est ce que vous demandez.

Une autre possibilité est celle mentionnée par @duncan dans sa réponse: intégrer Jython ou JRuby en tant que moteur de script dans votre application Ruby ou Python. Mais encore une fois, cela ne répond pas vraiment à votre question sur l'utilisation de bibliothèques Python arbitraires de Ruby ou vice versa.

Alors, quel est le problème ici?

Le problème est que pour que les deux temps de fonctionnement communiquent, ils doivent parler le même "langage". Et dans ce cas particulier, le seul langage commun aux deux runtimes est Java, ou plutôt un sous-ensemble de Java gravement handicapé. Donc, nous devons trouver un langage commun. Une façon de définir un tel langage serait que les deux runtimes comprennent le protocole MOP (Meta-Object Protocol) de l'autre.

Un MOP est fondamentalement un modèle objet pour le modèle objet du langage. Um, c'est déroutant parce que nous utilisons le mot "modèle d'objet" pour signifier deux choses différentes. Permettez-moi de reformuler cela:

Un MOP est fondamentalement un modèle de domaine pour le système objet du langage. Tout comme un modèle de domaine pour un système bancaire contient des objets représentant des clients réels, des comptes, des soldes, des livres, etc., et des méthodes qui représentent des actions réelles comme des transferts d'argent, des retraits, etc. classes de langage, méthodes, variables, objets et méthodes qui représentent des actions de langage telles que rechercher une variable, appeler une méthode, hériter d'une classe, construire une instance d'une classe.

Normalement, chaque exécution garde son MOP privé, et chaque exécution a son propre MOP.

Si JRuby et Jython exposé leurs RdP les uns aux autres et comprenions RdP de (ou, encore mieux encore: ils ont exposé leurs RdP à la machine virtuelle Java et les deux utilisés la même MOP), alors vous pourriez passer un de ces La méthode folle de JRuby porte sur Jython, et il saura comment trouver les méthodes qui appartiennent à cet objet et comment les appeler, parce qu'il peut simplement demander à la MOP de JRuby comment le faire.

Il existe actuellement un projet pour créer une telle MOP pour la JVM: le dynalang MOP est un projet de MOP standardisé et partagé pour les langages dynamiques s'exécutant sur la JVM. Il a été créé par Attila Szegedi, le mainteneur du moteur Mozilla Rhino ECMAScript. Pour le moment, aucune implémentation en langage grand format ne l'utilise, mais il y a une collaboration entre au moins Rhino, JRuby, Jython et Groovy pour s'assurer que dynalang est suffisamment générique pour pouvoir prendre en charge tous les modèles d'objet du langage.

Si vous voulez un aperçu de ce à quoi ressemblerait un monde avec un tel MOP partagé, vous pouvez jeter un oeil à Dynamic Language Runtime (DLR) de Microsoft. Le DLR contient juste un tel MOP et tous les runtimes qui supportent le DLR (qui, en plus des suspects habituels tels que IronRuby, IronPython, IronJS et IronScheme maintenant inclut également C# 4 et Visual Basic.NET 10) peuvent interopérer de manière presque transparente avec chaque autre.

Une autre plate-forme similaire est la Parrot Virtual Machine, qui a été spécialement conçue pour permettre l'interopérabilité de plusieurs langages dynamiques sur la même plate-forme d'exécution. Il existe des implémentations de Python (Pynie) et Ruby (Cardinal) disponibles, mais surtout Cardinal est encore très loin d'être une implémentation Ruby même à distance complète.

5

Il y a deux façons de le faire. Les deux offrent la possibilité de compiler statiquement du code et de produire une véritable classe Java à partir du script. Dans ce cas, Jython AFAIK génère du code source Java puis appelle javac via un script jythonc. Mais cela nécessite une compilation.

Pour les deux interpréteurs, vous pouvez appeler du code Java à partir de scripts et intégrer l'interpréteur dans une application Java.

Par exemple, pour appeler Java à partir de Python:

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

Pour intégrer interpréteur JRuby en Java, vous pouvez le faire (note, il existe un moyen basé JSR223 aussi, c'est le noyau d'un):

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

vous pouvez faire la même chose de Jyton (je suppose que vous devez donner correctement les chemins JRuby):

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

La même chose peut être faite dans l'autre sens.

Vous n'obtiendrez pas l'ensemble de ruby ​​stdlib exporté vers l'interpréteur python en faisant une importation. Vous auriez besoin de précompiler le stdlib de ruby ​​pour le bytecode à l'avance. Toutefois, avec la technique décrite ci-dessus et en ajoutant quelques scripts auxiliaires et des interfaces définies, vous pouvez faire le pont entre des fonctionnalités spécifiques d'une langue à l'autre.

Questions connexes