![]() |
JNI gesucht
Ich muss mit einem C-Programm eine Java Methode aufrufen. das geht mit JNI (Java Native Interface). Doch wo bekomme ich die jni.h Datei und alles, was ich sonst noch so dazu brauche? Ich habe schon dne ganzen Morgen gegoogelt, aber irgendwie keinen Download gefunden. :gruebel:
|
Re: JNI gesucht
You've got mail.
|
Re: JNI gesucht
Hi,
ich kann dir hier nur die Seite ![]() Gruß Der Unwissende |
Re: JNI gesucht
Ich habe jetzt folgendes Java Programm:
Code:
Dazu das C-Programm:
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; } }
Code:
Nur leider erkennt er die Datentypen JavaVMOption und JavaVMInitArgs nicht. Sie sind auch nicht in der jni.h datei zu finden. Den Code hab eich zwei PDFs. Lider wird da nicht gesagt, welche jni.h Datei verwendet wird.
#include <stdio.h>
#include "jni.h" int main() { JavaVMOption options[1]; JNIEnv *env; JavaVM *jvm; JDK1_1InitArgs vm_args; long status; jclass cls; jmethodID mid; jint square; jboolean not; options[0].optionString="-Djava.class.path=."; memset(&vm_args, 0, sizeof(vm_args)); vm_args.version = JNI_VERSION_1_2; vm_args.nOptions = 1; vm_args.options = options; status = JNI_CreateJavaVM(&jvm,(void**)&env,&vm_args); if (status != JNI_ERR) { cls = (*env)->FindClass(env, "HelloWorld"); if (cls != 0) {mid = (*env)->GetStaticMethodID(env,cls,"Test","(I)I"); if (mid != 0) {square = (*env)->CallStaticIntMethod(env,cls,mid,5); printf("Result of int Method:%d\n", square); (*jvm)->DestroyJavaVM(jvm); return 0; } else return -1; } #include <stdio.h> #include "jni.h" int main() { JavaVMOption options[1]; JNIEnv *env; JavaVM *jvm; JDK1_1InitArgs vm_args; long status; jclass cls; jmethodID mid; jint square; jboolean not; options[0].optionString="-Djava.class.path=."; memset(&vm_args, 0, sizeof(vm_args)); vm_args.version = JNI_VERSION_1_2; vm_args.nOptions = 1; vm_args.options = options; status = JNI_CreateJavaVM(&jvm,(void**)&env,&vm_args); if (status != JNI_ERR) { cls = (*env)->FindClass(env, "HelloWorld"); if (cls != 0) {mid = (*env)->GetStaticMethodID(env,cls,"Test","(I)I"); if (mid != 0) {square = (*env)->CallStaticIntMethod(env,cls,mid,5); printf("Result of int Method:%d\n", square); (*jvm)->DestroyJavaVM(jvm); return 0; } else return -1; } |
Re: JNI gesucht
Die jni.h findest du im JDK im include Verzeichnis. Die enthält (zumindest im JDK 1.5) auf jedenfall auch die Datentypen.
Gruß Der Unwissende |
Re: JNI gesucht
Ist das richtig, dass das JDG ca. 123 MB groß ist? dann dauert das noch eine Weile, bis ich das habe. :?
|
Re: JNI gesucht
JDG? Also das JDK ist im Download so in der Größe, auf der Platte gut 250 MByte, schon das JRE ist um die 130 MByte groß.
Ohne schnelle Leitung macht da Java auch gar keinen Spaß! Gruß Der Unwissende |
Re: JNI gesucht
Ja, JDK meine ich: java_ee_sdk-5-windows.exe
|
Re: JNI gesucht
Hm,
brauchst du wirklich die EE (Enterprise Edition?). Also Java unterscheidet hier die MicroEdition (für den Embedded Bereich gedacht, abgspeckter Funktionsumfang), die J2SE (Standard Edition), wird in der Regel als JDK bezeichnet und die J2EE (Enterprise Edition). Letztere enthält eine Menge an Enterprise Logik. Da kommen dann EnterpriseBeans zum Einsatz. Diese laufen in einer speziellen Umgebung (in einem Container). Die ermöglicht halt Skalierungen und Sicherheitsfeatures und nimmt dir komplett die Logik der Nebenläufigkeit ab (und und und). Dazu musst du die aber auch in einer Implementierung eines EE-Servers laufen lassen (Stichwort JBoss u.A.). Für die sollte eigentlich die J2SE reichen (wenn du nur Java + JNI verwenden möchtest). |
Re: JNI gesucht
Habe ich auch gerade gemerkt. Ich lade mir jetzt die SE Version runter. Werde ja dafür bezahlt, dass ich dem Download zu gucke. ;)
|
Re: JNI gesucht
|
Re: JNI gesucht
Das Problem kenne ich auch noch, unser Rückfallnetz besteht aus zwei ISDN Kanälen, entsprechend perfomant geht es dann voran (es müssen sich halt nur genug Leute 128 KBit teilen). Da war es dann auch immer schneller Dinge woanders runterzuladen und dann am nächsten Tag weiter zu machen. Aber im Moment wird mal keine Leitung durch Bagger zerstört und das Netz ist schnell (>>> 128 KBit).
Andererseits würde ich mich auch gern mal dafür bezahlen lassen ;-) [edit] @kalmi01 Ohne für Luckie sprechen zu wollen sprach er davon, dass er C verwenden möchte. Da man in letzter Zeit häufiger Luckie und C im selben Thread trifft dürfte er auch wirklich was in C machen wollen [/edit] |
Re: JNI gesucht
So, soweit scheint es zu funktionieren. Bis auf eine Fehlermeldung vom Linker: "undefined reference to `JNI_JNI_CreateJavaVM'". Muss ich da noch irgendwie eine lib-Datei linken oder so?
|
Re: JNI gesucht
Nein, aber du musst das include Verzeichnis komplett in deine C Umgebung (per Include Schalter) einbinden. Eigentlich sollte dann alles klappen. Andererseits heißt das ja in der Regel nicht viel.
[edit] Achso, im Include Verzeichnis gibt es noch ein weiteres Systemspezifisches Verzeichnis, dass du auch in den Include pfad packen musst. [/edit] |
Re: JNI gesucht
Hm:
Code:
Ändert leide rnichts an der Fehlermeldung. Der Compiler gibt allerdings schon eine warnung auis:
-I"C:\Programme\Java\jdk1.5.0_07\include\*" -I"C:\Programme\Java\jdk1.5.0_07\include\win32\*" -O0 -g3 -Wall -c -fmessage-length=0
Zitat:
|
Re: JNI gesucht
Ok,
ehrlich gesagt wundert es mich, dass der von dir gepostete C Code so überhaupt laufen sollte. Ich hab mal die Datei etwas abgeändert (bei mir fehlten 2 schließende Blöcke und die vmArgs müssen vom Typ JvmInitArgs sein).
Code:
Das ganze hab ich dann durch den Borland C Compiler gejagt :
#include <stdio.h>
#include "jni.h" int main() { JavaVMOption options[1]; JNIEnv *env; JavaVM *jvm; JavaVMInitArgs vm_args; long status; jclass cls; jmethodID mid; jint square; jboolean not; options[0].optionString="-Djava.class.path=."; memset(&vm_args, 0, sizeof(vm_args)); vm_args.version = JNI_VERSION_1_2; vm_args.nOptions = 1; vm_args.options = options; status = JNI_CreateJavaVM(&jvm,(void**)&env,&vm_args); if (status != JNI_ERR) { cls = (*env)->FindClass(env, "HelloWorld"); if (cls != 0) {mid = (*env)->GetStaticMethodID(env,cls,"Test","(I)I");} if (mid != 0) {square = (*env)->CallStaticIntMethod(env,cls,mid,5); } printf("Result of int Method:%d\n", square); (*jvm)->DestroyJavaVM(jvm); return 0; } else return -1; }
Code:
Und das compiliert ohne Probleme. Gelinkt habe ich den Code jetzt zwar nicht, aber ich denke mal die Probleme hattest du auch schon beim Compilieren?
bcc32 -I"C:\Programme\Java\jdk1.5.0_08\include" -I"C:\Programme\Java\jdk1.5.0_08\include\win32" "Blubb.c"
|
Re: JNI gesucht
Wenn ich deinen Code mit MinGW kompiliere, bekomme ich folgende Fehlermeldungen:
Code:
**** Full rebuild of configuration Debug for project Direct Soap Bridge Exe Demo **** mingw32-make clean all rm -rf ./ExeDemo.o ./ExeDemo.d DirectSoapBridgeExeDemo.exe process_begin: CreateProcess((null), rm -rf ./ExeDemo.o ./ExeDemo.d DirectSoapBridgeExeDemo.exe, ...) failed. make (e=2): Das System kann die angegebene Datei nicht finden. mingw32-make: [clean] Error 2 (ignored) ' ' 'Building file: ../ExeDemo.c' 'Invoking: GCC C Compiler' mingw32-gcc -I"C:\Programme\Java\jdk1.5.0_07\include" -I"C:\Programme\Java\jdk1.5.0_07\include\win32" -O0 -g3 -Wall -c -fmessage-length=0 -oExeDemo.o ../ExeDemo.c ../ExeDemo.c: In function `main': ../ExeDemo.c:16: warning: implicit declaration of function `memset' ../ExeDemo.c:29: warning: int format, jint arg (arg 2) ../ExeDemo.c:36:2: warning: no newline at end of file 'Finished building: ../ExeDemo.c' ' ' 'Building target: DirectSoapBridgeExeDemo.exe' 'Invoking: GCC C Linker' mingw32-gcc -oDirectSoapBridgeExeDemo.exe ./ExeDemo.o ./ExeDemo.o(.text+0x75): In function `main': D:/Projekte Datawerk/PVS/SVN/branches/Eclipse_mp/Direct_SOAP_Bridge_DLL/JNI/C-Programm/Debug/../ExeDemo.c:20: undefined reference to `_imp__JNI_CreateJavaVM@12' collect2: ld returned 1 exit status mingw32-make: *** [DirectSoapBridgeExeDemo.exe] Error 1 Build complete for project Direct Soap Bridge Exe Demo |
Re: JNI gesucht
Hm, sorry, mit minGW kenne ich mich jetzt nicht wirklich aus. Also bei Cygwin konnte man nie direkt auf ein Verzeichnis zugreifen. Da musste man den Umweg über das virtuelle Verzeichnis cyIrgendwas (nicht mehr im Kopf) gehen. Aber das sollte hier nicht das Problem sein. Vielmehr stellt dir minGW doch eine andere (unix) Umgebung zur Verfügung. Da weiß ich nicht in wie weit die Bibliotheken aus ...\include\win32 verwendet werden können. Hier sind immerhin plattformabhängige Aufrufe und Deklarationen drin. Daran kann es also (mit dem Compiler) scheitern. Hast du es einfach nur mit einem "normalen" C Compiler versucht? (mache ja schließlich auch gerne Fehler!)
|
Re: JNI gesucht
Das ist die Windows Version des Compilers. Ich habe damit schon erfolgreich normale Exe-FDateien, wie auch DLLs kompilieren können. Und was ist ein "normaler" C-Compiler?
|
Re: JNI gesucht
Ok, hab wohl nicht mitbekommen, dass MinGW einfach eine echt Portierung ist. Dachte ist nur minimaler als Cygwin aber wieder mit DLL die beiliegen muss. Gut, dann nehme ich auch das zurück.
Das Problem dass du hast, habe ich beim Linken auch (ich hätte nicht nur compilieren sollen). Es liegt daran, dass das Erzeungen der JVM nicht gelinkt werden kann. Statisch ist dies auch nicht möglich, da du auf jedem System die jvm an einem anderen Ort finden wirst. Du musst die Methode JNI_CreateJavaVM gegen die jvm.dll linken. Hier kann ich dir leider nichts genaueres sagen (mit meinem C ist's nicht all zu weit her). Du findest aber eine Delphi Implementierung, wie man diese Dll lädt und eine neue Instanz erzeugt, die dir weiterhelfen dürfte. Ich möchte hier nur auf den Download ![]() Der Ort, andem du die jvm.dll findest ist in der Registry unter HKLM\Software\JavaSoft\Java Runtime Environment\1.x als Runtimelib zu finden (bei einer Standard Sun JVM). Welches JRE du hier verwendest bleibt natürlich dir überlassen (soweit mehr als eins installiert ist). Ja, dann hoffe ich du kommst damit auch weiter, Gruß Der Unwissende |
Re: JNI gesucht
Danke, ich werde es morgen an der Arbeit ausprobieren.
|
Re: JNI gesucht
Zitat:
Zitat:
|
Re: JNI gesucht
Liste der Anhänge anzeigen (Anzahl: 1)
Hi,
ich war mal so frei, mich ein wenig an C zu probieren. Bitte keine Kommentare dazu, dass man das alles besser und schöner hätte machen können, sehe ich genauso, aber wie gesagt C und ich sind nicht die besten Freunde. Da ist mir schon C++ sympatischer (kann man wenigstens Objekte verwenden). Na ja, jedenfalls klappt das so bei mir ohne Probleme. Hier wird zur Laufzeit der Pfad zur DLL ermittelt und hier dynamisch die Methode geladen. Da du selbst viel mit der Windows-API gearbeitet hast und auch C kannst, sollte alles für dich verständlich sein. Insbesondere solltest du schauen, ob ich überhaupt sauber den Speicher freigebe, den ich verwende. Ups, da fällt mir gerade ein, ich verwende an einer Stelle ein calloc, da sorge ich wirklich nicht für die Freigabe, peinlich. Na ja, wäre schon mal die erste Stelle, die du korrigieren kannst :wink: Gruß Der Unwissende |
Re: JNI gesucht
Besten Dank. Ich habe es in der Zwischenzeit mit Delphi probiert. Mal sehen, wenn der Chef einsichtig ist, kan nich dabei bleiben. ;)
|
Re: JNI gesucht
Zitat:
Jedenfalls ist das hier eh der Punkt, ab dem ich dir von C abraten würde, env und jvm enthalten Zeiger auf Objekte, da kannst du dann deinem Chef auch sagen, dass du eh nicht um eine OO Sprache rum kommst (nicht wirklich schön jedenfalls) und dazu fällt mir nur ein: Zitat:
|
Re: JNI gesucht
Na ja, was das mal werden soll, kannst du hier nachlesen:
![]() Ich muss das dann noch irgendwie an die xfire Schnittstelle des Webserviceses dranklemmen. Und dann soll die DLL noch universell einsetzbar sein, also nicht auf einen Webservice speziell zugeschnitten ein. Das wird noch richtig lustig. :wall: |
Re: JNI gesucht
Ich habe mir mal deine Test-C-Dateien angeguckt. Wie nutze ich diese jetzt?
|
Re: JNI gesucht
Wie meinst du das denn?
Also wenn du bei dir das Programm übersetzen und linken kannst, bekommst du eine .exe die beim Start einfach eine JVM und ein JniEnvironment erzeugt. Das ist auch so ziemlich alles, was du brauchst. Die Funktionen (die du in der Doku und in der JNI.pas) findest, kannst du damit "wie gewohnt" aufrufen. Du hast ja grob soetwas:
Code:
Dabei ist dann clazz natürlich schon gültig und über findClass gesucht worden, dann ist dir hier nun alles bekannt und du bekommst eine gültige FielId. Mittels dieser kannst du dann die Fuktion get<T>Field aufrufen, wobei T dann der Datentyp ist, also z.B. getIntField.
jfieldID GetFieldID(JNIEnv *env, jclass clazz, const char *name, const char *sig);
Ja, das war's dann. |
Re: JNI gesucht
Ich habe jetzt deine Funktionen genommen und bei mir in das Programm eingebaut, sprich reinkopiert. Den entsprechenden Aufruf habe ich angepasst:
Code:
Leider bekomme ich dieses Windows Fenster zu sehen: "foobar.exe hat ein Problem festgestellt und muss beendet werden." Ich kann aber im Moment noch nicht sagen, woran es liegt, da ich noch nicht rausgefunden habe, wie man mit Eclipse debuggt. Bzw. wenn ich es versuche, bekomme ich von Eclipse die Meldung: "Launching failed", mit de rich im Moment nochnichts anfangen kann.
status = createJavaVm(jvm, env, &path[0]);
|
Re: JNI gesucht
Was genau hast du denn angepasst?
Also lässt du immer noch den Pfad über die Registry ermitteln? Ist Path dann gültig? (also auch der Wert, einfach mal ausgeben). Ja, könnte jetzt nur gut weiterraten, aber das hilft ja dann auch nicht viel. Läuft denn das Programm das ich dir geschickt hatte überhaupt? Wenn ja, dann lager doch den Teil, den du brauchst aus (würde ich dir eh empfehlen). Leg dann eine Methode an, die die JVM und das JniEnv erzeugt (und eine die es auch wieder frei gibt). Ja, mit C++ oder Delphi hast du da immer noch klare Vorteile (was hat dein Chef an denen auszusetzen?!). Jedenfalls kann ein solcher Fehler an mehreren Dingen liegen (etwas fuzzy und vielleicht nicht vollständig oder richtig):
Wären jetzt so die ersten Punkte die mir einfallen. Musst du mal schauen. |
Re: JNI gesucht
Ich versuche das ganze gerade zu debuggen.
|
Re: JNI gesucht
OK, ich bin etwas weiter gekommen. Und zwar findet er diesen Pfad "SOFTWARE\\JavaSoft\\Java Runtime Environment" wohl nicht, obwohl er genauso in der Registry steht. Das verstehe ich irgendwie nicht. Jedenfalls bekomme ich an dieser Stelle
Code:
in der Funktion int getJvmDllPath(char* path) die Fehlermeldung:
res = RegOpenKeyEx(HKEY_LOCAL_MACHINE, REG_PATH_TO_JRE, 0, KEY_READ, &key);
printf("RegOpenKeyEx(HKEY_LOCAL_MACHINE, REG_PATH_TO_JRE, 0, KEY_READ, &key)\n"); if (res != ERROR_SUCCESS) { LPTSTR pszBuf; pszBuf = SysErrorMessage(GetLastError(), NULL, 0); _tprintf(_T("%s\n"), pszBuf); LocalFree(pszBuf); return 0; } Zitat:
|
Re: JNI gesucht
Hm, an den Leserechten solltest du ja nicht scheitern (wenn du den Schlüssel mittels Regedit siehst).
Ja, da geht's dann wieder los, den Fehler seh ich gerade nicht. Endet der Pfad mit einer \0? Sonst kann hier natürlich wieder das letzte Zeichen fehlen. Ansonsten solltest du erstmal schauen, ob du denn einen anderen Schlüssel findest und öffnen kannst (z.B. HKEY_LOCAL_MACHINE\Software). Was die Fehlermeldung angeht, so kenne ich jetzt die Funktion SysErrorMessage nicht, aber kommt denn das gleiche auch bei FormatMessage raus?
Code:
Wie gesagt, ich weiß einfach nicht, wie SysErrorMessage aufgebaut ist, kann natürlich auch das gleiche machen, nur wundert mich die Fehlermeldung etwas. An sich solltest du vielleicht auch das GetLastError direkt rausziehen, damit hier der letzte Fehler nicht durch den Aufruf von z.B. FormatMessage überschrieben wird (gut, passiert wohl eher nicht, aber trotzdem).
if (res != ERROR_SUCCESS) {
char[MAX_PATH] buf; FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, 0, GetLastError(), 0, &buf[0], MAX_PATH, 0); _tprintf(_T("%s\n"), buf); return 0; } Ja, direkt einen Fehler seh ich natürlich auch nicht. Funktioniert denn das Beispielprogramm an sich? Das hier sieht ja nach einer eigenen Funktion aus. Gruß Der Unwissende |
Re: JNI gesucht
So, es hat etwas gedauert, da ich erst mal feststellen musste das MinGW keinen Debugger mitbringt. :wall:
Also dein Testprogramm liefert auch keinen gültigen Pfad zurück. Und es kommt der gleiche fehler wie bei mir: Zitat:
SysErrorMessage ist nur ein Wrapper im ![]() |
Re: JNI gesucht
Liste der Anhänge anzeigen (Anzahl: 1)
Zitat:
Also ich weiß nicht genau woher der Fehler kommen sollte. Da ich gerade kein MinGW zur Hand habe, hier mal das Kompilat (und ein leicht geänderter QC). Jetzt sollte der Fehlercode mit einer Meldung ausgegeben werden. Bei mir funktioniert alles wie es soll, gültiger Pfad und als Rückgabewert 0 (auf zwei Rechnern, beide mit XP SP 2). |
Re: JNI gesucht
Werde ich norgen mal an der Arbeit ausprobiern. Danke für deine Mühe.
|
Re: JNI gesucht
Also bei deiner Exe funktioniert es.
Kompiliere ich deinen Quellcode kommt das: Zitat:
Das verstehe ich einfach nicht. Mit Delphi geht es ja. Und warum geht dein Programm bei dir und mir und wenn ich deinen Code kompiliere geht es nicht mehr? Wie kannst du den Quellcode überhaupt kompilieren? Denn in der Funktion int getJvmDllPath(char* path) ist die Variable res nicht deklariert. Ich kann ihn erst kompilieren, wenn ich die Variable deklariere. Aber selbst dann kompiliert er nur mit Warnungen. Betrifft aber hauptsächlich die Ausgaben mit printf. |
Re: JNI gesucht
HI,
Zitat:
Zitat:
Jedenfalls hab ich mit dem diesen Code erzeugt. Ja, printf ist natürlich nicht das schönste, aber was gibt es denn so für Alternativen in C? Kenne mich da echt wenig aus :( Zitat:
Code:
wobei res also gleich in dieser Zeile deklariert wird als long. Deswegen sollte es auch eigentlich keine Probleme beim Compilieren geben. Aber wenn sich sogar der Quellcode beim Übertragen ändert ;-)
int getJvmDllPath(char* path) {
.... // öffnen des Schlüssels // HKEY_LocalMachine\\Software\\JavaSoft\\Java Runtime Enviroment\\ long res = RegOpenKeyEx(HKEY_LOCAL_MACHINE, REG_PATH_TO_JRE, 0, KEY_READ, &key); Ich weiß ehrlich gesagt nicht, warum es mit MinGW nicht laufen sollte. Wenn es Probleme beim Compilieren gäbe oder so, dann könnte ich das ja noch verstehen, aber wenn er die Datei linkt, dann sollte es eigentlich so laufen. Hast du denn wirklich mal andere Schlüssel zu öffnen versucht? Also wirklich nur eine C Programm, dass nicht mehr macht als einen beliebigen Schlüssel in der Registry zu öffnen? Gruß Der Unwissende |
Re: JNI gesucht
Das mit der Deklaration habe ich jetzt auch gesehen. Nur ein Programm, was den betreffenden Schlüssel öffnet, werde ich gleich mal machen.
|
Re: JNI gesucht
So neue Erkenntisse:
Dieser Code:
Code:
Mit VC kompiliert funktioniert. Der selbe Cod emit MinGW kompiliert funktioniert nicht und der Schlüssel kann nicht geöffnet werden. Ich schließe daraus, dass es sich um eine Einstellungssache bei MinGW handelt. Nur welche?
#include "stdafx.h"
#include <stdio.h> #include <tchar.h> #include <windows.h> #include "MpuTools.h" int OpenRegPath(TCHAR* Path) { HKEY key = NULL; _tprintf(Path); _tprintf(_T("\n")); long res = RegOpenKeyExW(HKEY_CURRENT_USER, Path, 0, KEY_READ, &key); return res; } int main () { DWORD res = OpenRegPath(_T("Software\\Intel")); if (res != ERROR_SUCCESS) { TCHAR szBuf[80]; _tprintf(_T("%s\n"), SysErrorMessage(GetLastError(), szBuf, countof(szBuf))); } else { _tprintf(_T("Schlüssel konnte erfolgreich geöffnet werden.")); } return 0; } |
Alle Zeitangaben in WEZ +1. Es ist jetzt 11:32 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