Construido sobre el complemento DLR probado en el campo disponible en la plataforma Sinapse, JCOBridge garantiza el mejor rendimiento en la integración de los mundos JVM y CLR.
- Recuperar tipo CLR
- Crear una instancia del objeto CLR
- Invocar métodos estáticos
- Invocar métodos de instancia
- Obtener/establecer propiedades estáticas
- Obtener/establecer propiedades de instancia
- Establecer delegados
- Suscribir/Cancelar suscripción a eventos
- Integra controles WPF en la ventana AWT/Swing
- Integre los controles de WinForms en la ventana AWT/Swing
- Integre objetos complejos de interfaz gráfica de usuario .NET en la ventana AWT/Swing
- Interfaz de usuario Controles, propiedades y gestión de eventos.
- Recuperar clase JVM
- Crear instancias de objetos JVM
- Invocar métodos estáticos
- Invocar métodos de instancia
- Obtener/establecer campos estáticos
- Obtener/establecer campos de instancia
- Utilice el acceso dinámico para escribir código de forma sencilla como se hace en el lenguaje Java.
- Utilice una interfaz específica para dirigir los métodos y campos de gestión.
JCOBridge (JVM-CLR Object Bridge) permite la ejecución de lenguajes nativos JVM, como java y scala, desde lenguajes CLR/.NET y viceversa, permite importar y usar bibliotecas, componentes y también administrar la interfaz gráfica de usuario desde uno. mundo de la programación al otro. Más información en www.jcobridge.com
Para explorar los ejemplos, debe realizar los siguientes pasos:
En este repositorio es posible encontrar código de ejemplo para los diferentes lenguajes de programación soportados por JCObridge. Los ejemplos están organizados en dos carpetas principales, JVM y CLR que contienen los proyectos relativos. Antes de ejecutar el código, es necesario compilar ejemplos de ambos mundos, porque no se realiza ninguna compilación en tiempo de ejecución de código externo, solo ejecución.
La GUI multiplataforma del proyecto muestra cómo utilizar AWT para crear una interfaz gráfica de usuario multiplataforma para .NET Core en hosts Windows y Linux. Para usar Swing simplemente cambie los controles dentro del código por los que prefiera.
Este es un ejemplo básico en el que llamamos a la clase simple definida en JavaClass.java desde una aplicación .NET. en /JVM/java/src/JavaClass.java tenemos una clase 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 );
}
}
en CLRJavaClassUseExampleprogram.cs tenemos la aplicación .NET C# simple
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 ) ;
}
}
}
}
Al ejecutar el código tenemos el siguiente resultado:
Hello World from Java!! 2 + 3 = 5 and sin(3,1415927) = 1,00000000
Este ejemplo es una extensión del Ejemplo de uso de clase Java donde los parámetros de entorno se configuran en la clase .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 ( ) ;
}
}
Esta es una aplicación más compleja que explora la capacidad de JCOBridge para realizar las siguientes operaciones: -Ejecutar código Java en el entorno .NET utilizando el contenedor Dynamic JVM -Administrar objetos compartidos -Registrar objetos CLR en el lado de la máquina virtual Java -Usar el objeto registrado desde el lado JVM -Llamar métodos en la clase registrada JVM y hacer que la operación se refleje en el objeto CLR -Crear un cuadro de diálogo en el lado JVM y usarlo desde el código .NET
Esta biblioteca contiene una única clase que proporciona operaciones dobles y de cadena que se llamarán desde JVM.
Un panel de Windows Form con su lógica completa que se utilizará para demostrar la integración de la interfaz de usuario en una aplicación gráfica Java.
Un panel WPF con su lógica completa que se utilizará para demostrar la integración de la interfaz de usuario en una aplicación gráfica Java.
Este es un ejemplo básico en el que llamamos a la clase simple definida en CSharpClass.cs desde una aplicación Java. en CLRCSharpClassCSharpClass.cs tenemos una clase 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 ) ;
}
}
}
en /JVM/src/JavaClass.java tenemos la aplicación 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 ;
}
}
}
Al ejecutar el código tenemos el siguiente resultado:
Hello World from C#!! 2 + 3 = 5 and sin(3,14159265) = 1,00000000
En este ejemplo un poco más complejo integramos en una interfaz de usuario awt java dos controles complejos diferentes, tomados de dos bibliotecas .NET. El primer control es un Windows Form, el segundo es un objeto WPF. La aplicación en JVMJavasrcAWTWinFormsWPF.java expone el proceso completo desde la referencia y generación del control hasta el registro del detector de eventos .NET y la administración de devolución de llamadas de eventos .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 ();
}
}
}
}
Una clase única que proporciona operaciones dobles y de cadena que se llamarán desde .NET CLR.
Una clase que contiene dos métodos y muestra cómo registrar y usar variables y objetos globales compartidos.
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 );
}
}
El método createGlobal crea un cuadro de diálogo awt global y lo registra para usarlo sin problemas desde el lado de CLR. testMyCLRClass muestra cómo usar un objeto global CLR registrado; en el ejemplo de CLR creamos este objeto desde el lado .NET y llamamos a esta función para usarlo y demostrar que las operaciones activas se reflejan entre JVM y CLR de manera transparente.
Se define una clase Scala simple para usarse desde CLR en JVMScalascalaclasssrcmainscalaScalaClass.class Llame a compilar y ejecutar script por lotes en JVMScala
Antes de llamar a compilar y ejecutar el script por lotes, se instalarán los binarios de Scala.
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 ( ", " )
}
}
En CLRScalaClassUseExampleProgram.cs tenemos una aplicación simple que usa la ScalaClass definida
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 ( ) ;
}
}
}
}
En Scala, todas las bibliotecas necesarias se agregarán explícitamente a la ruta base.
En este ejemplo llamamos al objeto .NET desde el lenguaje Scala a través de JCOBridge. Antes de llamar a compilar y ejecutar el script por lotes, se instalarán los binarios de Scala.
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" )
}
}