Jni (c++)

Hallo,
habe ein kleines HalloWelt Beispiel mit Java und C++ gemacht, sprich Java ruft ein C++ “Programm” auf und das gibt dann Hallo Welt aus. Jetzt würde ich das ganze sehr gerne so verändern das dass C++ “Programm” dem Java Programm einen Wert (Zahl) zurückgibt, kann mir da vielleicht jemand helfen?

So sieht das ganze bis jetzt aus, aber was muß ich in die beiden Klassen noch alles einbauen das Java was zurückbekommt:

public class HalloWeltBeispiel {
	public static void main(String[] args){
		HalloWelt obj = new HalloWelt();
		obj.printHallo();	
	}
}
class HalloWelt {
	static {
		System.loadLibrary("HalloWelt");
	}
	public native void printHallo();
}
//HalloWelt.cpp
#include <jni.h>
#include "HalloWelt.h"
#include <iostream>
#include <stdio.h>

using namespace std;

JNIEXPORT void JNICALL Java_HalloWelt_printHallo(
								JNIEnv *env, jobject myClass){
          printf("Hallo Welt, sagt das C Programm !!!!!  
");
		  int wert1 = 10;
		  cout << "wert1: " <<wert1 << '
';
}

Zuerst schreibe eine weitere „native“ Methode in Deine Java-Klasse mit dessen Rückgabetyp.

class HalloWelt {
    static {
        System.loadLibrary("HalloWelt");
    }
    public native void printHallo();
    public native int getInt();
}

Erzeuge mit dem javah -jni eine neue C-Header Datei, die etwa wie folgt ausschaut:

JNIEXPORT jint JNICALL Java_HalloWelt_getInt(JNIEnv *env, jobject obj){
    return(1);
}

Kompilieren, fertig :slight_smile:

Die „native“ Java-Methode sollte Dir nun im Glücksfall eine 1 zurückliefern :o)

Gut Schuß
VuuRWerK :wink:

Das hat leider nicht geklappt! :frowning:

Habe aber jetzt hier, JNI (Java talks with C++) Einführung (haertfelder.com) , eine kleine Anleitung gefunden. Das erste Beispiel, helloworld, funktioniert!

Hab jetzt das zweite Beispiel, Parameterübergabe, versucht, hier gibt mein c++ compiler (Borland) allerdings folgende Fehlermeldungen aus:


Error E2288 two.cpp 8: Pointer to structure required on left side of → or ->* i
n function _stdcall Java_classtwo_jnipower(JNIEnv *,_jclass *,long,_jstring ,
float)
Error E2288 two.cpp 10: Pointer to structure required on left side of → or →

in function _stdcall Java_classtwo_jnipower(JNIEnv *,_jclass ,long,_jstring *
,float)
Error E2288 two.cpp 12: Pointer to structure required on left side of → or →

in function _stdcall Java_classtwo_jnipower(JNIEnv *,_jclass *,long,_jstring *
,float)


Hier noch der Source der des C-Listings, hier muß ja was nicht stimmen!?

#include <jni.h>
#include <stdio.h>
#include <math.h>
#include "classtwo.h"

JNIEXPORT jdouble JNICALL Java_classtwo_jnipower(JNIEnv *env, jclass in_cls, jint in_int, jstring in_string, jfloat in_float)
{
	const char *c_string = (*env)->GetStringUTFChars(env, in_string, 0);
	
	jfieldID jfid = (*env)->GetStaticFieldID(env, in_cls, "ddd", "D");
	
	double in_double = (*env)->GetStaticDoubleField(env, in_cls, jfid);
	
	printf("%s %lf + pow(%d,%f)
", c_string, in_double, in_int, in_float);
	
	return (in_double + pow(in_int,in_float));
}

Hat zufällig jemand eine Idee was hier falsch läuft oder ob ich was falsch gemacht habe?

Was ist denn das auch für eine trollige Schreibweise mit den pointern? Edit: Na klar, im C-Standard ist diese Schreibweise so korrekt, my fault :smiley:

Probier mal ob Du mit folgendem Code mehr Glück hast:

#include <jni.h>
#include <stdio.h>
#include <math.h>
#include "classtwo.h"
 
JNIEXPORT jdouble JNICALL Java_classtwo_jnipower(JNIEnv *env, jclass in_cls, jint in_int, jstring in_string, jfloat in_float)
{
    const char *c_string = env->GetStringUTFChars(env, in_string, 0);
    jfieldID jfid = env->GetStaticFieldID(env, in_cls, "ddd", "D");
    double in_double = env->GetStaticDoubleField(env, in_cls, jfid);
    printf("%s %lf + pow(%d,%f)
", c_string, in_double, in_int, in_float);
    return (in_double + pow(in_int,in_float));
}

Gut Schuß
VuuRWerK :wink:

Edit: Mit fällt gerade ein warum Dein Kompiler diese Schreibweise anscheinend nicht mag. Die alte schreibweise für den pointer in C ist (*env)-> wenn Du aber das ganze mit einem C++ Compiler kompilierst musst Du env-> schreiben. Daher benutze lieber den gcc da kannst Du (*env) schrieben da es ein reiner C-Compiler ist. Oder Du umschließt Deinen Code mit folgendem:

#ifdef __cplusplus
extern "C" {
#endif

// Dein C Code

#ifdef __cplusplus
}
#endif

Das selbe steht im übrigen auch in der von javah erzeugten Header-Datei damit selbst der C+±Compiler weiß das er den darin befindlichen Code ausschließlich wie C-Code zubehandeln hat.

Danke für die Tipps, aber leider hat nichts geholfen!!! :frowning:

Zuerst habe ich versucht „(*env)->“ durch „env->“ zu ersetzen…dann kamen aber noch mehr Compiler-Fehler…(15 Stück)
Dann habe ich wieder alles ins alte geändert und meinen Source umschloßen, dann war ich wieder bei den alten 3 Fehlermeldungen wie bei meiner Ausgangslage. :frowning:

Noch eine Idee was falsch sein könnte?

Und schonmal mit einem anderen Compiler versucht? Der gcc(GNU-C-Compiler) sei hier an der Stelle zu empfehlen.

Gut Schuß
VuuRWerK :wink:

Da ist ein diffiziler Unterschied, je nachdem, ob man einen C oder C+±Compiler verwendet. Ersetze mal deine Aufrufe wie

const char *c_string = (*env)->GetStringUTFChars(env, in_string, 0);

durch

const char *c_string = env->GetStringUTFChars(in_string, 0);

(also wie VuuRWerK schon sagte, aber zusätzlich den ersten “env”-Parameter weglassen). Siehe auch http://en.wikipedia.org/wiki/Java_Native_Interface#How_the_JNI_works zum Unterschied zwischen der C- und der C+±Version