Construit sur le plugin DLR éprouvé disponible sur la plate-forme Sinapse, JCOBridge garantit les meilleures performances dans l'intégration des mondes JVM et CLR.
- Récupérer le type CLR
- Instancier un objet CLR
- Invoquer des méthodes statiques
- Invoquer des méthodes d'instance
- Obtenir/Définir des propriétés statiques
- Obtenir/Définir les propriétés de l'instance
- Définir les délégués
- Événements d'abonnement/désabonnement
- Intègre les contrôles WPF dans la fenêtre AWT/Swing
- Intégrer les contrôles WinForms dans la fenêtre AWT/Swing
- Intégrer des objets d'interface utilisateur graphique .NET complexes dans la fenêtre AWT/Swing
- Interface utilisateur Gestion des contrôles, des propriétés et des événements
- Récupérer la classe JVM
- Instancier des objets JVM
- Invoquer des méthodes statiques
- Invoquer des méthodes d'instance
- Obtenir/Définir des champs statiques
- Obtenir/Définir les champs d'instance
- Utilisez l'accès dynamique pour écrire du code de manière transparente, comme cela se fait en langage Java.
- Utiliser une interface spécifique pour gérer directement les méthodes et les champs
JCOBridge (JVM-CLR Object Bridge) permet l'exécution de langages natifs JVM, comme Java et Scala, à partir des langages CLR/.NET et vice-versa, il permet d'importer et d'utiliser des bibliothèques, des composants et également de gérer l'interface utilisateur graphique à partir d'un seul monde de la programmation à l’autre. Plus d'informations sur www.jcobridge.com
Pour explorer les exemples, vous devez effectuer les étapes suivantes :
Dans ce référentiel, il est possible de trouver des exemples de code pour les différents langages de programmation supportés par JCObridge. Les exemples sont organisés dans deux dossiers principaux, JVM et CLR qui contiennent les projets relatifs. Avant d'exécuter le code, il est nécessaire que des exemples des deux mondes soient compilés, car aucune compilation d'exécution de code étranger n'est effectuée, seule l'exécution.
Le projet Cross Platform GUI montre comment utiliser AWT pour créer une interface utilisateur graphique multiplateforme pour .NET Core sur les hôtes Windows et Linux. Pour utiliser Swing, remplacez simplement les commandes du code par celles que vous préférez.
Il s'agit d'un exemple basique où nous appelons la classe simple définie dans JavaClass.java à partir d'une application .NET. dans /JVM/java/src/JavaClass.java nous avons une classe simple
public class JavaClass {
/**
* This simple method return the "Hello World!!" string
* * @return "Hello World!!" string
*/
public String helloWorld ()
{
return "Hello World from Java!!" ;
}
/**
* This simple method return the sum of two double
* @param a
* @param b
* @return a + b
*/
public double add ( double a , double b )
{
return a + b ;
}
/**
* This simple method return the sin of a double
* @param a
* @return sin of a
*/
public double sin ( double a )
{
return Math . sin ( a );
}
}
dans CLRJavaClassUseExampleprogram.cs nous avons la simple application .NET C#
using MASES . LicenseManager . Common ;
using MASES . JCBridge . C2JBridge ;
using System ;
namespace JavaClassUseExample
{
class Program
{
static void Main ( string [ ] args )
{
new TestClass ( ) . Execute ( ) ;
}
class TestClass : SetupJVMWrapper
{
public override string ClassPath { get { return @"....JVMOutput" ; } }
public void Execute ( )
{
double a = 2 ;
double b = 3 ;
double c = Math . PI / 2 ;
var javaClass = DynJVM . JavaClass . @new ( ) ;
string hello = javaClass . helloWorld ( ) ;
double result = javaClass . add ( a , b ) ;
double sin = javaClass . sin ( c ) ;
Console . WriteLine ( "{0} {1} + {2} = {3} and sin({4:0.0000000}) = {5:0.00000000}" , hello , a , b , result , c , sin ) ;
}
}
}
}
En exécutant le code, nous obtenons le résultat suivant :
Hello World from Java!! 2 + 3 = 5 and sin(3,1415927) = 1,00000000
Cet exemple est une extension de l' exemple d'utilisation de classe Java dans lequel les paramètres d'environnement sont configurés dans la classe .NET TestClass .
class TestClass : SetupJVMWrapper
{
// the following line setup the classpath where JVM will search for classes
// during runtime it is possible to dynamically add other path using a call like DynJVM.JVMHelper.addPath(<the path to add>);
public override string ClassPath { get { return @"C:Program FilesMASES GroupJCOBCore;....JVMJavaOutput" ; } }
// uncomment the following line and set the correct JRE if the automatic search system fails
// public override string JVMPath { get { return @"C:Program FilesJavajre1.8.0_121binserverjvm.dll"; } }
// the following code adds all possible switch to the starting JVM.
// for a complete list see Oracle documentation: https://docs.oracle.com/javase/8/docs/technotes/tools/windows/java.html
public override IEnumerable < KeyValuePair < string , string > > JVMOptions
{
get
{
var dict = new Dictionary < string , string > ( ) ;
dict . Add ( "-Xmx128M" , null ) ; // this line adds a complete argument
// dict.Add(property, value); // this line adds an argument like -Dproperty = value
return dict ;
}
}
// the following code adds initial packages to the import statement.
public override IEnumerable < string > JVMPackages
{
get
{
var list = new List < string > ( ) ;
list . Add ( "java.lang" ) ; // this line adds java.lang.* like you do with "import java.lang.*" in Java
return list ;
}
}
// uncomment and set the following line when you need features of JDK like the use of the compiler
// public override string JDKHome { get { return @"C:Program FilesJavajdk1.8.0_121"; } }
public void Execute ( )
{
double a = 2 ;
double b = 3 ;
double c = Math . PI / 2 ;
var javaClass = DynJVM . JavaClass . @new ( ) ;
string hello = javaClass . helloWorld ( ) ;
double result = javaClass . add ( a , b ) ;
double sin = javaClass . sin ( c ) ;
Console . WriteLine ( "{0} {1} + {2} = {3} and sin({4:0.0000000}) = {5:0.00000000}" , hello , a , b , result , c , sin ) ;
Console . WriteLine ( "Press Enter to exit" ) ;
Console . ReadLine ( ) ;
}
}
Il s'agit d'une application plus complexe qui explore la capacité de JCOBridge à effectuer les opérations suivantes : -Exécuter du code Java dans l'environnement .NET à l'aide du wrapper Dynamic JVM -Gérer l'objet partagé -Enregistrer l'objet CLR du côté de la machine virtuelle Java -Utiliser l'objet enregistré du côté JVM -Appeler les méthodes sur la classe enregistrée JVM et refléter l'opération sur l'objet CLR -Créer une boîte de dialogue du côté JVM et l'utiliser à partir du code .NET
Cette bibliothèque contient une seule classe qui fournit des opérations doubles et de chaîne à appeler depuis la JVM.
Un panneau Windows Form avec sa logique complète qui sera utilisé pour démontrer l'intégration de l'interface utilisateur dans une application graphique Java.
Un panneau WPF avec sa logique complète qui sera utilisé pour démontrer l'intégration de l'interface utilisateur dans une application graphique Java.
Il s'agit d'un exemple basique où nous appelons la classe simple définie dans CSharpClass.cs à partir d'une application Java. dans CLRCSharpClassCSharpClass.cs nous avons une classe simple
using System ;
namespace MASES . CLRTests
{
public class CSharpClass
{
/// <summary>The method <c>HelloWorld</c> return the "Hello World!!" string</summary>
public String HelloWorld ( )
{
return "Hello World from C#!!" ;
}
/// <summary>The method <c>Add</c> return the sum of two double</summary>
public double Add ( double a , double b )
{
return a + b ;
}
/// <summary>The method <c>Add</c> return the sin of a double</summary>
public double Sin ( double a )
{
return Math . Sin ( a ) ;
}
}
}
dans le /JVM/src/JavaClass.java, nous avons l'application Java simple
import java . io . IOException ;
import org . mases . jcobridge .*;
public class CSharpClassUseExample {
public static void main ( String [] args ) {
try {
try {
try {
JCOBridge . Initialize ( "" );
} catch ( JCException e ) {
e . printStackTrace ();
}
} catch ( IOException e ) {
e . printStackTrace ();
}
//declare and create JCOBridge instance
JCOBridge bridge ;
bridge = JCOBridge . CreateNew ();
// adds the path where extarnal assemblies where found
bridge . AddPath ( "../CLR/Output/" );
// add REFERENCES to the .dll file
bridge . AddReference ( "CSharpClass" );
// GENERATE Object
JCObject CSharpObject = ( JCObject ) bridge . NewObject ( "MASES.CLRTests.CSharpClass" );
double a = 2 ;
double b = 3 ;
double c = Math . PI / 2 ;
//Invoke the C# class methods
String hello = ( String ) CSharpObject . Invoke ( "HelloWorld" );
double result = ( double ) CSharpObject . Invoke ( "Add" , a , b );
double sin = ( double ) CSharpObject . Invoke ( "Sin" , c );
System . out . println ( String . format ( "%s %.0f + %.0f = %.0f and sin(%.8f) = %.8f" , hello , a , b , result , c , sin ));
} catch ( JCException jce ) {
jce . printStackTrace ();
System . out . println ( "Exiting" );
return ;
}
}
}
En exécutant le code, nous obtenons le résultat suivant :
Hello World from C#!! 2 + 3 = 5 and sin(3,14159265) = 1,00000000
Dans cet exemple un peu plus complexe, nous intégrons dans une interface utilisateur awt java deux contrôles complexes différents, issus de deux bibliothèques .NET. Le premier contrôle est un Windows Form, le second est un objet WPF. L'application dans JVMJavasrcAWTWinFormsWPF.java expose le processus complet depuis la référence et la génération du contrôle jusqu'à l'enregistrement de l'écouteur d'événements .NET jusqu'à la gestion des rappels d'événements .NET.
import java . awt . Frame ;
import java . io . IOException ;
import org . mases . jcobridge .*;
public class AWTWinFormsWPF implements IJCVoidEventEmit {
public static void main ( String args []) {
new AWTWinFormsWPF (). createAndShow ();
}
int cycle = 0 ;
java . awt . TextArea gTextArea ;
// WPF
JCControl gControlWpfControl = null ;
// FORMS
JCControl gControlFormsControl = null ;
void createAndShow () {
try {
// LOGGER
IJCEventLog logger = null ;
try {
try {
JCOBridge . Initialize ( "" );
} catch ( JCException e ) {
e . printStackTrace ();
}
logger = new JCFileEventLog ( "WinFormsWPF.txt" );
} catch ( IOException e ) {
e . printStackTrace ();
}
JCOBridge bridge ;
bridge = JCOBridge . CreateNew ();
bridge . RegisterEventLog ( logger );
// adds the path where extarnal assemblies where found
bridge . AddPath ( "../../CLR/Output/" );
// add REFERENCES
bridge . AddReference ( "WPFTestControl" );
bridge . AddReference ( "WinFormsTestControl" );
// GENERATE CONTROLS
gControlWpfControl = bridge . GetControl ( "MASES.CLRTests.WPFTestControl.TestControl" );
gControlFormsControl = bridge . GetControl ( "MASES.CLRTests.WinFormsTestControl.TestControl" );
// CONFIGURE CONTROLS
gControlWpfControl . RegisterEventListener ( "FromComboBox" , this );
gControlWpfControl . RegisterEventListener ( "FromTextBox" , this );
gControlFormsControl . RegisterEventListener ( "FromComboBox" , this );
gControlFormsControl . RegisterEventListener ( "FromTextBox" , this );
Frame dialog = new Frame ();
gTextArea = new java . awt . TextArea ();
gTextArea . setText ( "This is an AWT TextArea" );
java . awt . GridLayout layout = new java . awt . GridLayout ( 2 , 2 );
dialog . setLayout ( layout );
dialog . add ( gControlWpfControl );
dialog . add ( gControlFormsControl );
dialog . add ( gTextArea );
dialog . validate ();
dialog . setTitle ( "WinForms-WPF AWT integration" );
dialog . setVisible ( true );
dialog . setSize ( 200 , 200 );
} catch ( JCException jce ) {
jce . printStackTrace ();
System . console (). readLine ( "Please press enter" );
System . out . println ( "Exiting" );
return ;
}
}
@ Override
public void EventRaised ( Object ... args ) {
System . out . println ( "EventRaised" );
if ( args [ 1 ] instanceof JCObject ) {
JCObject obj = ( JCObject ) args [ 1 ];
System . out . println ();
try {
if ( obj != null ) {
gTextArea . setText ( "Text area: event: " + obj . toString () + " Content: " + obj . Get ( "Content" ));
}
} catch ( JCException e ) {
e . printStackTrace ();
}
}
}
}
Une classe unique qui fournit des opérations doubles et de chaîne à appeler à partir du CLR .NET.
Une classe qui contient deux méthodes et affiche comment enregistrer et utiliser des variables globales et des objets partagés
import org . mases . jcobridge .*;
import java . awt .*;
public class GlobalVariableTest
{
public static void createGlobal () throws JCException
{
Dialog dialog = new Dialog (( Dialog ) null );
JCOBridge . RegisterJVMGlobal ( "SharedDialog" , dialog );
}
public static void testMyCLRClass ( Integer a , Integer b ) throws JCException
{
JCObject resultGetCLRObject = ( JCObject ) JCOBridge . GetCLRGlobal ( "MyCLRClass" );
resultGetCLRObject . Invoke ( "Add" , a , b );
}
}
La méthode createGlobal crée une boîte de dialogue awt globale et l'enregistre pour qu'elle soit utilisée de manière transparente du côté CLR. Le testMyCLRClass montre comment utiliser un objet global CLR enregistré, dans l'exemple CLR, nous créons cet objet du côté .NET et nous appelons cette fonction pour l'utiliser et démontrons que les opérations à chaud sont reflétées entre JVM et CLR de manière transparente.
Une classe Scala simple est définie pour être utilisée à partir de CLR dans JVMScalascalaclasssrcmainscalaScalaClass.class. Appelez la compilation et exécutez le script batch dans JVMScala.
Avant d'appeler, compilez et exécutez le script batch, les binaires Scala doivent être installés.
import java . lang . _
final class ScalaClass ( aString : String , val anInteger : Int ) {
def this () {
this ( "defaultString" , - 1 )
}
def this ( aBool : Boolean ) {
this ( "defaultString" , - 1 )
}
val scalaString = "This is a Scala String"
def add ( x : Int , y : Int ): Int = x + y
def stringConcat ( args : Array [ String ]): String =
{
return args . mkString ( ", " )
}
}
Dans CLRScalaClassUseExampleProgram.cs, nous avons une application simple qui utilise la ScalaClass définie
using CommonTest ;
using MASES . JCOBridge . C2JBridge ;
using MASES . LicenseManager . Common ;
using System ;
using System . IO ;
namespace ScalaClassUseExample
{
class TestClass : BaseTestClass
{
public override string GetProjectClassPath ( )
{
#if ! JCOBRIDGE_CORE
return @"....JVMScalaOutput" ;
#else
return @"......JVMScalaOutput" ;
#endif
}
public override string ClassPath
{
get
{
return new ClassPathBuilder ( GetProjectClassPath ( ) + @"*" , @"C:Program Files (x86)scalalib*.jar" ) . Build ( ) ;
}
}
public override void Execute ( )
{
int a = 10 ;
int b = 15 ;
var scalaClass = DynJVM . ScalaClass . @new ( ) ;
var result = scalaClass . add ( a , b ) ;
Console . WriteLine ( "{0} + {1} = {2}" , a , b , result ) ;
string [ ] strings = new string [ ] { "One" , "Two" , "Three" } ;
var concatString = scalaClass . stringConcat ( strings ) ;
Console . WriteLine ( "{0} = {1}" , string . Concat ( strings ) , concatString ) ;
Console . WriteLine ( "Press Enter to exit" ) ;
Console . ReadLine ( ) ;
}
}
class Program
{
static void Main ( string [ ] args )
{
try
{
new TestClass ( ) . Execute ( ) ;
}
catch ( Exception e )
{
Console . WriteLine ( e . Message ) ;
Console . WriteLine ( "Press any key." ) ;
Console . ReadKey ( ) ;
}
}
}
}
Dans Scala, toutes les bibliothèques nécessaires doivent être explicitement ajoutées au chemin de base.
Dans cet exemple, nous appelons un objet .NET depuis le langage Scala via JCOBridge. Avant d'appeler, compilez et exécutez le script batch, les binaires Scala doivent être installés.
import java . util . Iterator
import org . mases . jcobridge . _
object Main extends App {
try
{
JCOBridge . Initialize ();
}
catch
{
// catch to avoid problem with Trial mode of JCOBridge
case jce : JCException => System . out . println ( jce . getMessage )
}
val bridge = JCOBridge . CreateNew ()
// adds a new reference to WPF
bridge . AddReference ( "PresentationFramework" )
// get MessageBox type
val msgType = bridge . GetType ( "System.Windows.MessageBox" )
// invoke static method to show a message box on the screen
msgType . Invoke ( "Show" , "Please press enter to continue" )
// get .NET type
val enumType = bridge . GetType ( "System.Environment" )
// invokes static method
val genObj = enumType . Invoke ( "GetLogicalDrives" )
// retrieve the iterator
val iteratorObj = genObj . asInstanceOf [ JCObject ]. iterator
// iterate on all object and print the value
while ( iteratorObj . hasNext ) println ( iteratorObj . next )
// invoke static method to show a message box on the screen
msgType . Invoke ( "Show" , "Please press enter" )
// event callback example
val tObj = bridge . NewObject ( "System.Timers.Timer" ); // create the timer object
val timerObj = tObj . asInstanceOf [ JCObject ];
// register an event handler when the Timer elaps
timerObj . RegisterEventListener ( "Elapsed" , new ScalaJCVoidEventEmit ());
// set Interval property
timerObj . Set ( "Interval" , 1000 ); // set properties
// enable the Timer
timerObj . Set ( "Enabled" , true ); // start timer
// invoke static method to show a message box on the screen
msgType . Invoke ( "Show" , "Please press enter" )
}
final class ScalaJCVoidEventEmit () extends JCVoidEventEmit {
override def EventRaised ( args : Object *) : Unit =
{
// scala seems to have a problem to translate var args argument into JVM bytecode. This method is needed to avoid compilation problems
}
// this method defines exactly the signature expected from the event
def EventRaised ( sender : Object , arg : Object ) : Unit =
{
println ( "Timer Elapsed" )
}
}