![]() |
Re: Delphi mit Java komunizieren
so nach eine langen Pause gehts weiter.
Also den Array den man nun als Pointer gespeichert hat, kann man nun folglich abrufen p[0] usw. Wie siehts mit mehrdimensionalen Arrays aus? Werden gleichermaßen geholt oder ?
Delphi-Quellcode:
hm. 1. hab ich jetzt nen 2d array und kann einfach so aufrufen : p[0,1] ?
// Aufruf der Methode
buffer := JIntArray(self.jvm.JniEnv.CallObjectMethod(instance, mid, [])); p := PIntegerArray(self.jvm.JniEnv.GetIntArrayElements(buffer, isCopy)); 2. Wie sähe denn die Signtur bei der Ermittlung der MethodenID aus ? einfach so ? : [I ? |
Re: Delphi mit Java komunizieren
Zitat:
Zitat:
Zitat:
[ADD] Hm, bin mir eigentlich doch nicht so sicher. Ich meine in Java sind mehrdimensionale Arrays echte Arrays of Array. Das heißt natürlich, dass hier ein Array von Referenzen gespeichert wird. Das wiederum heißt, jedes Array hat eigene Eigenschaften (z.B. seine Länge). Der sichere Weg ist es hier einfach nur eindimensional auf Arrays zuzugreifen (z.B. angelehnt an die Scanline). Hier siehst du wieder, warum ich schon sagte, dass man möglichst die primitiven Datentypen nehmen sollte. Es ist einfach der Unterschied komplett verschiedener Programmieransätze, der hier durch kommt. Wären die immer 100% kompatibel würde man sich schnell fragen ob man beide Sprachen braucht. Jedenfalls kann es sein, dass du hier eine Art Adapter bemühen solltest, der einfach mehrdimensionale Arrays eindimensional zurückgeben kann. [/ADD] |
Re: Delphi mit Java komunizieren
Und ich wieder :)
so hab lange nix gemacht, aber jetzt gehts weiter. Also das Handbuch is soweit fertig. 1 )Ich mach mich jetzt an dieses Beispiel programm. Das ganze Programm und alle Klassen sind in einem Jar gespeichert und meine frage ist, brauch ich die .*class dateien oder reicht dieses jar ? wenn ja wie ? 2 ) So ich habe eine Klasse in einer Datei und gebe deren Pfad an. Danach erzeuge ich ein Objekt dieser Klasse und speicher das Objekt als ein JObject. Bei dem Constructor vder Klasse wird aber eine anderes Objekt einer anderen Klasse automatisch erzeugt. Meine Frage ist: Wie können sich selbstgeschriebene Klassen untereinander finden. ?! ist das einfach so möglich ? oder müssen die Dateien in einem Ordner liegen? Finden die sich nur wenn sie in eimem gemeinsamen jar oder .java bleiben (so wie sie eben programmiert wurden) ? |
Re: Delphi mit Java komunizieren
Hm,
diesmal bin ich mir wirklich unsicher, was du eigentlich wissen möchtest. An sich würde ich dir hier wohl eher zu einem Javabuch (sehr gut ist Java ist auch nur eine Insel, kostenlos online erhältlich) raten als zu meiner Hilfe. Autoren solcher Bücher haben didaktisch wohl um einiges mehr drauf und erklären (hoffentlich) aufbauend und schrittweise und erklären alles korrekt (zumindest in guten Büchern). Ich weiß nicht genau, wo dein jar herkommt. An sich gibt es hier ein eigenes Kapitel, über diese Art von Dateien. Ein .jar ist eigentlich nur ein einfaches Archiv, in dass du mehrere Dateien packen kannst. Der Vorteil liegt klar auf der Hand, du hast eine Datei, die du so komplett weiter reichen kannst. Zudem gibt es noch verschiedene Möglichkeiten, weitere Dinge einzubinden / anzustellen. So ist ein jar auch gepackt (weiß gar nicht ob es auch unkromprimiert wie tar verwendet werden kann, glaube aber es war so). Dann hast du noch eine ganz wichtige Datei, das Manifest. Hier kannst du zum Beispiel eine main-class bekannt machen. Steht eine solche in der Manifest und enthält eine main Methode, ist dein jar direkt startbar. Zu dem Umgang mit Jars kann ich dir eigentlich nur ein Buch bzw. die Sun Seiten nahe legen, da du hier wirklich vollständig die Möglichkeiten erklärt bekommst. In der Regel hat jede IDE (z.B. Eclipse) gleich eine gute Kapselung, so dass du auch bei jars nicht die Kommandozeile bemühen musst (es aber kannst). Einer der wichtigsten Vorteile von jars ist es, dass du diese transparent in den Classpath einbinden kannst. Die Datei wird dabei einfach als Pfad behandelt. Alle .class Dateien in diesem jar kann Java wie lokale .class Dateien, die entpackt auf der Platte liegen behandeln. Die Standardklassen liegen auch als .jar in deiner JRE / dem JDK vor. Zitat:
Wenn der Konstruktor etwas erzeugt, so tut er dies ja eigentlich in Java. Dies passiert damit automatisch und ohne deinen Eingriff in Delphi. Was du mit dem Finden von verscshiedenen Klassen meinst weiß ich jetzt nicht genau. In Java wird eine Klasse qualifiziert aufgerufen. Klassen liegen in einem Package, welches wiederum in einem package liegen kann usw. Jedenfalls würdest du eine Klasse ungefähr so anlegen:
Code:
Durch das package.subpackage legst du fest, wo Class1 herkommt. In einem Package darf dann nur eine Klasse mit diesem Namen liegen. Der Einfachheit halber kannst du eine Klasse auch samt package importieren. Hier steht einmal im Kopf deiner .java Datei der import Befehl. Alle Klassen im gleichen package sind aut. bekannt. Solche die du hier importierst können ohne das Präfix des package verwendet werden. Hast du jetzt aber zwei Klassen mit gleichem Namen, stellst du wiederum durch die Qualifizierung sicher, dass du die richtige Klasse adressierst (ansonsten würde die Reihenfolge der Imports entscheiden).
package.subpackage.Class1 = new package.subpackage.Class1();
Ja, wie gesagt, was du hier mit finden meinst, da bin ich mir nicht ganz sicher. Die einzelnen Dateien müssen halt im Suchpfad von Java für Klassen liegen (der so genannte Classpath). Ja, mehr als eine Klasse in eine .java Datei zu packen ist immer ganz schlecht! Die Ordner Struktur bildet eigentlich nur die Struktur der Packages ab. Ob die Dateien in einem Ordner oder in einem jar (und hier in einem Ordner des Archivs) liegen ist letztlich egal. Du musst die .class Dateien immer in den Ordner packen, der dem package entspricht. Ein Unterordner entspricht also einem subpackage. Das oberste Element (der Wurzelordner) muss hier im Classpath liegen, damit Dateien relativ zu diesem Pfad gefunden werden können (für ein .jar File heißt das, dass dieses .jar im Classpath liegen muss). |
Re: Delphi mit Java komunizieren
OK. ich werd mal genauer.
Also ich hab in der DateiA eine klasse namens Map. erzeuge ich ein Objekt dieser Klasse so wird automatisch beim Erzeugen der Klasse vom Java Quelltext aus ein weiteres Objekt einer anderen Klasse die aber in DateiB vorliegt. Ich gebe also den Classpath der DateiA an um die Klasse und den Konstruktor zu finden und rufe den auf. Meine frage ist nun . Kann der Constructor die DateiB (und damit die weitere Klasse) einfach so finden? und die zweite frage war eben zum Jar. Da sind alle meine Klassen gespeichert (Auch DateiA und DateiB). Wie rufe ich genau den Path auf ? cls := self.jvm.JniEnv.FindClass('SpatialCommander.jar\Da teiA');?? |
Re: Delphi mit Java komunizieren
Liste der Anhänge anzeigen (Anzahl: 1)
Zitat:
Zitat:
Viel viel besser ist es, wenn man in dem Ordner, indem das Programm liegt die richtige Version der verwendeten Bibliotheken/Klassen findet. Java kann per Schalter mehrere Pfade für eine JVM in den Classpath aufnehmen. In der Delphikapselung gibst du den Java-Classpath im Konstruktor der TJVM an. Hier wird der Ort angegeben, in dem alle Packages liegen, die du zusätzlich zu den Standardbibliotheken verwendest. In den Beispielprogrammen von mir ist dies der Unterordner Java/bin. Jetzt fällt dir sicherlich auf, dass du aber keine Datei in diesem Unterordner findest, erst im Ordner /Java/bin/package1/subpackage/ liegt dann die .class Datei. Wenn du dir die .java Datei der Klasse anschaust, findest du hier auch den Eintrag package package1.subpackage; Ist natürlich kein Zufall. Ein Java Package wird auf die Verzeichnisstruktur abgebildet. Java sucht also die Klasse A aus dem Package package1.subpackage im Classpath. Dazu wird nach dem Ordner package1 gesucht, der einen Unterordner subpackage hat, in dem die Klasse liegt. Weitere Subpackages würden weitere Unterordner mit sich bringen. Dateien eines Packages befinden sich damit natürlich immer im gleichen Ordner. Ich hoffe/denke soweit ist erstmal alles klar? Ja, der Vollständigkeit halber sei hier natürlich noch gesagt, die Klasse allein (ohne Ordner und Unterordner) kann nicht verwendet werden. Liegt sie in einem Package muss diese Struktur auch abgebildet sein. Dies ist einfach schon deshalb erforderlich, da sonst die Klasse A aus package1 und die völlig andere Klasse A auf package2 nicht einfach irgendwo liegen dürfen, man möchte sie schließlich unterscheiden! Ok, was hat das alles mit deiner ursprünglichen Frage zu tun? Ganz einfach: Klasse A möchte eine Instanz von Klasse B erzeugen. Lässt sich Klasse B im Classpath finden, ist das kein Problem. Liegt Klasse B im selben Package wie A tritt nie ein Problem auf. Ansonsten musst du schauen. Liegen die Packages im selben Wurzelordner (im Beispiel wäre dies der Unterordner Java/bin/), würde B gefunden werden (Java/bin/ wird komplett in den Classpath übernommen). In der Regel wirst du genau diesen Fall haben. Da ich gleich auf die .jar Dateien eingehen werde, lasse ich hier den anderen Fall einfach mal aussen vor (ich kann da eh nichts zu sagen!). Zitat:
Ein .jar File ist wirklich eine tolle Erfindung. Das wichtigste Prinzip hast du schon benannt, du hast alle Klassen in einer Datei. Du kannst dein ganzes Programm einfach in eine einzige Datei packen und hast alles was du brauchst. Wichtig ist hier, dass du eine .jar Datei wie einen lokalen Ordner behandeln kannst. Du hast nicht direkt die Dateien A und B in dem jar File, sondern sie liegen in einem Unterverzeichnis, dass dem Package entspricht. Für Java verhält sich ein .jar File transparent. Java merkt nicht, dass es ein Archiv ist sondern behandelt diese Datei wie einen normalen Pfad. Du kannst es dir so vorstellen, als ob Java das Archiv aut. entpackt und du dich nun im Wurzelordner des entpackten Archivs befindest. Das heißt, du kannst auch einfach eine komplette .jar in deinen Classpath aufnehmen und alle Packages die hier drin stecken sind aut. im Classpath zu finden (mit ihren Klassen natürlich). Auch für ein .jar sind nur die .class Dateien wichtig. Die .java sind immer QC und müssen nicht mitgeliefert werden. Ist nur Wichtig bevor du Kunden Quellcode aushändigst :wink: Wenn du also die jar Datei in den Classpath steckst, kannst du ganz normal auf die Klassen zugreifen. Du musst Java nicht sagen, dass die in einem .jar liegen, dass merkt Java eh nicht. Du greifst ganz normal auf das Package zu. Ich habe das bekannte Beispiel nochmal mit einem .jar erstellt. Also genau genommen habe ich einfach nur die Unterordner java/bin und java/src entfernt und ihren Inhalt in ein sehr einfaches jar gesteckt. Im jar findest du die Dateien TestClass.class/.java in dem Unterverzeichnis package1/subpackage (also dem eingetragenen Package). TJvm bekommt nun als Classpath den Pfad der .jar Datei. Das Laden der Klasse erfolgt wie gewohnt mittels
Delphi-Quellcode:
Diese Zeile ist wirklich unverändert. Ich hoffe das zeigt dir nochmal, dass die .jars wirklich transparent für Java sind. Hier gibt es keinen Unterschied zu einem lokalen Verzeichnis, es gelten die gleichen Regeln. Allerdings kann ein .jar File noch ein wenig mehr (was du dann in den Details der Manifest Datei findest).
cls := self.jvm.JniEnv.FindClass('package1/subpackage/TestClass);
An sich sind .jar Files sehr gut zu verwenden. Du hast eine einfache und kompakte Form alles wichtige zusammen zu halten und weiter zu reichen. Hier sollte auch noch mal deutlich gesagt werden, dass du so sehr leicht konsistente Versionen von Programmen erstellen und verwalten kannst. Liegen alle verwendeten (nicht Standardklassen) in deinem .jar, ist dieses so komplett und kann verwendet werden. Keine Versionskonflikte und (hoffentlich) keine anderen Probleme. Wie gesagt, häufig werden .jars auch gleich startfähig ausgeliefert, dann hast du eine startbare Datei und musst dich um nichts kümmern. Ja, anbei das veränderte / neue Beispiel. Hoffe das macht die Verwendung noch etwas klarer. |
Re: Delphi mit Java komunizieren
Ok .. war zu voreilig :D
hab grad gemerkt ich muss die dateien noch compilieren. Mach ich morgen und dann sehen ma weiter .. aber danke schonmal :) |
Re: Delphi mit Java komunizieren
Ich muss da noch mal nachhaken. Ich bin jetzt erstmal auf Delphi umgestiegen, damit ich irgendwie weiterkomme.
Mein Java-Programm sieht so aus:
Code:
Jetzt will ich die Methode Test aufrufen:
public class HelloWorld {
public static void main(String[] argv) throws Exception { HelloWorld test = new HelloWorld(); int res = test.Test(); System.in.read(); System.out.print(res); } public int Test() { System.out.print("Hello, world\n"); return 42; } }
Delphi-Quellcode:
Aber er findet die Methode Test nicht. Was mache ich da falsch?
procedure TForm1.FormCreate(Sender: TObject);
begin Jvm := TJvm.create('..\..\JavaDemo'); end; procedure TForm1.Button1Click(Sender: TObject); var cls : JClass; mid : JMethodID; result : JInt; instance : JObject; begin cls := self.jvm.JniEnv.FindClass('HelloWorld'); Assert(Assigned(cls), 'Class HelloWorld not found'); mid := self.jvm.JniEnv.GetMethodID(cls, '<init>', '()V'); Assert(Assigned(mid), 'Constructor not found'); instance := self.jvm.JniEnv.NewObject(cls, mid, []); mid := self.jvm.JniEnv.GetMethodID(cls, 'Test', '(I)I'); Assert(Assigned(mid), 'Method "Test" not found'); result := self.jvm.JniEnv.CallIntMethod(instance, mid, [10]); ShowMessage('Result = ' + IntToStr(result)); end; OK, habe es gefunden. Die Signatur hat nicht gestimmt. So muss es aussehen:
Delphi-Quellcode:
mid := self.jvm.JniEnv.GetMethodID(cls, 'Test', '()I');
|
Re: Delphi mit Java komunizieren
Ein Problem ist jetzt doch noch aufgetaucht: Wie muss ich eine Methode aufrufen, die einen String zurückgibt?
Ich habe es so probiert:
Delphi-Quellcode:
Aber da findet er die Methode nicht:
procedure TForm1.btnStrTestClick(Sender: TObject);
var cls : JClass; mid : JMethodID; result : JString; instance : JObject; begin cls := self.jvm.JniEnv.FindClass('HelloWorld'); Assert(Assigned(cls), 'Class HelloWorld not found'); mid := self.jvm.JniEnv.GetMethodID(cls, '<init>', '()V'); Assert(Assigned(mid), 'Constructor not found'); instance := self.jvm.JniEnv.NewObject(cls, mid, []); mid := self.jvm.JniEnv.GetMethodID(cls, 'strTest', '()Ljava/lang/String'); Assert(Assigned(mid), 'Method "strTest" not found'); result := self.jvm.JniEnv.CallObjectMethod(instance, mid, []); ShowMessage('Result = ' + String(result)); end;
Code:
Hat sich auch erledigt. Sio geht es:
public String strTest()
{ return "Hello, world"; }
Delphi-Quellcode:
mid := self.jvm.JniEnv.GetMethodID(cls, 'strTest', '()Ljava/lang/String;');
Assert(Assigned(mid), 'Method "strTest" not found'); result := self.jvm.JniEnv.CallObjectMethod(instance, mid, []); ShowMessage('Result = ' + jvm.JniEnv.JStringToString(result)); |
Re: Delphi mit Java komunizieren
Zitat:
Delphi-Quellcode:
So sollte eigentlich alles klappen (ungetestet).
mid := self.jvm.JniEnv.GetMethodID(cls, 'strTest', '()Ljava/lang/String;');
|
Re: Delphi mit Java komunizieren
Hallo Miteinander, Ciao der Unwissende
Hab in der letzten Zeit wieder ein bisschen rumexperimentiert.... Jedoch stehe ich schon wieder etwas an... Habe folgender Code in Java geschrieben:
Delphi-Quellcode:
Das ganze wurde in einem .jar verpackt (2 Klassen "HelloWorld" und "HelloWorld2")
package test.d2j;
import test.d2j2.HelloWorld2; public class HelloWorld { public String Test(String name){ return "Ciao " + name; } public String Test2(String name){ HelloWorld2 hw2 = new HelloWorld2(); return hw2.Test(name); } } Soweit so gut. Keine Probleme mit mehreren Klassen in einem .jar beim Aufruf von Test2 via Delphi. Jetzt wollte ich aber zusätzlich das log4j einbinden. Das würde folgendermasse aussehen:
Delphi-Quellcode:
Und hier hänge ich wieder...
package test.helsana;
import org.apache.log4j.Logger; import test.helsana2.HelloWorld2; public class HelloWorld { private static Logger logger = Logger.getLogger( HelloWorld.class ); public String Test(String name){ return "Ciao " + name; } public String Test2(String name){ HelloWorld2 hw2 = new HelloWorld2(); return hw2.Test(name); } } Sobald ich den Logger einschalten will, findet er die Klasse nicht. Kann mir jemand weiterhelfen? Greez Bucchi |
Re: Delphi mit Java komunizieren
hey .. sorry .. muss auch noch nefrage stellen.
bei der ermittlung der MethodenID muss man ja die Übergabetypen festlegen. I steht für Integer usw.... was ist aber bei einer Objektübergabe. Reicht da folgende Zeile ? Lfully-qualified-class; oder hab ioch das falsch verstanden uns es muss folgendermaßen heißenm L<Classenname> ; oder wie soll das gehen ? |
Re: Delphi mit Java komunizieren
Achja noch ein weiteres Problem. Ich hab hier maln quelltext Form1.MiniSC.MBMap.obj ist hierbei das objekt der Klasse MBMap , dass ich schon erzeugt habe ..
Delphi-Quellcode:
Wenn ich haber die funktion newObject aufruf kommt ein fehler .. und zwar folgender :
cls := jvm.JniEnv.FindClass('com/gdv/mapbuilder/gui/MBMenuBar');
if cls = nil then ShowMessage('Klasse "MBMenuBar" nicht gefunden'); ConstructorMid := jvm.JniEnv.GetMethodID(cls, '<init>', '(Lcom/gdv/mapbuilder/MBMap;)V'); if ConstructorMid = nil then ShowMessage('Konstruktor nicht gefunden'); Obj := jvm.JniEnv.NewObject(cls, ConstructorMid, [Form1.MiniSC.MBMap.Obj]); if Obj = nil then ShowMessage('Fehler beim erzeugen der Instanz'); "im Projekt SC.ece ist eine Exception der Klasse EAccressViolation mit der Meldung"zugriffsverletzung bei Adresse 0047ßb74 in Modul "SC.exe". Lesen von adresse 00000004" aufgetreten" Die ShowMessage (Fehler beim erzeugen der Instanz kommt) nicht. hatter die instanz jetzt richtig erzeugt ?! .. ist meine übergabe [Form1.MiniSC.MBMap.Obj]); überhaupt richtig ?! .. oder übergeb ich da was anderes als das Objekt (Der klasse JObject) Gruß Simon |
Re: Delphi mit Java komunizieren
Zitat:
Zitat:
Liegt denn das jar File zu log4j im Klassenpfad? Nur da kann dann eine solche Klasse gefunden werden. Gruß Der Unwissende |
Re: Delphi mit Java komunizieren
Zitat:
Zitat:
Gruß Der Unwissende PS.: Wegen der Dauer der Antwort gilt das gleiche wie im Beitrag zuvor |
Re: Delphi mit Java komunizieren
Zitat:
Delphi Klassen und Java Klassen haben aus sicht des Programms nichts mit einander gemeinsam! Eine Delphi Klasse wird völlig anders initialisiert und auch völlig anders im Speicher gehalten. Den großen unterschied siehst du schon daran, dass du bei Java Reflections anwenden kannst, für Delphi ist nichts (komplett) gleichwertiges vorhanden. Das heißt, dass die JVM also schon andere Informationen als ein RTTI haben muss. Würdest du jetzt ein Delphi-Objekt als Instanz einer Java-Klasse weiter reichen, dann verstehe ich, dass es kracht! Die JVM würde nun eine Referenz auf ein Objekt bekommen. Um die korrekte Übergabe des Speichers kümmert sich dann schon die Kapselung (JNI), aber der Versuch diese Referenz als Java Klasse zu verwenden muss fehlschlagen. Die Frage wäre also, wie hast du Form1.MiniSC.MBMap.obj erzeugt? Gruß Der Unwissende |
Re: Delphi mit Java komunizieren
hey, also Form1.MiniSC.MBMap.Obj ist hierbei ein JObjekt und wurde folgender maßen erzeugt :
Delphi-Quellcode:
soweit ich das gesehen habe ist es auch kein fehler aufgetreten .. MBMap wurde erzeug.
cls := jvm.JniEnv.FindClass('com/gdv/mapbuilder/MBMap');
if cls = nil then ShowMessage('Klasse "MBMap" nicht gefunden'); ConstructorMid := jvm.JniEnv.GetMethodID(cls, '<init>', '()V'); if ConstructorMid = nil then ShowMessage('Konstruktor nicht gefunden'); Obj := jvm.JniEnv.NewObject(cls, ConstructorMid, []); if Obj = nil then ShowMessage('Fehler beim erzeugen der Instanz'); Die MBMenuBar (abstammung von der MenuBar in Java) wird nun erzeugt .. dafür muss ich diese MBMap übergeben
Delphi-Quellcode:
und bei der übergabe oder was auch immer kommt der fehler .. es könnte aber auch sein, dass der fehler nicht an der MBMap liegt , sondern ich einfach keine MenuBar ereugen kann, weil mir ein komponent fehlt .. oder weil ich keine Grafiken erzeugen kann ?! MBMenuBar = Menüleiste
cls := jvm.JniEnv.FindClass('com/gdv/mapbuilder/gui/MBMenuBar');
if cls = nil then ShowMessage('Klasse "MBMenuBar" nicht gefunden'); ConstructorMid := jvm.JniEnv.GetMethodID(cls, '<init>', '(Lcom/gdv/mapbuilder/MBMap;)V'); if ConstructorMid = nil then ShowMessage('Konstruktor nicht gefunden'); Obj := jvm.JniEnv.NewObject(cls, ConstructorMid, [Form1.MiniSC.MBMap.Obj]); if Obj = nil then ShowMessage('Fehler beim erzeugen der Instanz'); |
Re: Delphi mit Java komunizieren
Hi,
Zitat:
An sich sieht es sonst richtig aus. Hab es auch noch mal mit zwei sehr einfachen Klassen getestet (aber das einfach ist egal, entweder es klappt oder eben nicht), keine Probleme. Man kann ein JObject übergeben und es wird (wenn es vom richtigen Typ ist) auch gecastet und funktioniert. Deshalb solltest du wirklich nochmal schauen, was du für einen Parameter du wirklich übergibst. Am besten initialisierst du einfach mal Form1.MiniSC.MBMap.Obj mit nil und schaust halt vor dem Aufruf des Konstruktors der MBMenuBar nach, ob die Variable wirklich <> nil ist. Gruß Der Unwissende |
Re: Delphi mit Java komunizieren
Ich hab noch ein Problem.
Ich habe eine Klasse VectorDataSource. und eine Weiter Klasse namens ShapeVectorDataSource. Diese Klasse erbt von der VectorDataSource. Jetzt habe ich ein Object der KLasse ShapeVectorDataSource erzeugt. und eine andere Constructor verlangt aber kein ShapeVectorDataSource sonder die Klasse VectorDataSource (sozusagen die unterklasse) . meine frage ist nunr .. kann ich dieeinfach übergeben ?! also bei mir kommt ein fehler .. kann ich mit der jni das Objekt der Klasse ShapeVectorDataSOurce zum VectorDataSource casten (im Java geht das ja) |
Re: Delphi mit Java komunizieren
Hi,
das sollte eigentlich kein Problem darstellen. An sich weiß Delphi und JNI ja nichts von der Klasse die du verwendest. Es handelt sich um ganz normale Java Klassen, auf die du nur in der nicht JVM-Welt eine Referenz (JObject) hälst. Die Instanz hinter der Referenz kann aber ausserhalb der JVM nie verwendet werden. Deshalb kannst du über JNI auch das machen, was Java unterstützt. Eine Unterklasse ist ja nur eine Spezialisierung. Du garantierst damit, dass jede Unterklasse den Umfang der Elternklasse besitzt, diesen jedoch auch erweitern kann (und natürlich einzelne Methoden unabhängig implementieren). Nur damit ich es richtig verstehe, du hast etwas wie:
Code:
Das heißt, du erbst von VectorDataSource und irgendein konstruktor hätte gerne eine Instanz von VectorDataSource. Dem kannst du ohne Probleme (auch per JNI) eine Instanz von ShapeVectorDataSource übergeben. Nur das umgekehrte würde nie klappen, da ein ShapeVectorDataSource ja neue Dinge einführen kann.
public class ShapeVectorDataSource extends VectorDataSource { ...
|
Re: Delphi mit Java komunizieren
hm .. komisch ..
also bei mir sagt der am schluss das das objekt das is erzeugen wollte leer ist. Woran kann es dann liegen ? Wenn nich daran ?! |
Re: Delphi mit Java komunizieren
Was?
Wer sagt dir denn was genau? Ich kenne deinen Code nicht, ich kann es dir mit so wenig Info's nicht sagen. Kann im Prinzip alles sein. Wenn JNI/Delphi nicht sagt, dass die Erzeugung fehlgeschlagen ist, dann hast du ein Objekt erzeugt und die Referenz kannst du in einem JObject speichern. Solange du diese Referenz nicht anfässt, wird die JVM wissen, dass die GC das zugehörige Objekt nicht freigeben darf. Würdest du hier etwas falsches Erzeugt haben, so bekommst du einen Error, der dir einen ungültigen Cast anzeigen würde. |
Re: Delphi mit Java komunizieren
so hier nochmal mit Quelltext :
als erstes wird ein Objekt der JavaKlasse ShapeVectorDatasource erzeugt .. dann will ich einen VectorLayer erzeugen. Der Konstuktor (wie man ja auch sieht) brauch aber nicht einen ShapeVectorblablub, sonder einen VectorDataSource (eben die unterklasse) .. und da kommt dass das objekt von der Klasse VectorLayer leer ist .. warum auch immer ..
Delphi-Quellcode:
es kommt keine Meldung außer 'Fehler beim erzeugen der Instanz: VectorLayer'
constructor JDShapeFileVector.create(Path :PAnsiChar) ;
Var JPath : JString; begin cls := jvm.JniEnv.FindClass('com/gdv/mapbuilder/datasources/shapefile/ShapefileVectorDataSource'); if cls = nil then begin ShowMessage('Klasse "ShapefileVectorDataSource" nicht gefunden'); exit; end; ConstructorMid := jvm.JniEnv.GetMethodID(cls, '<init>', '(Ljava/lang/String;)V') ; if constructorMid = nil then begin ShowMessage('Konstruktor nicht gefunden') ; exit ; end; JPath := Jvm.JniEnv.StringToJString(Path) ; Obj := jvm.JniEnv.NewObject(cls, ConstructorMid,[JPath]); if Obj = nil then ShowMessage('Fehler beim erzeugen der Instanz'); VectorLayer := JDVEctorLayer.create(Obj); end; {*create ShapeVector} destructor JDShapeFileVector.destroy ; begin Vectorlayer.destroy ; end; constructor JDVectorLayer.create(ShapeFile : JObject); begin cls := jvm.JniEnv.FindClass('com/gdv/mapbuilder/layer/MBVectorLayer'); if cls = nil then begin ShowMessage('Klasse "MBVectorLayer" nicht gefunden'); exit; end; ConstructorMid := jvm.JniEnv.GetMethodID(cls, '<init>', '(Lcom/gdv/mapbuilder/datasources/VectorDataSource;)V'); if constructorMid = nil then begin ShowMessage('Konstruktor nicht gefunden') ; exit ; end; Obj := jvm.JniEnv.NewObject(cls, ConstructorMid,[ShapeFile]); //ShapeFile ist hier eben vom Objekt ShapefileVectorbla und nicht von der verlangten unterklasse VectorDataSource if Obj = nil then ShowMessage('Fehler beim erzeugen der Instanz: VectorLayer'); end; kann es jetzt sein dass das Obj der Klasse Vector leyer trotzdem erzeugt wurde ?! |
Re: Delphi mit Java komunizieren
Zitat:
Das Problem ist, dass mir hier nicht ganz klar ist, warum der Code da überhaupt funktioniert. Du verwendest hier Konstruktoren, die nie inherited create aufrufen. Wenn das also dein Delphi-Code ist, solltest du schon an der Stelle ein Problem haben. Ansonsten ist mir auch nicht klar, wo die Variable obj herkommt. Die verwendest du hier relativ global, obwohl zwei völlig verschiedene Instanzen hier abgelegt werden sollen. Ob sie nicht zwischen den zwei Schritten noch an einer anderen Stelle verändert wird, kann ich so nicht sehen / sagen. Besser ist es, wenn du hier mit einer eigenen Variable arbeitest. An sich verwirrt mich auch etwas der Aufbau deines Programms. Dein JDVectorlayer benötigt ein JDShapeFileVector, soweit so klar. Jetzt würde ich sagen, dass JDVectorLayer also von der Existenz eines JDShapeFileVector wissen muss, nicht umgekehrt. Folglich sollte also JDShapeFileVector sich eine Instanz von JDShapeFileVector besorgen und diese verwenden... Also es wirkt auf micht wirklich etwas unglücklich modelliert. Worin jetzt der eigentliche Fehelr besteht kann ich so aber auch nicht sagen (sehe ihn nicht). Wie gesagt, globale Instanz von obj wäre ganz schlecht. |
Re: Delphi mit Java komunizieren
ich frag meinen arbeitgebeer mal wie weit ich das projekt hochladen darf .. aber eins kan ich sagen .. obj ist nicht global !
|
Re: Delphi mit Java komunizieren
Liste der Anhänge anzeigen (Anzahl: 1)
oder würde dir mal der komplette quelltext (ohne javadaten) erstmal reichen ?
|
Re: Delphi mit Java komunizieren
Versuch es mal mit dem Aufruf der geerbten Methode im Konstruktor:
Delphi-Quellcode:
Das gehört immer an erster Stelle in den Konstruktor. Damit wird überhaupt erst der Speicher reserviert, der für die Struktur benötigt wird. Vielleicht findest du dort schon deinen Fehler.
begin
inherited create; ... end; [Add] Ansonsten solltest du deine Klassen an sich noch etwas überarbeiten. Es ist immer schöner, wenn man die Schutzklassen die es gibt auch verwendet. Variablen solltest du immer als private deklarieren und den Zugriff über Properites nach aussen kapseln. Methoden sollten dann protected sein (wenn sie nur in der Klasse sichtbar sein sollen), sonst public. Der Zugriff auf Methoden (und imho auch Variablen) sollte qualifiziert werden (self. vorschreiben), damit ist immer klar, dass du eine Instanzvariable meist. [/Add] |
Re: Delphi mit Java komunizieren
gut also sachen wie obj nicht public lassen usw.
aber was meinst du mit inherited .. ich mein meine klassen in Delphi sind ja eigentlich nicht voneinander vererbt .. nur die in der JavaKlasse .. meine muss ja auch nich vererbt sein...... hm .. also kann ich einfach das ShapeFile der Klasse ShapeFileVectorData übergeben obwohl er nur die unterklasse FilVectordartablub haben will ?! .. da müsste es keinen komplikationen geben ?! .. hab ich denn mit JNI alles richtig programmiert ? |
Re: Delphi mit Java komunizieren
Zitat:
Statt
Delphi-Quellcode:
kannst du auch schreiben
TXYZ = class
... end;
Delphi-Quellcode:
Beide Blöcke haben die gleiche Aussage! Führst du einen eigenen Konstruktor ein, so musst du immer als erstes dafür sorgen, dass Speicher alloziert wird, die Adresse bekannt gegeben, etc. Irgendwoher muss Delphi ja dann wissen, wo jetzt dein Objekt liegt, welchen Typ es hat usw. Davon übernimmt der Vererbte Konstruktor von TObject schon einen guten Teil. Deswegen beginnt jeder Konstruktor immer mit der Zeile:
TXYZ = class(TObject)
... end; [delphi] constructor TXYZ.create; begin inherited create; end; [delphi] Also so sieht es bei direkten Erben von TObjekt aus, bei einem TControl würdest du natürlich dem inherited create noch den Owner mitgeben, aber der würde damit nur die geerbte Methode von TComponent aufrufen, dass geht dann wieder runter bis zum Parameterlosen create Aufruf eines TObject. Ähnlich sieht es dann beim Destruktor auf. Der muss ja letztlich sauber machen. Jetzt kannst du dich selbst drum kümmern, wie Delphi seine Klassen verwaltet (was keineswegs sinnvoll ist) oder du greifst hier dann einfach auf den geerbten Destruktor zurück. Überschreibst du also einen Destruktor, so muss die letzte Zeile inherited destroy heißen (die gibt einfach den Speicher des Objekts und aller Variablen, etc. frei). |
Re: Delphi mit Java komunizieren
ok .. es klappt alles .. ich habe eine methode vergessen aufzurufen .. daher kamen haltz folgefehler auf .. hatte aber was mit dem Java Programm zu tun.. werde aber trotzdem auch nochmal den delphiquellcode überarbeiten
|
Re: Delphi mit Java komunizieren
Hallo miteinander
Habe wieder mal ein Problem... Für den Aufruf meines JavaProgramm muss ich zuerst eine Klasse instanzieren (EnvironmentProvider) --> Dies geht ohen weitere Probleme. Danach muss eine weitere Klasse instanziert werden (Mitarbeiter). Der Constructor sieht vor, dass als Parameter den EnvironmentProvider und ein Pfad zu einem XML übergeben werden muss. Die Übergabe des EnvironmentProvider ist kein Problem, jedoch wird das XML-File nicht gefunden. Der ganze JavaCode ist in einem Jar verpackt. Darunter besteht die Struktur /config/config.xml Beim Instanzieren der Klasse Mitarbeiter habe ich versucht den Parameter in allen verschieden Varianten versucht einzugeben, jedoch ohne Erfolg. Hat jemand ne Ahnung auf was ich achten soll? Eine Grundlegende Frage dazu: Falls ich mehrere Klassen instanzieren muss, muss ich immer auf die Reihenfolge der Aufrufe aufpassen --> Zuerst muss ich die Klassen suchen (FindClass(...)), danach alle Methoden (GetMethodID(...)) und erst dann die Klassen instanzieren. Falls ich es nicht so mache und zuerst eine Klasse instanzieren, dann findet er mir nur noch die Methoden der zuerst Instanzierten Klasse.. Mache ich was falsch, oder ist das vom JNI so vorgegeben? Danke, hoffe es kann mir jemand weiterhelfen Greez Bucchi |
Alle Zeitangaben in WEZ +1. Es ist jetzt 10:45 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz