Cast jByteArray zu unsigned char

perichte

Grünschnabel
Hallo,

ich schlage mich schon geraume Zeit mit dem genannten Problem rum. Bei meiner Arbeit muss ich eigentlich nur in JAVA Programmieren und bin daher in C, vor allem mit Pointern, nicht sehr gewandt . Allerdings verwende ich gerade JNI und muss deshalb einige wenige Dinge in C "programmieren". Dabei muss ich eigentlich in C nur fertige Methoden aufrufen und nur die entsprechenden Parameter setzen. Hierzu kommt es bei mir allerdings zu Problemen bei der Umwandlung der übergebenen Parameter.

Folgendes Problem möchte ich gerne lösen:
-Ich übergebe ein JavaByteArray (jByteArray) an die c-Methode
-Anschließend möchte das Byte-Array in einem unsigned char Array abspeichern

Hierzu ein kleines Codebeispiel:

Code:
JNIEXPORT jbyteArray JNICALL Java_api_SHA1_zSha1
  (JNIEnv *env, jobject obj, jbyteArray arr){    	

unsigned char input_data[1000000];

unsigned char data[64];

int flen;

flen = (*env)->GetArrayLength (env, arr);

//Das Problem liegt hier: Wie muss der Code aussehen, damit ich das jByteArray in data speichere?
*data = (*env)->GetByteArrayElements(env, arr, 0);

memcpy(input_data, data, flen);

Ich würde mich freuen, wenn mir jemand weiterhelfen kann.
Die Fehlermeldung des Compilers lautet übrigens:

warning: assignment makes integer from pointer without a cast

ANMERKUNG:

Gerade eben hat bei mir folgende Lösung funktioniert:

Code:
jbyte *inputBytes;
int flen;


flen = (*env)->GetArrayLength (env, arr);


inputBytes = (*env)->GetByteArrayElements(env, arr, 0);
(*env)->ReleaseByteArrayElements(env, arr, inputBytes, 0);


memcpy(input_data, (unsigned char *) inputBytes, flen);

Das kann man bestimmt auch eleganter lösen? Habe irgendwo gelesen, dass es über GetByteArrayRegion() gehen soll...

Allerdings habe ich immernoch das Problem, dass ich gerne hätte, dass ich dem unsigned char Array sage, dass es nur 64 Byte groß ist. Wie kann ich das bei dem Cast hier gescheit anwenden? Danke im voraus für die Antworten.
 
Zuletzt bearbeitet:
Hi.
Gerade eben hat bei mir folgende Lösung funktioniert:

Code:
jbyte *inputBytes;
int flen;


flen = (*env)->GetArrayLength (env, arr);


inputBytes = (*env)->GetByteArrayElements(env, arr, 0);
(*env)->ReleaseByteArrayElements(env, arr, inputBytes, 0);


memcpy(input_data, (unsigned char *) inputBytes, flen);

Das kann man bestimmt auch eleganter lösen? Habe irgendwo gelesen, dass es über GetByteArrayRegion() gehen soll...

Allerdings habe ich immernoch das Problem, dass ich gerne hätte, dass ich dem unsigned char Array sage, dass es nur 64 Byte groß ist. Wie kann ich das bei dem Cast hier gescheit anwenden? Danke im voraus für die Antworten.
Du darfst das Array, welches du von der GetByteArrayElements Funktion bekommst, natürlich erst wieder mit der ReleaseByteArrayElements Funktion freigeben, wenn du es nicht mehr brauchst.

Nachdem du es freigegeben hast darfst du es nicht mehr verwenden. (in Java hättest du eine NullPointer Exception bekommen - in C ist es mehr oder weniger Zufall was dann passiert).

Warum willst du denn überhaupt das Array nochmal umkopieren? Es ist doch beides nur ein Speicherblock, da gibt es keinen Unterschied.

Gruß

PS: Beim memcpy Aufruf brauchst du nicht nach (unsigned char*) casten. Die Funktion arbeitet sowieso nur mit void Zeigern.
 
Zuletzt bearbeitet:
Hi,

danke für die Antwort. das memcpy mache ich, weil ich einer anderen C-Funktion das Array als unsigned char-Array übergeben muss.

Hab den Code jetzt folgendermaßen abgeändert:



Code:
unsigned char input_data[1000000];

flen = (*env)->GetArrayLength (env, JavaByteArray);

inputBytes = (*env)->GetByteArrayElements(env, JavaByteArray, 0);

memcpy(input_data, inputBytes, flen);

Jetzt ist bei mir diesbezüglich noch eine andere Frage aufgetaucht.
Nachdem ich eine C-Funktion mit entsprechenden Parametern aufgerufen habe, liefert diese mir ein unsigned char-Array zurück. Jetzt möchte ich dieses Array als jByteArray an die Java Funktion zurückgeben. Dies scheint aber nicht ganz zu funktionieren, denn die Ausgaben, die ich auf der Java-Seite erhalte sind alles andere als richtig.

Code:
int outlen = 20;

unsigned char output_hash [int Längexy]; //Das ist die Rückgabe der aufgerufenen Funktion

jByteArray outputByteArray = (*env)->NewByteArray (env,outlen);
(*env)->SetByteArrayRegion (env, outputByteArray, 0, outlen, (jbyte *) output_hash);

return outputByteArray;

Ich verstehe nicht, wo hier der Fehler liegen soll, dennoch ist meine Ausgabe totaler Murks. Für Anregungen bin ich sehr dankbar.
 
Zuletzt bearbeitet:
Hi.
Hi,

danke für die Antwort. das memcpy mache ich, weil ich einer anderen C-Funktion das Array als unsigned char-Array übergeben muss.
Das Kopieren hat aber dann keinen Sinn. Du kopierst doch nur x Bytes aus einem Speicherbereich in einen anderen Speicherbereich - weiter passiert da nichts, es sind nachwievor die gleichen Werte.

Du mußt lediglich die jbyte* Variable zu unsigned char* casten.

Stimmen denn die Werte bevor du die Funktion aufrufst? Stimmen die Werte die von der Funktion zurückgegeben werden?

Gruß
 
Hi,

okay, mir leuchtet das mittlerweile ein mit dem Kopieren. Dennoch ist meine Mehthode immer noch nicht zufrieden.

Sie benötigt unter anderem folgenden Parameter:

Code:
cmethod(unsigned char *input_data, ........)

Folgendes habe ich implementiert:

Code:
JNIEXPORT jbyteArray JNICALL Java_PackageXY_Hash
  (JNIEnv *env, jobject obj, jbyteArray arr){

int flen = (*env)->GetArrayLength (env, arr);

jbyte *inputBytes = (*env)->GetByteArrayElements(env, arr, 0);
(*env)->ReleaseByteArrayElements(env, arr, inputBytes, 0);

Anschließend nun will ich die Methode aufrufen mit:

Code:
cmethod((unsigned char *) inputBytes,.........)

Trotzdem funktioniert es immernoch nicht. Die Methode kann nicht erfolgreich ausgeführt werden. Im ByteArray, dass übergeben wird, sind Hexadezimalzahlen enthalten, aber das dürfte ja keine Rolle spielen. Irgendwie bin ich verzweifelt :( Ich muss aus dem Byte-Array ein Pointer auf ein unsigned char Array erstellen? kann mir vielleicht direkt jeman d ein Code-beispiel aufzeigen, wie das funktionieren könnte? Würde sehr helfen.
 
Zuletzt bearbeitet:
Hi.
Hi,

okay, mir leuchtet das mittlerweile ein mit dem Kopieren. Dennoch ist meine Mehthode immer noch nicht zufrieden.

Sie benötigt unter anderem folgenden Parameter:

Code:
cmethod(unsigned char *input_data, ........)

Folgendes habe ich implementiert:

Code:
JNIEXPORT jbyteArray JNICALL Java_PackageXY_Hash
  (JNIEnv *env, jobject obj, jbyteArray arr){

int flen = (*env)->GetArrayLength (env, arr);

jbyte *inputBytes = (*env)->GetByteArrayElements(env, arr, 0);
(*env)->ReleaseByteArrayElements(env, arr, inputBytes, 0);

Anschließend nun will ich die Methode aufrufen mit:

Code:
cmethod((unsigned char *) inputBytes,.........)

Trotzdem funktioniert es immernoch nicht. Die Methode kann nicht erfolgreich ausgeführt werden.
Was heißt denn das? Stürzt das Programm ab? Wird eine Fehlermeldung angezeigt?
Im ByteArray, dass übergeben wird, sind Hexadezimalzahlen enthalten, aber das dürfte ja keine Rolle spielen.
Natürlich spielt das eine Rolle was in dem Array drin steht. Was sind denn für dich Hexadezimalzahlen, d.h. wie speicherst du diese denn in dem Array? Meinst du einfach so:
Java:
byte a[] = new byte[5];
a[2] = 0x55;
Was erwartet denn die Funktion für Werte bzw. was tut diese Funktion denn überhaupt? Funktioniert die Funktion überhaupt richtig?
Irgendwie bin ich verzweifelt :( Ich muss aus dem Byte-Array ein Pointer auf ein unsigned char Array erstellen? kann mir vielleicht direkt jeman d ein Code-beispiel aufzeigen, wie das funktionieren könnte?
Eine Array-Variable ist nichts weiter als ein Zeiger in C/C++. Du kannst die Funktion folgendermaßen aufrufen:
C:
cmethod((unsigned char*)inputBytes, ...);
Gruß
 
Zurück