JNI 샘플

Passing Strings from C to Java through a StringBuffer, Accessor Methods

C code:

HArrayOfChar *charArray;
long length = unilen(cAbbreviatedName);

charArray = makeCharArray(cAbbreviatedName, length);

execute_java_dynamic_method (
EE(),
(HObject *) abbreviatedName,
"append",
"([C)Ljava/lang/StringBuffer;",
charArray);

Using JNI:

JNIEXPORT jint JNICALL
Java_COM_novell_nsi_libsWrapper_BinderyJNI_NWScanObject /* modified for example */
(
JNIEnv *env,
jclass obj,
jobject objName, // out, optional, StringBuffer
)
{
nstr8 cObjectName [MAX_BINDERY_OBJECT_NAME_LEN];

jstring javaString;
jclass cls;
jmethodID mid;

.
.
.
Some code to get cObjectName

javaString = (jstring)(*env)->NewStringUTF(env, (const char *)cObjectName);

cls = (*env)->GetObjectClass(env, objName);
mid = (*env)->GetMethodID(env, cls, "append","(Ljava/lang/String;)Ljava/lang/StringBuffer;");
if (0 == mid)
{
printf("GetMethodID returned 0\n");
return(-1);
}
(*env)->CallObjectMethod(env, objName, mid, javaString);

Passing Strings from Java to C, with Localization

The 1.0 old way was to use the call:

javaString2CString(javaStr,cStr,sizeof(cStr));
Now we have two options:
Use the netware localization routines to make a CString
or call GetStringUTF(env,javaobj,cStr);
GetStringUTF creates a UTF string which if the high bit is not set, then it is like any normal CString. If the Highbit is set, it indicates the next char belongs to the same character. UTF is compressed unicode. Example (old way): javaString2CString (oldPassword, oldPasswordStr, sizeof (oldPasswordStr));

Example (new way with localization):

CFunction(JNIEnv *env,
jclass cls,
jstring jString) // this guy comes in
{

unicode *uStr;
pnstr cLocalizedStr;
size_t uLength;

cLocalizedStr =(pnstr) malloc(((*env)->GetStringLength(env,jString)+1)*2);
uStr = (unicode *)(*env)->GetStringChars(env,jString,0); //stays in unicode

ccode = NWUnicodeToLocal(_hUnicodeToLocal,
((pnuint8) cLocalizedStr), // this will contain our new string
((*env)->GetStringLength(env,jString)+1),
uStr,
0xFF, // strNoMap
&uLength
);

if(N_SUCCESS != ccode)
{
return(ccode);
}

Example (jni way without localization):

uStr = (unicode *)(*env)->GetStringChars(env,jString,0); //stays in unicode

Example Cstring, you are sure is not unicode ever.

Str = (*env)->GetStringUTFChars(env,jString,0); //regular C string

Passing int from Java to C

This is so simple it hardly deserves mention.
In java:

The native declaration:
public native int passInt(int intToPass);

The java call

int j = 1;
passInt(j);

The native handling in C

JNIEXPORT jint JNICALL
Java_passInt(jint thePassedInt)
{
//jint in C is a signed 32 bit integer;
printf("the int is %d",thePassedInt);

//There is no way to change the java variable directly.
thePassedInt = 5; // this gets lost after the return.
return(thePassedInt); // you could return it,
// But what if you have more than one to return?
// Then you must pass in (Integer?) objects and set the values
// through CallObjectMethod() or SetIntField().
}

Passing Objects from C to Java

cls = (*env)->GetObjectClass(env, objID);
mid = (*env)->GetMethodID(env, cls, "setValue","(I)V");
if (0 == mid)
{
printf("GetMethodID returned 0\n");
return(-1);
}
(*env)-&gt;CallVoidMethod(env, objID, mid, cObjectID);</code>

Directly Passing a String from C to Java, Field Access

name = (*env)->NewStringUTF(env,entryInfo.entryName);
      if (name == NULL)
      {
         printf("NewStringUTF returned NULL\n");
         return (-1);
      }
      fid = (*env)->GetFieldID(env,clazz,"entryName","Ljava/lang/String;");

      (*env)->SetObjectField(env,info,fid,name);

Passing C Structures from C to Java

In java you need an object to represent the structure.
Then you pass the java object into the native.
From C, access the class directly with calls to SetTypeField, where type
is a java type.

In the following example, info is the java type which represents the
C structure testInfo.

struct info{
      int index;
      int space;
      int count;
      int key;
      int nameLength;
      char name[30];
}testInfo;

Here is the java class to represent testInfo

public class EntryInformation
{
   protected int index;
   protected int space;
   protected int count;
   protected int key;
   protected int nameLength;
   protected String  name;
}

Here is the native call.

JNIEXPORT jint JNICALL
Java_FillCStruct
(
   JNIEnv *env,
   jclass obj,
   jobject    info      // EntryInformation object instantiation
)
{
   testInfo entryInfo;
   jclass clazz;
   jfieldID fid;
   jmethodID mid;

   GetInfo(entryInfo);   // fills in the entryInfo

   clazz = (*env)->GetObjectClass(env, info);
   if (0 == clazz)
   {
      printf("GetObjectClass returned 0\n");
      return(-1);
   }
   fid = (*env)->GetFieldID(env,clazz,"index","I");

   // This next line is where the power is hidden. Directly change
   // even private fields within java objects. Nasty!
   (*env)->SetIntField(env,info,fid,testInfo.index);

   fid = (*env)->GetFieldID(env,clazz,"space","I");
   (*env)->SetIntField(env,info,fid,testInfo.space);

   fid = (*env)->GetFieldID(env,clazz,"count","I");
   (*env)->SetIntField(env,info,fid,testInfo.count);

   fid = (*env)->GetFieldID(env,clazz,"key","I");
   (*env)->SetIntField(env,info,fid,testInfo.key);

   fid = (*env)->GetFieldID(env,clazz,"nameLength","I");
   (*env)->SetIntField(env,info,fid,testInfo.nameLength);

   name = (*env)->NewStringUTF(env,testInfo.name);
   if (name == NULL)
   {
      clazz = (*env)->FindClass(env,"java/lang/OutOfMemoryError");
      (*env)->ThrowNew(env,clazz,NULL);
      return (-1);
   }
   fid = (*env)->GetFieldID(env,clazz,"name","Ljava/lang/String;");
   (*env)->SetObjectField(env,info,fid,name);
}

Passing Objects from Java to C

Making Java Strings in C

non-jni code:

      Hjava_lang_String *name;
      name = makeJavaString (cName, strlen (cName));

jni code:

      name = (*env)->NewStringUTF(env,cName);
      if (name == NULL)
      {
         clazz = (*env)->FindClass(env,"java/lang/OutOfMemoryError");
         (*env)->ThrowNew(env,clazz,NULL);
         return (-1);
      }

Passing a Single String Array Element from C to Java

non-jni code:

      Hjava_lang_String *javaVolName;
      unhand (volName)->body[0] = (HString *) javaVolName;

jni code:

      jobjectArray volName;
      jstring javaVolName;

      javaVolName = (*env)->NewStringUTF(env, cVolNameStr);

      (*env)->SetObjectArrayElement(env,volName,0,javaVolName);

Passing a Single Int Array Element from Java to C

non-jni code:

      cInt = unhand (volNumber)->body[0];

jni code:

      jint *arr;

      arr = (*env)->GetIntArrayElements(env, javaIntArr,0);
      cInt = (nuint8) arr[0];
      (*env)->ReleaseIntArrayElements(env, javaIntArr, arr, 0);

Passing a Single Int Array Element from C to Java

non-jni code:

      unhand (volNumber)->body[0] = cInt;

jni code:

      jint jIntTemp[1]; // SetIntArrayRegion expects a jintArray coming in

      jIntTemp[0] = searchSequence.searchDirNumber;
      (*env)->SetIntArrayRegion(env, javaIntArr,0,1,jIntTemp);
This entry was posted in Java. Bookmark the permalink.

1 Response to JNI 샘플

  1. Pingback: JNI 사용법 | threadbuilder

Leave a comment