# c++ Bibliothek einbinden



## jenzi (11. Jan 2007)

Hallo,
Ich möchte in einem Java-Prog eine c++ Bibliothek einbinden. Ich weiß das es über jni geht. Aber wie?

ich habe die
 JavaTest.h
und die
 libJavaTest.so

Die c-Klasse heißt "JavaTest" und die methode "int returnValue(int aValue)".

Kennt jemand ein einfaches Beispiel zum aufrufen einer C-Methode aus Java?

Danke


----------



## thE_29 (11. Jan 2007)

Du musst dir einen Wrapper schreiben!

Hättest du die SUCHE benutzt hättest du einen Beitrag gefunden, der nicht mal solange her ist:

http://www.java-forum.org/de/viewtopic.php?t=42263

Lies dir den THREAD BIS ZUM ENDE durch


----------



## dsv fritz (11. Jan 2007)

Oder um sich Grundsätzlich mit JNI zu beschäftigen:
java.sun.com/j2se/1.4.2/docs/guide/jni/spec/jniTOC.html


----------



## jenzi (11. Jan 2007)

Also ich hab mir das jetzt mal angeschaut. Folgende Fragen hab ich da noch:

1. Hab ich keine dll-Files, sondern (wie gesagt) JavaTest.h und die libJavaTest.so.
Ich weiß jetzt nicht wo der Unterschied ist.

2. Sind die Methoden im C-Code nicht als JNICALL-Methode definiert. Da ich später mit diesem Vorgehen auf eine ganze Menge C-Klassen zugreifen will kann ich das auch nicht mal eben einfügen. (außerdem hab ich 0 Ahnung von Cpp)

3. Wie kann ich dem Java-Prog zeigen, wo die Biblio liegt?


----------



## jenzi (11. Jan 2007)

Also zum Verständnis hab ich mir mal ne kleine Bsp.Biblio erstellt.

JavaTest.h

```
class JavaTest
{
  public:
    int returnValue(int aValue);
};
```

JavaTest.cxx

```
#include "JavaTest.h"

int JavaTest::returnValue(int aValue)
{
  return aValue;
}
```

JavaTestMain.cxx

```
#include <iostream.h>
#include "JavaTest.h"

int main(int aNbrOfArgs, char** aArgsList)
{
  JavaTest theJavaTest;

  cout << "JavaTest returns " << theJavaTest.returnValue(123) << endl;

  return 0;
}
```

Jetzt will ich die JavaTest.returnValue aus Java einfach aufrufen. Die Cpp-Files sind als libJavaTest.so gespeichert.


----------



## jenzi (11. Jan 2007)

Achso. Die JavaTestMain ist nicht in der Biblio. Die war nur zum testen.


----------



## Guest (11. Jan 2007)

Also wenn du ne ganze Menge Dateien einbinden willst und keine Ahnung von C++ hast, ist das erstmal schlecht 

Aber aber nicht hoffungslos. Ich empfehle dir SWIG. Mit SWIG kann man sich die Wrapper klassen mittels eines Konfigurationsfiles generieren lassen. as klappt auch sehr gut und geht ruck zuck!!! 

Es dauert allerdings etwas, bis man sich bei komplexeren C-Gebilden (Funktionspointer, void*, etc) einen passenden Konfugurationsfile geschrieben hat, der die Sache so in Java wrappt, das man damit intuitiv arbeiten kann. Aber zu den meisten Sachen findet man in der onlien doku gute Beispiele und von Hand ist auch nicht gerade einfach wenn man nur eine dll und einen Header hat einen void* in Java zu wrappen und damit zu arbeiten.


----------



## thE_29 (11. Jan 2007)

@jenzi: warum liest du nicht einfach mal den Thread durch?!

Dann wirst du kapieren, dass das was du willst einfach nicht geht.. (aber wozu lesen..)

Außerdem .dll == Windows
.so == Linux/Mac/Unix

Hier ne kleine Anleitung für Linux: http://public.cabit.wpcarey.asu.edu/janjua/java/jni/


----------



## jenzi (12. Jan 2007)

OK, was ist wrappen?

Da seh ich ja schon mein Projekt ins Wasser fallen.

Was müsste ich denn tun, damit es funktioniert? In allen C-Files rumschreiben? Das wird aber ne Menge Arbeit.


----------



## thE_29 (12. Jan 2007)

Genau, du musst dir selber .so Objekte erstellen die auf die C/C++ .so zugreift, da Java und C/C++ einfach andere Datentypen hat (bzw Ränge, da ja int in C viel kleiner ist als in Java).


----------



## jenzi (12. Jan 2007)

Kann ich denn die C-Methoden so schreiben, dass ich ihr den Namen der jeweiligen aufzurufenden C-Methode übergebe?
So das die von mir geschriebene Methode die tatsächliche Methode anhand von einer Variablen aufruft?

zB.:

```
JNIEXPORT int JNICALL
aufruf(String MetName) {
   return MetName();
}
```

Oder muss ich dann eine solche Methode für jede der schon vorhandenen C-Methoden schreiben auf die ich zugreifen will?


----------



## Axel (12. Jan 2007)

Also erstmal muss ich den hier Anwesenden Recht geben.
@Jens: Lies erstmal alle verlinkten Artikel/Threads, wenn sie dir angeboten werden. Und allererste Anlaufstelle für Informationen bleibt immer noch SUN mit ihren verschiedenen Java-Artikeln, die einem eigentlich alles Wichtige erklären können. Ich hab auch allein mit deren Hilfe mein erste JNI-Programm gebaut ohne irgendwelche anderen Tutorials oder so zu brauchen.

Eine exzellente Quelle ist z.B. dieses Kapitel eines auf java.sun.com verfügbaren Open Books.

Das dir alle Vorredner gesagt haben, dass das, was du machen willst, nicht geht oder nur über Wrapper geht, liegt vielleicht daran, dass du nicht ganz deutlich gesagt hast, ob du nun eine C/C++-Bibliothek hast, die du nicht entwickelt hast, oder eine, die du selber entwickeln möchtest.

Hast du eine fremde Bibliothek, kannst du die dort enthaltenen Funktionen nicht direkt aus Java mit JNI aufrufen, da JNI zum Einen bestimmte Signaturen der Funktionen fordert, und zum Anderen die Java-Typen nicht mit C-Typen kompatibel sind.
Die einzige Möglichkeit, die du hier hast, ist das "Wrappen". D.h. du baust dir eine Bibliothek, die nichts anderes macht, als deinen Java-Aufruf entgegenzunehmen und die Argumente in C-Typen umwandelt und dann die eigentliche Bibliothek aufruft. Zum Schluss muss natürlich das Ergebnis in Java-Typen umgewandelt werden.

Baust du dir selber eine Bibliothek, die du aufrufen willst, dann bist du komplett frei, welche Typen du nutzt. Du kannst auch direkt mit Java-Typen arbeiten (also mit den JNI-Strukturen, die diese darstellen).

Genereller Ablauf:
1. Java-Klasse schreiben mit deiner nativen Methode ("[modifier] native [return_type] [name]([arguments])"), und dem Befehl zum Laden der Bibliothek
2. Kompilieren der Java-Klasse
3. Generieren der Header-File mit javah
4. Implementieren deines nativen Codes mit der eben erzeugten Header-File
5. Kompilieren des nativen Codes zu der gewünschten Bibliothek

Wenn du eine fremde Bibliothek hast, dann machst du im 4. Schritt nichts anderes, als den Aufruf für die eigentliche Bibliothek zu übersetzen und zu delegieren...

Ich hoffe das war hilfreich soweit. Und lies das verlinkte Buch-Kapitel!


----------



## Axel (12. Jan 2007)

Hmm, leider geht Edit als Anonymer nicht...Egal.

@Jens: Die Idee eines nativen Dispatchers für beliebig viele und beliebig verschiedene Funktionen ist etwas arg abstrus (in meinen Augen). In Java könnt ich mir sowas ja mit Reflection noch vorstellen, aber eine ähnliche Funktionalität gibt es meines Wissens nicht C/C++ (Wie auch?). Damit würde nur die Möglichkeit einer massiven "Funktions-Registry" mit enormen Kontrollstrukturen und Typumwandlungen bleiben. Ich glaub selbst mit Funktionspointern wird das ein Unding sein...


----------



## thE_29 (12. Jan 2007)

Naja, in C/C++ kann man Funktionn (callback Funktionen) auch übergeben!

Und man kann Pointer auf Funktionen erstellen und diese dann aufrufen! Also würde es von der Idee her, vielleicht sogar gehen!

Problem is halt, das er in einem Array die Parameter der Methoden übergeben muss, sowie Rückgabewerte.. (da ja nicht immer alles den gleichen return Wert hat).

Das mit den Funktionspointer geht 100% unter Windows, da man oft Funktionen aus dlls nachladen muss und die somit aufruft (sprich genau das was er will).
Nur unter Linux habe ich das ganze noch nicht gemacht!


----------



## Axel (12. Jan 2007)

Ja gut, ich meinte auch weniger, dass das mit Funktionspointern nicht geht, sondern dass das, so wie du beschrieben hast, mit weiteren weiteren Anforderungen versehen ist und daher in meinen Augen keines realistischen Versuchs würdig ist.

Gut, ich muss dazu sagen, dass ich ihn persönlich kenne und daher weiß, in welchem Zeitrahmen er so etwas erledigen müsste (zusammen mit dem, was er ja eigentlich erledigen will)...


----------



## thE_29 (12. Jan 2007)

Naja, man muss halt C/C++ können wenn man sowas machen will!

Sonst schauts da duster aus


----------



## Gast (12. Jan 2007)

Ich kann nur nochmal betonen guck dir SWIG an, der generiert dir fast alles selber, dabrauchst du nur wenig C kenntinsse. Wobei um Callbacks/Funktionspointer umusetzten ist doch etwas arbeit nötig, aber vielllllll weniger als von hand.


----------

