JCOBridge basiert auf dem praxiserprobten DLR-Plugin, das in der Sinapse-Plattform verfügbar ist, und garantiert die beste Leistung bei der Integration von JVM- und CLR-Welten.
- CLR-Typ abrufen
- CLR-Objekt instanziieren
- Rufen Sie statische Methoden auf
- Instanzmethoden aufrufen
- Statische Eigenschaften abrufen/festlegen
- Instanzeigenschaften abrufen/festlegen
- Delegierte festlegen
- Veranstaltungen abonnieren/abbestellen
- Integriert WPF-Steuerelemente in das AWT/Swing-Fenster
- Integrieren Sie WinForms-Steuerelemente in das AWT/Swing-Fenster
- Integrieren Sie komplexe grafische .NET-Benutzeroberflächenobjekte in das AWT/Swing-Fenster
- Benutzeroberfläche, Steuerelemente, Eigenschaften und Ereignisverwaltung
- Rufen Sie die JVM-Klasse ab
- Instanziieren Sie JVM-Objekte
- Rufen Sie statische Methoden auf
- Instanzmethoden aufrufen
- Statische Felder abrufen/festlegen
- Instanzfelder abrufen/festlegen
- Verwenden Sie dynamischen Zugriff, um Code nahtlos zu schreiben, wie dies in der Java-Sprache geschieht
- Verwenden Sie eine bestimmte Schnittstelle, um Methoden und Felder direkt zu verwalten
JCOBridge (JVM-CLR Object Bridge) ermöglicht die Ausführung von JVM-Muttersprachen wie Java und Scala aus CLR/.NET-Sprachen und umgekehrt. Es ermöglicht den Import und die Verwendung von Bibliotheken und Komponenten sowie die Verwaltung der grafischen Benutzeroberfläche von einem einzigen Gerät aus Programmierwelt zum anderen. Weitere Informationen unter www.jcobridge.com
Um die Beispiele zu erkunden, müssen Sie die folgenden Schritte ausführen:
In diesem Repository finden Sie Beispielcode für die verschiedenen von JCObridge unterstützten Programmiersprachen. Die Beispiele sind in zwei Hauptordnern organisiert, JVM und CLR, die die entsprechenden Projekte enthalten. Vor der Ausführung des Codes müssen Beispiele aus beiden Welten kompiliert werden, da keine Laufzeitkompilierung von Fremdcode erfolgt, sondern nur die Ausführung.
Das Projekt Cross Platform GUI zeigt, wie man mit AWT eine plattformübergreifende grafische Benutzeroberfläche für .NET Core auf Windows- und Linux-Hosts erstellt. Um Swing zu verwenden, ändern Sie einfach die Steuerelemente im Code auf Ihre bevorzugten.
Dies ist ein einfaches Beispiel, bei dem wir die in JavaClass.java definierte einfache Klasse aus einer .NET-Anwendung aufrufen. In /JVM/java/src/JavaClass.java haben wir eine einfache Klasse
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 );
}
}
In CLRJavaClassUseExampleprogram.cs haben wir die einfache .NET C#-Anwendung
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 ) ;
}
}
}
}
Wenn wir den Code ausführen, erhalten wir die folgende Ausgabe:
Hello World from Java!! 2 + 3 = 5 and sin(3,1415927) = 1,00000000
Dieses Beispiel ist eine Erweiterung des Java-Klassenanwendungsbeispiels , in dem Umgebungsparameter in der .NET- TestClass -Klasse konfiguriert werden.
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 ( ) ;
}
}
Dies ist eine komplexere Anwendung, die die Fähigkeit von JCOBridge untersucht, die folgenden Vorgänge auszuführen: - Java-Code in der .NET-Umgebung mit dem dynamischen JVM-Wrapper ausführen - Gemeinsam genutzte Objekte verwalten - CLR-Objekt auf der Seite der Java Virtual Machine registrieren - Das registrierte Objekt verwenden von der JVM-Seite - Rufen Sie Methoden für die in der JVM registrierte Klasse auf und lassen Sie den Vorgang im CLR-Objekt widerspiegeln. - Erstellen Sie ein Dialogfeld auf der JVM-Seite und verwenden Sie es aus dem .NET-Code
Diese Bibliothek enthält eine einzelne Klasse, die Doppel- und String-Operationen bereitstellt, die von der JVM aufgerufen werden können.
Ein Windows Form-Panel mit seiner vollständigen Logik, das zur Demonstration der Benutzeroberflächenintegration in einer Java-Grafikanwendung verwendet wird.
Ein WPF-Panel mit seiner vollständigen Logik, das zur Demonstration der Benutzeroberflächenintegration in einer grafischen Java-Anwendung verwendet wird.
Dies ist ein einfaches Beispiel, bei dem wir die in CSharpClass.cs definierte einfache Klasse aus einer Java-Anwendung aufrufen. In CLRCSharpClassCSharpClass.cs haben wir eine einfache Klasse
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 ) ;
}
}
}
In /JVM/src/JavaClass.java haben wir die einfache Java-Anwendung
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 ;
}
}
}
Wenn wir den Code ausführen, erhalten wir die folgende Ausgabe:
Hello World from C#!! 2 + 3 = 5 and sin(3,14159265) = 1,00000000
In diesem etwas komplexeren Beispiel integrieren wir zwei verschiedene komplexe Steuerelemente aus zwei .NET-Bibliotheken in eine AWT-Java-Benutzeroberfläche. Das erste Steuerelement ist ein Windows Form, das zweite ein WPF-Objekt. Die Anwendung in JVMJavasrcAWTWinFormsWPF.java stellt den gesamten Prozess von der Steuerreferenz und Generierung über die Registrierung des .NET-Ereignis-Listeners bis hin zur Rückrufverwaltung für .NET-Ereignisse bereit.
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 ();
}
}
}
}
Eine einzelne Klasse, die Doppel- und Zeichenfolgenoperationen bereitstellt, die von der .NET-CLR aufgerufen werden können.
Eine Klasse, die zwei Methoden enthält und anzeigt, wie gemeinsam genutzte globale Variablen und Objekte registriert und verwendet werden
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 );
}
}
Die Methode „createGlobal“ erstellt einen globalen AWT-Dialog und registriert ihn für die nahtlose Verwendung von der CLR-Seite. Die testMyCLRClass zeigt, wie ein registriertes globales CLR-Objekt verwendet wird. Im CLR-Beispiel erstellen wir dieses Objekt von der .NET-Seite und rufen diese Funktion auf, um es zu verwenden und zu demonstrieren, dass Hot-Operationen zwischen JVM und CLR auf transparente Weise widergespiegelt werden.
Eine einfache Scala-Klasse ist für die Verwendung von CLR in JVMScalascalaclasssrcmainscalaScalaClass.class definiert. Rufen Sie das Kompilieren auf und führen Sie das Batch-Skript in JVMScala aus
Vor dem Aufruf zum Kompilieren und Ausführen des Batch-Skripts müssen Scala-Binärdateien installiert werden.
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 ( ", " )
}
}
In CLRScalaClassUseExampleProgram.cs haben wir eine einfache Anwendung, die die definierte ScalaClass verwendet
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 ( ) ;
}
}
}
}
In Scala müssen alle benötigten Bibliotheken explizit zum Basispfad hinzugefügt werden.
In diesem Beispiel rufen wir ein .NET-Objekt aus der Scala-Sprache über JCOBridge auf. Vor dem Aufruf zum Kompilieren und Ausführen des Batch-Skripts müssen Scala-Binärdateien installiert werden.
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" )
}
}