22.4Nativ die String-Länge ermitteln
Wir haben unsere Funktion noch nicht zu Ende geführt. Es fehlt die Berechnung der Zeichenkettenlänge, für die wir den String zuerst von der Unicode-Implementierung in ein C-Zeichenfeld überführen müssen. Dazu dient eine JNI-Funktion GetStringUTFChars(…), die wir über die Umgebung env nutzen können.
[»]Hinweis
Die Schreibweisen unterscheiden sich im Fall von C oder C++. Während es bei C
heißt, schreiben wir bei C++:
In der objektorientierten C++-Variante ist env als Argument nicht mehr nötig. Wir bleiben bei unseren Buchbeispielen in der prozeduralen C-Welt und übergeben daher allen JNI-Funktionen das JNIEnv.[ 152 ](Siehe dazu http://docs.oracle.com/javase/8/docs/technotes/guides/jni/spec/design.html#native_method_arguments.)
Die Zeichenkettenlänge liefert die C-Funktion strlen(…), die im Header string.h definiert ist:
Listing 22.7strlen.c
#include "strlen.h"
#include <stdio.h>
#include <string.h>
JNIEXPORT jint JNICALL
Java_com_tutego_jni_StrLen_strlen( JNIEnv *env, jclass clazz, jstring s ) {
if ( s == NULL ) {
jclass exc = (*env)->FindClass( env, "java/lang/NullPointerException" );
if ( exc != NULL )
(*env)->ThrowNew( env, exc, "(in C code)" );
return –1;
}
const char* str = (*env)->GetStringUTFChars( env, s, NULL );
if ( str == NULL )
return –1;
int len = strlen( str );
(*env)->ReleaseStringUTFChars( env, s, str );
return (jint) len;
}
Mit JNI lassen sich auf der C-Seite Java-Objekte erzeugen und zerstören, genauso wie sich Java-Methoden aufrufen und Werte austauschen lassen. Wir nutzen das, um ein Ausnahmeobjekt zu erzeugen, wenn es keine Referenz auf ein String-Objekt gibt.