ç¹å®ã®æ¹åãã®ãšã³ããªã§ããçµç·¯ãšãã¯ç«¯æãã®ã§ãèªã¿ã«ãããšã³ããªãããããŸããããã容赊ãã
ããŠããšããæ¹ãããJNIã®ãµã³ãã«ã³ãŒããæžããŠæ¬²ãããšããäŸé ŒãåããŸãããCïŒC++ã«ã¯è©³ããæ¹ãªã®ã§ãããJavaã¯ããã§ããªãæ§åãã§ããJava-JNIã§ããããã€ã³ã¿ãŒãã§ãŒã¹ã§åŠçãããããã ãã©ãæããŠãããªãïŒãã®ãããªããšãèãããŸããã
åžæãèããJavaã®nativeã¡ãœãã宣èšããCèšèªçã«è¡šèšãããšããããªæãã ãšæããŸãã
long int testfunc(int *num, char *s)
ã€ãŸããlongãè¿ããŠåŒæ°ã¯åºå倿°ãšããŠæžãæãããâŠãšã
Javaã§è§£éãããšããããªããŸããã
int num = ...; String s = ...; long ret = testfunc(num, s); // ããã§numãšsã®å€ãå€ãã
Javaãç¥ã£ãŠããã°åããã®ã§ããããã®ä»æ§ã¯Javaã§ã¯å®çŸäžå¯èœã§ãããªããªããJavaã®ããªããã£ãïŒint, long, float, doubleãªã©ãªã©ïŒããã³Stringã¯ã倿Žäžå¯ã ããã§ãã
â»ãªãã¬ã¯ã·ã§ã³ã䜿çšããŠã©ãã®ããã®ããšããã®ã¯ããã§ã¯çœ®ããŠãããŸã
ããšãããªããã£ãã¯ãã€ã³ã¿ïŒåç
§ïŒãæ±ããªãã®ã§ãããããåç
§æž¡ãèªäœãã§ããªãã§ãããã
äŸé ŒãããŠããæ¹ã¯ã詊è¡é¯èª€ã®çµæâŠ
int[] intArray = ....; long ret = func1(intArray); // ããã§ãintArrayã®äžèº«ãå€æŽ int intValue = intArray[0]; String stringValue = func2(intValue);
ã®ããã«ãnativeã¡ãœããã2ã€ã«åå²ããããšã§å¯ŸåŠãããããã§ãããfunc1ã«intãæž¡ãããšãããªãŒãšåããŠããããŸããããåè¿°ã®éãintã¯å€æŽäžå¯ãªã®ã§ããã¯ã§ããŸããã
ã§ãã®ã§âŠå€æŽå¯èœãªã¯ã©ã¹ããã©ã¡ãŒã¿ïŒæ»ãå€ã«ãªããžã§ã¯ããå©çšããªããšããŸãã¹ããŒããªè§£ã¯åºãªãã®ã§ãããã¡ãã£ãšã ããµã³ãã«ãæžããŠã¿ãããšæããŸãã
Eclipseã¯å«ãã ã£ãã®ãšããã§ã«åãç°å¢ãæå ã«ããã¿ãããªã®ã§ç«¯æããŸãïŒç¬ïŒã
以åŸãHelloJni.javaãšããååã®ãã¡ã€ã«ã§äœæ¥ãããŸããæçµçã«ã¯ãHelloJniã¯ã©ã¹å
ã«ã€ã³ã¿ãŒã¯ã©ã¹ãå®çŸ©ããŸãã
ã³ã³ãã€ã«ã³ãã³ãã¯ã以äžã®éãã§ãã
$ javac HelloJni.java $ javah HelloJni $ gcc -fPIC -c HelloJni.cpp -I /usr/lib/jvm/java-6-sun/include/ -I /usr/lib/jvm/java-6-sun/include/linux/ $ gcc -shared HelloJni.o -o libHelloJni.so
JNIã®ããããã¡ã€ã«ã®å Žæã¯ãé©å®èªã¿æ¿ããŠãã ãããã
å®è¡ã³ãã³ãã¯ã以äžã®éãã§ãã
$java -Djava.library.path=[libHelloJni.soã眮ããŠãããã£ã¬ã¯ããª] HelloJni
ãªããJavaãã¡ã€ã«äžã«
System.loadLibrary("HelloJni");
ãšèšè¿°ããã®ããå¿ãç¡ãã
åœæ¹ã®å®è¡ç°å¢ã¯ã以äžã®éãã§ãã
$ lsb_release -a No LSB modules are available. Distributor ID: Ubuntu Description: Ubuntu 11.04 Release: 11.04 Codename: natty $ uname -a Linux ubuntu 2.6.38-10-generic #46-Ubuntu SMP Tue Jun 28 15:07:17 UTC 2011 x86_64 x86_64 x86_64 GNU/Linux $ java -version java version "1.6.0_26" Java(TM) SE Runtime Environment (build 1.6.0_26-b03) Java HotSpot(TM) 64-Bit Server VM (build 20.1-b02, mixed mode) $ gcc --version gcc (Ubuntu/Linaro 4.5.2-8ubuntu4) 4.5.2 Copyright (C) 2010 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
64bit Ubuntu Linuxã§ãã
ããã§ã¯ãããããã®ãµã³ãã«ã§ã¯nativeã¡ãœããã®ã€ã³ã¿ãŒãã§ãŒã¹ã¯å€æŽããŸãããåŒã³åºãåæ°ã¯1åã§ããŸãããããã©ã€ããŸãã
è§£æ³ãã®1ïŒObjectã®é åã䜿ã
ããŸããã¬ã€ãªããæ¹ã§ã¯ãããŸãããObjectã®é åãnativeã¡ãœããã«æž¡ãããšã§ãintãšStringã®ãã©ã¡ãŒã¿ãåæã«æž¡ãããã€é åã®èŠçŽ ã倿Žå¯èœãªããšãå©çšããŠå€ãæžãæããæ¹æ³ã§ãã
JavaåŽã¯ãã¡ãã
public native long writeObjectArray(Object[] objects); Object[] objects = {new Integer(5), "HelloWorld"}; long ret = writeObjectArray(objects); System.out.println(String.format("num = %d, str = %s, ret = %d", objects[0], objects[1], ret));
C++åŽã¯ãã¡ãã
â»ããããã¡ã€ã«ã¯ç«¯æããŸã
JNIEXPORT jlong JNICALL Java_HelloJni_writeObjectArray
(JNIEnv *env, jobject thisj, jobjectArray objects)
{
jlong ret = 15;
jclass integerClass = env->FindClass("java/lang/Integer");
jmethodID integerConstructor = env->GetMethodID(integerClass, "<init>", "(I)V");
jmethodID intValueMethod = env->GetMethodID(integerClass, "intValue", "()I");
jint intValue = env->CallIntMethod(env->GetObjectArrayElement(objects, 0), intValueMethod);
jstring stringValue = (jstring)env->GetObjectArrayElement(objects, 1);
const char *s = env->GetStringUTFChars(stringValue, NULL);
printf("第1èŠçŽ [%d], 第2èŠçŽ [%s]\n", intValue, s);
env->SetObjectArrayElement(objects, 0, env->NewObject(integerClass, integerConstructor, intValue * 2));
env->SetObjectArrayElement(objects, 1, env->NewStringUTF("Hello JNI World"));
env->ReleaseStringUTFChars(stringValue, s);
return ret;
}
SetObjectArrayElementã§ãé
åã®èŠçŽ ãæžãæããŠããããšããã€ã³ãã§ãããã³ãã¯Objecté
åã®äžã«intãè©°ãããã£ãã®ã§ãããããããintãååŸããã®ãé£ãããŠæå¿µããŸããâŠã
å®è¡ãããšããããªããŸãã
第1èŠçŽ [5], 第2èŠçŽ [HelloWorld] num = 10, str = Hello JNI World, ret = 15
è§£æ³ãã®2ïŒå€æŽå¯èœãªã¯ã©ã¹ãæž¡ããåŒã³åºãå ã§ãã®å€ã倿Žãã
setterïŒgetterãæã£ãã¯ã©ã¹ãå®çŸ©ããŠããããã¡ãœããã®ãã©ã¡ãŒã¿ãšããããšã§C++åŽã§å€ãæžãæããŸãã
FindClassã¯ã¯ã©ã¹ãæ¢ããããGetMethodIDã¯ã¡ãœãããæ¢ãããã®é¢æ°ã§ãã
ãŸããHelloJniã¯ã©ã¹ã®ã€ã³ããŒã¯ã©ã¹ãšããŠã以äžã®ãããªã¯ã©ã¹ãå®çŸ©ããŸãã
â»å¥ã«ã€ã³ããŒã¯ã©ã¹ã§ããå¿
èŠã¯ãããŸãããå¥ãœãŒã¹ã«ããã®ãé¢åã ã£ãã®ã§ãã€ã³ããŒã¯ã©ã¹ãå©çšããã ãã§ã
public static class SendReceiveObject { private int intValue; private String stringValue; public void setIntValue(int intValue) { this.intValue = intValue; } public int getIntValue() { return intValue; } public void setStringValue(String stringValue) { this.stringValue = stringValue; } public String getStringValue() { return stringValue; } }
å®éã«å©çšããæã¯ããããªæãã§ãã
public native long writeResult(SendReceiveObject sendReceive); SendReceiveObject sendReceive = new SendReceiveObject(); sendReceive.setIntValue(5); sendReceive.setStringValue("Hello World"); ret = writeResult(sendReceive); System.out.println(String.format("sendreceive.num = %d, sendreceive.str = %s, ret = %d", sendReceive.getIntValue(), sendReceive.getStringValue(), ret));
C++åŽã
JNIEXPORT jlong JNICALL Java_HelloJni_writeResult
(JNIEnv *env, jobject thisj, jobject sendReceive)
{
jlong ret = 15;
jclass sendReceiveClass = env->FindClass("HelloJni$SendReceiveObject");
jmethodID getIntValueMethod, setIntValueMethod, getStringValueMethod, setStringValueMethod;
getIntValueMethod = env->GetMethodID(sendReceiveClass, "getIntValue", "()I");
setIntValueMethod = env->GetMethodID(sendReceiveClass, "setIntValue", "(I)V");
getStringValueMethod = env->GetMethodID(sendReceiveClass, "getStringValue", "()Ljava/lang/String;");
setStringValueMethod = env->GetMethodID(sendReceiveClass, "setStringValue", "(Ljava/lang/String;)V");
jint intValue = env->CallIntMethod(sendReceive, getIntValueMethod);
jstring stringValue = (jstring)env->CallObjectMethod(sendReceive, getStringValueMethod);
const char *s = env->GetStringUTFChars(stringValue, NULL);
printf("intValue[%d], stringValue[%s]\n", intValue, s);
env->CallIntMethod(sendReceive, setIntValueMethod, intValue * 2);
env->CallObjectMethod(sendReceive, setStringValueMethod, env->NewStringUTF("Hello JNI World"));
env->ReleaseStringUTFChars(stringValue, s);
return ret;
}
ã¯ã©ã¹ãã¡ãœãããæ¢ããªããŠã¯ãªããªããããå°ã é¢åã§ããå°ãªããšãJavaåŽã¯ã¡ãããšintãStringã®åã§æ±ãããšãã§ããããã«ãªããŸãã
å®è¡çµæã
intValue[5], stringValue[Hello World] sendreceive.num = 10, sendreceive.str = Hello JNI World, ret = 15
ãã ããã®æ¹æ³ã®äžæºç¹ã¯åŒã³åºãåŽã§åŒæ°ã®å€ãåæã«å€æŽããã®ã¯ãæè¿ã®ããã°ã©ãã³ã°ã¹ã¿ã€ã«ãšããŠã¯ã©ããªã®ããªããšæããŸãã
è§£æ³ãã®3ïŒåŒã³åºãå ã§æ°ããã€ã³ã¹ã¿ã³ã¹ãçæããŠè¿ã
ãã®2ã®çºå±åœ¢ã§ããåŒæ°ãšããŠãã©ã¡ãŒã¿ã¯ã©ã¹ãåãåãããã®å 容ããæ°ããã€ã³ã¹ã¿ã³ã¹ãçæããŠè¿åŽããŸãã
ããã§ããã€ã³ããŒã¯ã©ã¹ãå©çšããŠããŸãã
public static class ParamObject { private int intValue; private String stringValue; private long longValue; public ParamObject(int intValue, String stringValue) { this.intValue = intValue; this.stringValue = stringValue; } public ParamObject(int intValue, String stringValue, long longValue) { this(intValue, stringValue); this.longValue = longValue; } public int getIntValue() { return intValue; } public String getStringValue() { return stringValue; } public long getLongValue() { return longValue; } }
å©çšåŽã¯ãã¡ãã
public native ParamObject createNewParam(ParamObject param); ParamObject param = new ParamObject(5, "HelloWorld"); ParamObject result = createNewParam(param); System.out.println(String.format("result.num = %d, result.str = %s, result.ret = %d", result.getIntValue(), result.getStringValue(), result.getLongValue()));
C++åŽã¯ãã¡ãã
JNIEXPORT jobject JNICALL Java_HelloJni_createNewParam
(JNIEnv *env, jobject thisj, jobject param)
{
jclass paramClass = env->FindClass("HelloJni$ParamObject");
jmethodID getIntValueMethod, getStringValueMethod;
jmethodID paramConstructor;
getIntValueMethod = env->GetMethodID(paramClass, "getIntValue", "()I");
getStringValueMethod = env->GetMethodID(paramClass, "getStringValue", "()Ljava/lang/String;");
paramConstructor = env->GetMethodID(paramClass, "<init>", "(ILjava/lang/String;J)V");
jint intValue = env->CallIntMethod(param, getIntValueMethod);
jstring stringValue = (jstring)env->CallObjectMethod(param, getStringValueMethod);
const char *s = env->GetStringUTFChars(stringValue, NULL);
printf("intValue[%d], stringValue[%s]\n", intValue, s);
jobject ret = env->NewObject(paramClass,
paramConstructor,
intValue * 2,
env->NewStringUTF("Hello JNI World"),
15);
env->ReleaseStringUTFChars(stringValue, s);
return ret;
}
åŒæ°ParamObjectã®å 容ãèªã¿åãããã®å 容ãå ã«ïŒStringã¯ç¡èŠããŠããŸããâŠïŒæ°ããParamObjectã¯ã©ã¹ã®ã€ã³ã¹ã¿ã³ã¹ãçæããŠè¿åŽããŸãã
å®è¡çµæã¯ãã¡ãã
intValue[5], stringValue[HelloWorld] result.num = 10, result.str = Hello JNI World, result.ret = 15
ãã©ã¡ãŒã¿ã®ããã«æ»ãå€ãæã£ãŠããã®ãè¥å¹²åŸ®åŠã§ããããã£ã±ãæ°ããã€ã³ã¹ã¿ã³ã¹ãçæããŠè¿ãã¹ã¿ã€ã«ã®æ¹ãããããªãŒãšæããŸãã
å®å šãªãœãŒã¹ã³ãŒã
äžå¿ãæ²èŒããŠãããŸãã
HelloJni.java
public class HelloJni { public static void main(String[] args) { new HelloJni().execute(); } public native long writeObjectArray(Object[] objects); public native long writeResult(SendReceiveObject sendReceive); public native ParamObject createNewParam(ParamObject param); public void execute() { System.loadLibrary("HelloJni"); Object[] objects = {new Integer(5), "HelloWorld"}; long ret = writeObjectArray(objects); System.out.println(String.format("num = %d, str = %s, ret = %d", objects[0], objects[1], ret)); SendReceiveObject sendReceive = new SendReceiveObject(); sendReceive.setIntValue(5); sendReceive.setStringValue("Hello World"); ret = writeResult(sendReceive); System.out.println(String.format("sendreceive.num = %d, sendreceive.str = %s, ret = %d", sendReceive.getIntValue(), sendReceive.getStringValue(), ret)); ParamObject param = new ParamObject(5, "HelloWorld"); ParamObject result = createNewParam(param); System.out.println(String.format("result.num = %d, result.str = %s, result.ret = %d", result.getIntValue(), result.getStringValue(), result.getLongValue())); } public static class SendReceiveObject { private int intValue; private String stringValue; public void setIntValue(int intValue) { this.intValue = intValue; } public int getIntValue() { return intValue; } public void setStringValue(String stringValue) { this.stringValue = stringValue; } public String getStringValue() { return stringValue; } } public static class ParamObject { private int intValue; private String stringValue; private long longValue; public ParamObject(int intValue, String stringValue) { this.intValue = intValue; this.stringValue = stringValue; } public ParamObject(int intValue, String stringValue, long longValue) { this(intValue, stringValue); this.longValue = longValue; } public int getIntValue() { return intValue; } public String getStringValue() { return stringValue; } public long getLongValue() { return longValue; } } }
HelloJni.cpp
#include "HelloJni.h" JNIEXPORT jlong JNICALL Java_HelloJni_writeObjectArray (JNIEnv *env, jobject thisj, jobjectArray objects) { jlong ret = 15; jclass integerClass = env->FindClass("java/lang/Integer"); jmethodID integerConstructor = env->GetMethodID(integerClass, "<init>", "(I)V"); jmethodID intValueMethod = env->GetMethodID(integerClass, "intValue", "()I"); jint intValue = env->CallIntMethod(env->GetObjectArrayElement(objects, 0), intValueMethod); jstring stringValue = (jstring)env->GetObjectArrayElement(objects, 1); const char *s = env->GetStringUTFChars(stringValue, NULL); printf("第1èŠçŽ [%d], 第2èŠçŽ [%s]\n", intValue, s); env->SetObjectArrayElement(objects, 0, env->NewObject(integerClass, integerConstructor, intValue * 2)); env->SetObjectArrayElement(objects, 1, env->NewStringUTF("Hello JNI World")); env->ReleaseStringUTFChars(stringValue, s); return ret; } JNIEXPORT jlong JNICALL Java_HelloJni_writeResult (JNIEnv *env, jobject thisj, jobject sendReceive) { jlong ret = 15; jclass sendReceiveClass = env->FindClass("HelloJni$SendReceiveObject"); jmethodID getIntValueMethod, setIntValueMethod, getStringValueMethod, setStringValueMethod; getIntValueMethod = env->GetMethodID(sendReceiveClass, "getIntValue", "()I"); setIntValueMethod = env->GetMethodID(sendReceiveClass, "setIntValue", "(I)V"); getStringValueMethod = env->GetMethodID(sendReceiveClass, "getStringValue", "()Ljava/lang/String;"); setStringValueMethod = env->GetMethodID(sendReceiveClass, "setStringValue", "(Ljava/lang/String;)V"); jint intValue = env->CallIntMethod(sendReceive, getIntValueMethod); jstring stringValue = (jstring)env->CallObjectMethod(sendReceive, getStringValueMethod); const char *s = env->GetStringUTFChars(stringValue, NULL); printf("intValue[%d], stringValue[%s]\n", intValue, s); env->CallIntMethod(sendReceive, setIntValueMethod, intValue * 2); env->CallObjectMethod(sendReceive, setStringValueMethod, env->NewStringUTF("Hello JNI World")); env->ReleaseStringUTFChars(stringValue, s); return ret; } JNIEXPORT jobject JNICALL Java_HelloJni_createNewParam (JNIEnv *env, jobject thisj, jobject param) { jclass paramClass = env->FindClass("HelloJni$ParamObject"); jmethodID getIntValueMethod, getStringValueMethod; jmethodID paramConstructor; getIntValueMethod = env->GetMethodID(paramClass, "getIntValue", "()I"); getStringValueMethod = env->GetMethodID(paramClass, "getStringValue", "()Ljava/lang/String;"); paramConstructor = env->GetMethodID(paramClass, "<init>", "(ILjava/lang/String;J)V"); jint intValue = env->CallIntMethod(param, getIntValueMethod); jstring stringValue = (jstring)env->CallObjectMethod(param, getStringValueMethod); const char *s = env->GetStringUTFChars(stringValue, NULL); printf("intValue[%d], stringValue[%s]\n", intValue, s); jobject ret = env->NewObject(paramClass, paramConstructor, intValue * 2, env->NewStringUTF("Hello JNI World"), 15); env->ReleaseStringUTFChars(stringValue, s); return ret; }
ã¡ãã£ãšã§ãåèã«ãªãã°ããã®ã§ããâŠã©ãã§ããïŒ