# JNI-functions



## [RTB]H3r0 (10. Feb 2005)

HAllo...
jo ich hab hier die anfragen zur winAPI gfestellt.

und jetzt weiss ich nicht weiter...
(vielleicht ist es auch eher ne c++ problematic... mal sehen):

Ich möchte die WINAPI MessageBox nutzen.
die ist in der winuser.h definiert.
mein java programm ist denkbar einfach:#


```
class WindowsFunctions{
static{
    System.loadLibrary("winapis");
}
    public native static void MsgBox(String text, String titel, int style);
    public static void main(String args[]){
        MsgBox("Text","Titel",4);
    }
}
```
 
da lasse ich javah drüberlaufen.
das ergebnis ist (ohne kommentare): WindowsFunctions.h


```
#include <jni.h>
#ifndef _Included_WindowsFunctions
#define _Included_WindowsFunctions
#ifdef __cplusplus
extern "C" {
#endif
JNIEXPORT void JNICALL Java_WindowsFunctions_MsgBox(JNIEnv *, jclass, jstring, jstring, jint);
#ifdef __cplusplus
}
#endif
#endif
```

jetzt mein *alles entscheidendes*  winapis.cpp file (ohne kommentare):

```
#include <vcl.h>
#include <stdio.h>
#include "WinFunctions.h"
#include <jni.h>
#pragma hdrstop

int WINAPI DllEntryPoint(HINSTANCE hinst, unsigned long reason, void*)
{
  return 1;
}

JNIEXPORT void JNICALL Java_WinFunctions_MsgBox(JNIEnv *env, jclass clazz, jstring text, jstring titel, jint style){
  char buffer[128];
  buffer[0] = *(env->GetStringChars(titel,0));
  for(int i=0;i<=127;i++)
  printf("%c",buffer[i]);
  //MessageBox(NULL,"Text","Titel",4);  
}
//erstellt mit bb3.0
```

ich weiss... in der onlineresourcen, habe ich für die SetStringCHars-Methode andere schreibweisen gesehen,.#
ich habe eion bischen in den headder files gestöbert und hab festgestellt, dass hier wohl ein unterschied zwischen c und c++ zum tragen kommt.

diese dll hier kann ich bei java einbinden, und ich kann die messagebox sogar sehen!!
nur ist der text falsch.
er gibt mir nur das erste zeichen wieder aus.
wie mann an diesem code-schnipsel sieht,  gebe ihc das ganze array aus...
nur buffer[0] enthällt sinnvolle daten.
bei der messagbox kommt noch hinzu, dass sie leider 
    const char *
braucht. 
das programm ist so lauffähig.
 nur ist die ausgabe ungenügend.
wie kann ich meine JNIENV dazu veranlassen, den string vernünftig in diesem array (Buffer) abzulegen??
hilfe gesucht.

thx a lot H3r0.
[R0c|< ']['h3m Br4Ve]


----------



## thE_29 (10. Feb 2005)

1. sollte deine Java Klasse gleich heißen wie die erstelle dll (in meinem Bsp jni_test)
2. das holen von den Strings sieht bei dir nicht gut aus!

JAVA_CODE


```
public class jni_test
{
  static{
      System.loadLibrary("JNI_TEST");
  }
  public native static void MsgBox(String text, String titel, int style);

  public jni_test()
  {
    MsgBox("Hallo test","Titel",4);
  }

  public static void main(String[] args)
  {
    jni_test jni_test = new jni_test();
  }
}
```

C++ Code -- verwende MSVC++ 6.0

```
#include <windows.h>
#include "jni_0005ftest.h"

JNIEXPORT void JNICALL Java_jni_1test_MsgBox
  (JNIEnv *env, jclass cl, jstring text, jstring title, jint typ)
{

	char *mytext = new char[env->GetStringLength(text)]; //größe
	char *mytitle = new char[env->GetStringLength(title)]; 
	int iTyp = (int) typ;

	env->GetStringUTFRegion(text,0,env->GetStringLength(text),mytext);
	env->GetStringUTFRegion(title,0,env->GetStringLength(title),mytitle);
	
	MessageBox(NULL,mytext,mytitle,iTyp);
}
```

jni_0005ftest.h <-- Name wurde durch javah -jni -classpath ... erstellt

```
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>

/* Header for class jni_0005ftest */

#ifndef _Included_jni_0005ftest
#define _Included_jni_0005ftest

#ifdef __cplusplus
extern "C" {
#endif

/*

 * Class:     jni_0005ftest

 * Method:    MsgBox

 * Signature: (Ljava/lang/String;Ljava/lang/String;I)V

 */

JNIEXPORT void JNICALL Java_jni_1test_MsgBox

  (JNIEnv *, jclass, jstring, jstring, jint);


#ifdef __cplusplus
}
#endif

#endif
```

Am besten ist du spielst dich noch ein bisi rum und lernst was drauß 

JNI ist manchmal ziemlich nervig und schwer zu kapieren, aber irgendwann hat mans dann!


----------



## [RTB]H3r0 (10. Feb 2005)

doppelt gemoppelt is weg....


----------



## [RTB]H3r0 (10. Feb 2005)

das hab ich gemerkt.
es gibt ein so gewaltiges datentypen-gemauschel, das ich völlig den überblick verliere.
ich werde mal das alles so erstellen, wie du.
aber compilieren tu ich dann mit bcb3.0

morgen gibts nen feedback.

(wenn wieder nur das erste zeichen reingeht, RASTE ich!!)
vielleicht ist ja GetStringUTFRegion das richtige.
thx. bis bald


----------



## [RTB]H3r0 (11. Feb 2005)

FETT FETT FETT FETT FETT FETT FETT
Das ist so perfekt,und so einfach... ich verstehe nicht, wieso das mit GetStringUTFChars nicht geklappt hat....
hast nen vorschlag?

so klappt das super.
jetzt kann ich wenigstens sicher mit den strings jonglieren. thx a lot!!!
H3r0.
Rock ThEm Brave


----------



## thE_29 (14. Feb 2005)

So, da ist das was du wolltest:

C++ Code - jni_test.cpp - MSVC 6.0


```
JNIEXPORT jboolean JNICALL Java_jni_1test_WritePrivateProfileString
  (JNIEnv *env, jclass cl, jstring appName, jstring keyName, jstring newEntry, jstring fileName)
{
	char *appN = new char[env->GetStringLength(appName)];
	char *keyN = new char[env->GetStringLength(keyName)];
	char *newE = new char[env->GetStringLength(newEntry)];
	char *filN = new char[env->GetStringLength(fileName)];
	
	env->GetStringUTFRegion(appName,0,env->GetStringLength(appName),appN);
	env->GetStringUTFRegion(keyName,0,env->GetStringLength(keyName),keyN);
	env->GetStringUTFRegion(newEntry,0,env->GetStringLength(newEntry),newE);
	env->GetStringUTFRegion(fileName,0,env->GetStringLength(fileName),filN);




	return (jboolean)	WritePrivateProfileString(appN,keyN,newE,filN);
}


JNIEXPORT jstring JNICALL Java_jni_1test_GetPrivateProfileString
  (JNIEnv *env, jclass cl, jstring appName, jstring keyName, jstring def, jstring fileName)
{
	
	char *tmp = new char[MAX_PATH];
	char *appN = new char[env->GetStringLength(appName)];
	char *keyN = new char[env->GetStringLength(keyName)];
	char *defV = new char[env->GetStringLength(def)];
	char *filN = new char[env->GetStringLength(fileName)];
	
	env->GetStringUTFRegion(appName,0,env->GetStringLength(appName),appN);
	env->GetStringUTFRegion(keyName,0,env->GetStringLength(keyName),keyN);
	env->GetStringUTFRegion(def,0,env->GetStringLength(def),defV);
	env->GetStringUTFRegion(fileName,0,env->GetStringLength(fileName),filN);

	int i = GetPrivateProfileString(appN,keyN,defV,tmp,MAX_PATH,filN);

	char *ret = new char[i];
	sprintf(ret,"%s",tmp);

	return env->NewStringUTF(ret);
}
```

Header: jni_0005ftest.h


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

#ifndef _Included_jni_0005ftest
#define _Included_jni_0005ftest
#ifdef __cplusplus
extern "C" {
#endif
/*
 * Class:     jni_0005ftest
 * Method:    WritePrivateProfileString
 * Signature: (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)Z
 */
JNIEXPORT jboolean JNICALL Java_jni_1test_WritePrivateProfileString
  (JNIEnv *, jclass, jstring, jstring, jstring, jstring);

/*
 * Class:     jni_0005ftest
 * Method:    GetPrivateProfileString
 * Signature: (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;
 */
JNIEXPORT jstring JNICALL Java_jni_1test_GetPrivateProfileString
  (JNIEnv *, jclass, jstring, jstring, jstring, jstring);

#ifdef __cplusplus
}
#endif
#endif
```

Java Code - jni_test.java:


```
public class jni_test
{
  static{
      System.loadLibrary("JNI_TEST");
  }
  public native static boolean WritePrivateProfileString(String appName, String keyName, String newEntry,String fileName);
  public native static String GetPrivateProfileString(String appName, String keyName, String def,String fileName);

  public jni_test()
  {
      System.out.println(WritePrivateProfileString("bla","key","5","C:\\test.ini"));
      System.out.println(GetPrivateProfileString("bla","key","29","C:\\test.ini"));
  }

  public static void main(String[] args)
  {
    jni_test jni_test = new jni_test();
  }
}
```


Und ab jetzt mach ich dir nix mehr, jetzt hast du genug Funktionen zum Testen!


----------



## [RTB]H3r0 (16. Feb 2005)

danke dir....
nur war mein problem bei den getPrioveateProfileStrings, dass die funktion unter c schon nicht liefen....
vielleicht hab ich ja auch ne falsche implementierung verwendet...
wenn das hier läuft, staune ich ...
(wirklich vielen dank für deine bemühungen)
Thx a lot H3r0


----------



## [RTB]H3r0 (16. Feb 2005)

jetzt mal ehrlich...
das flutscht nur so.
ich frrag dioch nicht weiter....
will ja nen paar wwinapis nutzen, um meine Abschlussarbeit nen bischen aufzuwerten...
(fachinformatik)
mein feghler war, dass bei der Pfadangabe c:\bla
stand und nicht, c:\\bla
das ist schließlich nen fehler in c.

bleib kompetent
H3r0


----------



## thE_29 (16. Feb 2005)

Nö, das ist in jeder Programmiersprache so  (die ich kenne)


\\ = \

\ alleine => nächstes Zeichen ist Escape zeichen

Bsp.: \t = Tabulator

\n = Enter

Man muß also einen \ mit 2 \ darstellen, da er sonst sich denken würde, das nächste Zeichen isn Escape Zeichen, bsp

C:\HALLO => Java ein Fehler, da der kein \H Escapezeichen kennt!

In C net, weils dem wurscht ist, ganz blöd wäre diese Stellung

C:\temp => weder in Java ein Fehler noch in C, da er es so übersetzen würde: C:[TAB]emp

Und wenn du sowas zur Abschlußprüfung net weißt, stellt sich die Frage obst du deine Hausaufgaben immer selber gemacht hast, oder machen hast lassen ;>



Normalerweise, würde ich dein Bsp ja auch nie machen (weil wir sowas net tun), nur in JNI kennt sich kaum einer aus, deswegen hab ichs dir gemacht!


----------



## [RTB]H3r0 (2. Mrz 2005)

thx.


----------



## [RTB]H3r0 (11. Mrz 2005)

gibtes escapezeichen für umlaute???
das wäre die lösung!


----------



## Bert Brenner (9. Jun 2005)

Eine möglichkeit Umlaute relativ problemlos an den JNI Teil weiterzureichen ist z.b.

Alle "ö" ersetzen durch "..o" oder eine andere Zeichenfolge die sonst nicht vorkommt. Und dann im JNI Teil das ganze wieder andersrum ersetzen.


----------



## thE_29 (10. Jun 2005)

Am besten ist Sonderzeichen durch Hex Darstellung ersetzen

Also stattn Ö = 153 DECIMAL Code durch

\0x0099 ersetzen und das schicken!


----------

