JNI Wrapper Klasse

tdc

Bekanntes Mitglied
Hi,
mit JNI stehe ich gerade vor dem Problem eine Wrapperklasse zu schreiben. Ich muss also eine C++-Klasse/Methode aufzurufen, ohne sie vorher modifiziert zu haben.
Normalerweise muss man den Methodennamen ja folgendermaßen anpassen: Java_packageName_className_methodName
wenn ich das mit einer Methode mache, müsste ich ja von dort aus unmodifizierte C++-Methoden problemlos aufrufen können. Ich bekomme allerdings einen Error. (java: symbol lookup error: ...)

In meinem Beispiel habe ich eine Klasse Hello.cpp und eine Klasse World.cpp. Wenn ich jetzt den Header einbinde und die Methode "void create ()" mit einem "create();" aufrufe, bekomme ich obige Fehlermeldung.

Wie ruft man die Methode also richtig auf?
 

Marco13

Top Contributor
Einfach irgendeinen Namen modifizieren wird nicht reichen. Hast du den üblichen Weg verfolgt:
- native Methode in Java Klasse schreiben
- javah ausführen zum Header-Generieren
- Implementieren der Methode aus dem Header
...
?
 

tdc

Bekanntes Mitglied
Ja, das ist schon klar und funktioniert auch bereits. Die Frage ist nur, wie ich es machen soll, wenn ich ein größeres C++-Programm habe, was ich nicht komplett verändern möchte. In einem Tutorial wurde kurz angesprochen, man könnte eine Wrapperklasse schreiben. Das Problem ist nur, dass, wenn ich versuche aus einer angepassten C++-Klasse heraus eine "normale" C++-Methode aufzurufen, eine Fehlermeldung ausgegeben wird.
 

tdc

Bekanntes Mitglied
Mit anpassen meine ich:
"Normales C++":
Code:
#include <iostream>
using namespace std;
 
int main()
{
	cout << "Hello World!" << endl;
}
"angepasst":
Code:
#include <jni.h>
#include <iostream>
using namespace std;

extern "C"
JNIEXPORT void JNICALL Java_jni_callnative(JNIEnv *env,
                                                  jobject obj)
{
   cout << "Hello World!" << endl;
   return;
}

Natürlich sind diese Anpassungen oft recht einfach, aber bei ein paar 100 Klassen könnte es nervig werden. :)
 
T

troll

Gast
einfaches beispiel

>.../jni/JNIClass.java
Java:
package jni;
public class JNIClass
{
	public native void callnative();
}

call > javah jni.JNIClass

>.../jni_JNIClass.h
Code:
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class jni_JNIClass */

#ifndef _Included_jni_JNIClass
#define _Included_jni_JNIClass
#ifdef __cplusplus
extern "C" {
#endif
/*
 * Class:     jni_JNIClass
 * Method:    callnative
 * Signature: ()V
 */
JNIEXPORT void JNICALL Java_jni_JNIClass_callnative
  (JNIEnv *, jobject);

#ifdef __cplusplus
}
#endif
#endif

im implementierenden C-code ist nun die "jni.h" sowie "jni_JNIClass.h" einzubinden ... sowie die funktion Java_jni_JNIClass_callnative zu implementieren ...

einfach in irgendeine C-datei die "jni.h" einzubinden und einen zur klasse passenden funktions-namen zu wählen wird so halt nicht funktionieren ...
wenn du also wrapper basteln willst dann bau erstmal so normal eine JNI-lib und arbeite diese dann in dein bestehendes C-projekt ein ...
 

Marco13

Top Contributor
Ja, die Strategie wäre da eher so wie troll angedeutet hat, und aus der (automatisch mit allm drum und dran generierten) Methode heraus die 'eigene' Methode aufzurufen ('main' in dem Beispiel)
 

tdc

Bekanntes Mitglied
einfach in irgendeine C-datei die "jni.h" einzubinden und einen zur klasse passenden funktions-namen zu wählen wird so halt nicht funktionieren ...

Ja, das ganze drumherum mit nen Header generieren, einzubinden, das zu kompilieren, etc. funktioniert ja bereits.

Ja, die Strategie wäre da eher so wie troll angedeutet hat, und aus der (automatisch mit allm drum und dran generierten) Methode heraus die 'eigene' Methode aufzurufen ('main' in dem Beispiel)

Ja, nur das aufrufen der Methode funktioniert bei mir noch nicht. Hier mal ein kleines Beispiel:
hello.cpp
Code:
#include "jniTest.h"
#include <iostream>
#include "world.h"
using namespace std;

extern "C"
JNIEXPORT void JNICALL Java_jniTest_callnative(JNIEnv *env,
                                                  jobject obj)
{
	cout << "Hello" << endl;
	create();
	return;
}

world.cpp
Code:
#include "world.h"
#include <iostream>

void create () {
	std::cout << "World!" << std::endl;
	return;
}

world.h
Code:
#ifndef world_H
#define world_H
void create();
#endif /* world_H */

Wenn ich in Hello.cpp den Aufruf "create();" weglasse, funktioniert alles. (Ausgabe: "Hello")
Wenn ich es aber so lasse, bekomme ich eine Fehlermeldung. (java: symbol lookup error:...)

jniTest.h ist übrigens der, aus der Java-Klasse generierte Header.
 
G

Gastredner

Gast
Ich bin jetzt nicht der C/C++-Experte, aber du solltest vielleicht mal versuchen, deine Funktionsdefinition von create in world.h als extern "C" zu definieren:
Code:
#ifndef world_H
#define world_H
#ifdef __cplusplus
extern "C" {
#endif
void create();
#ifdef __cplusplus
}
#endif
#endif /* world_H */
C++ verarbeitet Funktionsnamen anders als C (unter anderem um überladene Funktionen zu ermöglichen), weswegen C-Code C++-Funktionen, die nicht als extern "C" deklariert sind (und somit den gleichen Konventionen wie C-Funktionen unterworfen sind) nicht aufrufen kann.
 

tdc

Bekanntes Mitglied
Okay, jetzt ist zumindest die Fehlermeldung schöner. ;)
davor:
Code:
java: symbol lookup error: /home/.../JNITestpp2/libhello.so: undefined symbol: _Z6createv
jetzt:
Code:
java: symbol lookup error: /home/.../JNITestpp2/libhello.so: undefined symbol: create
Scheint aber nicht das einzige Problem an meinem Code zu sein...
 

Marco13

Top Contributor
Die Fehlermeldung ist die gleiche, einmal mit und einmal ohne Name mangling - Wikipedia, the free encyclopedia ;)

Scheint als würde da beim Linken irgendwas nicht klappen, aber dann sollte sich eigentlich schon der Linker beschweren. (Ich nehme auch an, dass du (spziell für diesen Test noch) keine anderen Libs einbindest). Bin auch nicht soo fit mit Linux Linking & Co (Verwöhnt von CMake und IDEs :oops: ). Mehr als Websuchen ( java - Loading JNI crashes with undefined symbols - Stack Overflow etc) kann ich da im Moment leider nicht anbieten.
 
G

Gastredner

Gast
Also, ich habe das jetzt mal versucht nachzubauen und bei mir funktioniert es.

jni_JniClass.h:
Code:
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class jni_JniClass */

#ifndef _Included_jni_JniClass
#define _Included_jni_JniClass

#ifdef __cplusplus
extern "C" {
#endif

/*
 * Class:     jni_JniClass
 * Method:    callnative
 * Signature: ()V
 */
JNIEXPORT void JNICALL Java_jni_JniClass_callnative
  (JNIEnv *, jobject);

#ifdef __cplusplus
}
#endif

#endif

jniImpl.cpp:
Code:
#include <iostream>
#include "jni_JniClass.h"
#include <jni.h>
#include "world.h"

JNIEXPORT void JNICALL Java_jni_JniClass_callnative(JNIEnv *, jobject) {
	std::cout << "In callnative()" << std::endl;
	create();
	return;
}

world.h:
Code:
#ifndef __WORLD_H
#define __WORLD_H

#ifdef __cplusplus
extern "C" {
#endif

void create();

#ifdef __cplusplus
}
#endif

#endif

world.cpp:
Code:
#include <iostream>
#include "world.h"

void create() {
	std::cout << "In create()" << std::endl;
	return;
}

JniClass.java:
Java:
package jni;
public class JniClass
{
	static {
		System.loadLibrary("jnitest");
	}
    public native void callnative();
}

Test.java:
Java:
import jni.JniClass;

public class Test {

	public static void main(String[] args) {
		JniClass test = new JniClass();
		test.callnative();
	}
}

Der Aufruf [c]C:\Users\ANON\Desktop>java -Djava.library.path=C:\Users\ANON\Desktop\jni\jnitest-build-desktop-Qt_4_8_1_for_Desktop_-_MSVC2010__Qt_SDK__Debug\release\ Test[/c] erzeugt dann auch die korrekte Ausgabe:
Code:
In callnative()
In create()
Fehlt dir vielleicht das [c]System.loadLibrary("your_lib");[/c]?
 

Marco13

Top Contributor
Ohne das loadLibrary würde er sich AFAIK schon über das 'callnative' beschweren. Die aktuelle Fehlermeldung deutet m.E. auf einen Fehler beim Linken hin. Poste vielleicht mal die Kommandozeilen, die du jetzt verwendet hast, dann kann tdc schauen, ob er da was anders hat...
 
G

Gastredner

Gast
Meinst du den Aufruf des C-Compilers? Habe ich nicht (mehr), habe den QtCreator zum Schreiben der C++-Anteile genommen und das Projekt mittlerweile wieder gelöscht. Der Aufruf von java steht ja im Post.
 

Marco13

Top Contributor
Ja, den meinte ich - da gibt's einige ziemlich trickreiche und wichtige flags (siehe auch der verlinkte Post).
[ot]
Das haben die Linuxer nun davon, weil sie sich durch Tippen ellenlanger Zeilen an der Konsole als uber-Geek fühlen wollen, während man als Klickibunti-Windows-DAU nur auf "Compile" klickt :D
[/ot]
Aber mal im ernst: @tdc Du hast das manuell an der Console compiliert? Vielleicht kann jemand erahnen (oder ggf. auch schlicht lokal bei sich ausprobieren) was da falsch sein könnte, wenn du die Compiler-Zeilen posten würdest...
 
T

troll

Gast
es gab hier docn vor ein paar wochen einen ähnlichen thread ... ich glaube es war der wo versucht wurde eine .net-lib mit java anzusprechen ...
dabei wurden einige compiler und linker optionen genannt die wohl für normale c-libs "lebenswichtig" sind ... vielleicht hilft die sufu den thread zu finden ...
wenn es nicht daran lag könnte es auch was damit zu tun haben das c und c++ gemis ht werden ... hier hilft allerdings das sun tut mit einem beispiel weiter
 

tdc

Bekanntes Mitglied
Danke für den Hinweis. Es lag wirklich an dem Compile-Befehl, so funktioniert es jetzt:
Code:
g++ -fPIC -shared -I/usr/local/java/include -I/usr/local/java/include/genunix hello.cpp world.cpp -o libhello.so
Muss ich jetzt jede *.cpp-Datei einzeln auflisten? Gibt es nicht eine bessere/schönere Lösung bei verdammt vielen Sourcefiles? (Okay, die Frage geht jetzt eher in Richtung C++ als Java...)
 

tdc

Bekanntes Mitglied
Danke für die Hilfe, ich habs jetzt endlich hinbekommen! :toll:
(die letzten paar Tage war nicht mehr JNI mein Problem, sondern das ganze C++-Zeug zu kompilieren, jetzt funktioniert es aber endlich :) )
 


Schreibe deine Antwort... und nutze den </> Button, wenn du Code posten möchtest...
Ähnliche Java Themen
  Titel Forum Antworten Datum
S AffineTransform Wrapper der im Uhrzeigersinn rotiert..? Allgemeine Java-Themen 2
D Datentypen Typbestimmung unbekannter Wrapper-Klassen Allgemeine Java-Themen 5
E wie call by reference mit Wrapper-Klassen? Allgemeine Java-Themen 2
dayaftereh Java executable wrapper? Allgemeine Java-Themen 4
K Wrapper um ZipInputStream funktioniert nicht Allgemeine Java-Themen 2
H Einbinden einer 3rd party DLL via Java Wrapper (JNI) Allgemeine Java-Themen 11
J Wrapper Array in korresp. primitiven Array umwandeln? Allgemeine Java-Themen 2
A Eigene Wrapper-Klassen Allgemeine Java-Themen 2
G Object. Wrapper Allgemeine Java-Themen 12
R JNI-Dlls aus dynamischen Wrapper-Klassen laden Allgemeine Java-Themen 14
S Java Wrapper Allgemeine Java-Themen 6
M Java Wrapper für interaktive Perl-Skripte Allgemeine Java-Themen 3
G wrapper --> unwrapper Allgemeine Java-Themen 5
M Methodenübersicht einer Klasse einsehen Allgemeine Java-Themen 14
Jose05 Java-Klasse im extra cmd-Fenster ausführen Allgemeine Java-Themen 3
torresbig Klasse mit extends Calendar über Methoden ändern (Hirnblockade) Allgemeine Java-Themen 7
A Zweite Service Klasse beim Kompilieren Allgemeine Java-Themen 6
B Ein Objekt einer Klasse mehreren anderen Klassen zur Verfügung stellen? Allgemeine Java-Themen 6
Atten007 Java-Klasse auf macOS entpacken? Allgemeine Java-Themen 2
M Klasse durch Klassen Aufteilung verbessern, aber wo? Allgemeine Java-Themen 1
E Eine Methode einer extendeten Klasse deakitivieren Allgemeine Java-Themen 12
H Kombination Interface und Abstrakte Klasse bei Generics Allgemeine Java-Themen 3
EinNickname9 Best Practice Singleton und Singleton mit Instanz zu anderer Klasse -Pattern Allgemeine Java-Themen 30
Y ImagePanel von anderer Klasse in eine MainFrame Klasse hinzufügen. Allgemeine Java-Themen 1
Lukas2904 Schleife mit ansteuerung einer Klasse Allgemeine Java-Themen 5
d.lumpi Aus Einer Klasse auf ein Objekt einer anderen Klasse Zugreifen Allgemeine Java-Themen 1
missy72 Klassen Eigene Klasse MessageWindow ähnlich der Alert Klasse Allgemeine Java-Themen 2
Drachenbauer wie kann ich alle instanzen einer Klasse durchsehen, ohne, dass diese in einer Liste erzeugt wurden? Allgemeine Java-Themen 11
kanywayne Java programmieren: Polynom Klasse Allgemeine Java-Themen 4
L Die abzuleitende Klasse als Parameter übergeben Allgemeine Java-Themen 4
S Klassen Einfügen von unbekannter menge an Variablen in eine Klasse mithilfe von ASM Allgemeine Java-Themen 5
C Klasse mit Mockito simulieren Allgemeine Java-Themen 9
P einen public <Optinal String> in einer anderen Klasse mit einem Int vergleichen Allgemeine Java-Themen 2
S Wenn eine Klasse zwei Interfaces mit derselben Methodensignatur implementiert: welche wird aufgerufen? Allgemeine Java-Themen 15
Thallius Key/Value Table in Klasse einlesen Allgemeine Java-Themen 14
S static in Interface und Klasse Allgemeine Java-Themen 2
W Was genau sind IOTools? Kann ich stattdessen nicht die Scanner Klasse verwenden? Allgemeine Java-Themen 3
V Threads Probleme beim Aufrufen von Methoden einer anderen Klasse (Threads) Allgemeine Java-Themen 14
X Collections Gibt es eine Klasse welche die Vorteile von List und HashMap vereint, aber konstante Laufzeit (O(1)) hat in Java? Allgemeine Java-Themen 4
D javassist API Klasse in MethodCall ermitteln Allgemeine Java-Themen 8
kodela Klasse mit "gezipten" Daten Allgemeine Java-Themen 6
J Builder Klasse mit Lombok bauen Allgemeine Java-Themen 2
L Operatoren Java Reflections: Alle Methoden einer Klasse aufrufen ohne Exceptions Allgemeine Java-Themen 5
M [SOAP] - Klasse aus WSDL ausschließen Allgemeine Java-Themen 2
N Generic Type einer Generischen Klasse während der Laufzeit bekommen Allgemeine Java-Themen 2
X Klassen Klasse BreakIterator Allgemeine Java-Themen 6
R Arraylist in andere Klasse leiten und bearbeiten Allgemeine Java-Themen 10
kodela Klassen Klasse "vergisst" ihre Daten Allgemeine Java-Themen 2
pkm Kann eine ServerSocket-Klasse nicht stateful sein? Allgemeine Java-Themen 4
E Socket Dynamische Klasse von ObjectOutputStream lesen. Allgemeine Java-Themen 8
M Matcher-Klasse findet match nicht Allgemeine Java-Themen 6
cool_brivk24 Variablen abfragen von Boolean von anderer Klasse Allgemeine Java-Themen 12
S Seltsames Ergebnis mit Date-Klasse Allgemeine Java-Themen 6
J int Werte in einer anderen Klasse in Arrays speichern Allgemeine Java-Themen 3
D Warum kann ich eine (deflaut) Klasse aus einer Libary in einem anderen Projekt benutzen? Allgemeine Java-Themen 3
Neoline Klassen Singleton Klasse buchmanager Allgemeine Java-Themen 19
M Kapselung Modellierung von Intervallen: Klasse Interval Allgemeine Java-Themen 4
B Übernommene Variablen(werte) aus der Main-Klasse ändern? Allgemeine Java-Themen 9
ReinerCoder Klasse kann nicht public deklariert werden Allgemeine Java-Themen 2
ReinerCoder Methode einer Klasse meldet Fehler "misplaced construct(s)" Allgemeine Java-Themen 13
I Collection - contains-Methode überschreiben (anonyme innere Klasse) Allgemeine Java-Themen 4
X Klassen File-Klasse wird als Directory markiert Allgemeine Java-Themen 8
S Methoden Liste soll Methode aus innerer Klasse aufrufen Allgemeine Java-Themen 4
J IndexOutOfBoundsException bei der Nutzung der Klasse Message von mime4j Allgemeine Java-Themen 5
P Array einer abstrakten Klasse Allgemeine Java-Themen 4
J Zugriff auf erstellte Objekte einer Klasse von einer Klasse ausserhalb Allgemeine Java-Themen 3
kodela Dynamisches Array in einer Klasse Allgemeine Java-Themen 5
M Was geschieht mit Java-Klasse, die aus ArrayList entfernt wird? Allgemeine Java-Themen 10
perlenfischer1984 Lombok Builder soll andere Klasse bauen Allgemeine Java-Themen 4
perlenfischer1984 Mit Lombok Builder Felder in Super Klasse füllen Allgemeine Java-Themen 12
T String aus While Schleife für ganze Klasse sichtbar machen Allgemeine Java-Themen 5
K Best Practice Auf die Klasse zugreifen im erzeugten ActionListener Allgemeine Java-Themen 2
K Mit Button neue Klasse öffnen Allgemeine Java-Themen 9
J Reflection mit Klasse und Subklasse Allgemeine Java-Themen 11
C Classpath Neue Klasse über einen Button ausführen Allgemeine Java-Themen 3
magdaStone Logikproblem Umschalten von booleans in anderer Klasse Allgemeine Java-Themen 7
P mehrer Verschiedene Objekte in einer Klasse erstellen. Allgemeine Java-Themen 4
A Java Klasse auf Tomcat während der Laufzeit austauschen Allgemeine Java-Themen 1
C Abstrakte Klasse, lokale Variable-Problem Allgemeine Java-Themen 1
N Vererbung Design-Problem mit vorhandenen, von der Klasse unabhängigen Methoden Allgemeine Java-Themen 12
Messoras Klassen Sämtliche Variablen einer Klasse übernehmen Allgemeine Java-Themen 6
H Methoden Methode 'updateItem' der Klasse 'TreeCell' Allgemeine Java-Themen 3
B Animierte Klasse schreiben - Wie? Allgemeine Java-Themen 9
M Klassen Eine Klasse in mehreren Klassen einbinden Allgemeine Java-Themen 11
N Methoden Methoden einer Klasse auf Grundlage eines Strings aufrufen Allgemeine Java-Themen 6
AssELAss Log4j Logging Ausgabe für jede Klasse in seperates File Allgemeine Java-Themen 2
L Eclipse JavaFX Klasse starten programmatisch Allgemeine Java-Themen 1
F Try/catch über ganze Klasse Allgemeine Java-Themen 9
L Von ArrayList abgeleitete Klasse nur mit bestimmten Objekten füllen Allgemeine Java-Themen 1
so_ein_Komischer Erste Schritte java Math Klasse finden? Allgemeine Java-Themen 2
J beans.instantiate(): Klasse kann nicht instanziiert werden Allgemeine Java-Themen 2
I Interface Interface / Klasse - wieso Abstract? Allgemeine Java-Themen 13
R Abstrakte Basisklasse und instanzierte Objekte der abgeleiteten Klasse als Basisklasse übergeben Allgemeine Java-Themen 2
F Methodenaufruf mit abgeleiteter Klasse als Arg... Allgemeine Java-Themen 10
M Klasse in separaten Thread ausführen.Wie genau? Allgemeine Java-Themen 2
A Best Practice Unterschied zwischen einer sauberen Dependency Injection und einer statischen Klasse Allgemeine Java-Themen 5
F Methoden in der Enumeration Klasse Allgemeine Java-Themen 1
S Die Initialisierung von Feldern in ableitender Klasse erzwingen..? Allgemeine Java-Themen 16
S Mit Generics Klasse erstellen die selbst T erweitert..? Allgemeine Java-Themen 4
M Variable außerhalb Klasse definierbar? Allgemeine Java-Themen 2

Ähnliche Java Themen

Neue Themen


Oben