如何将Java Map 转换为cocos2d ValueMap?
How to convert Java Map to cocos2d ValueMap?
小问题:
如何将 jobject
转换为 cocos2d::ValueMap
?
详细问题:
我有Java部分:
public class MyCallback implements MyListener {
public native void callback(Object data);
public MyCallback(){}
@Override
public void onResponse(Map<String, String> data) {
callback(data);
}
}
我想 return 将数据映射到 Cocos2d Class。所以我写道:
JNIEXPORT void JNICALL Java_com_comp_ MyCallback_ callback
(JNIEnv *env, jobject obj, jobject data) {
我得到 jobject data
那么现在如何从 jobject
得到 ValueMap
?
cocos2d::ValueMap myData = ... ???
HashMap 是必须访问才能获取内容的对象。所以,前面还有很多代码 ;)
往下看:
#include <stdio.h>
#include "jni.h"
#include "recipeNo037_PassHashMap.h"
JNIEXPORT int JNICALL Java_recipeNo037_PassHashMap_displayHashMap
(JNIEnv *env, jclass obj, jobject objarg) {
/* Get objarg's class - objarg is the one we pass from
Java */
jclass clsHashMap = (*env)->GetObjectClass(env, objarg);
/* Remember that you can alway get method signature using javap tool
> javap -s -p java.util.HashMap | grep -A 1 key
public java.util.Set<K> keySet();
descriptor: ()Ljava/util/Set;
*/
jmethodID midKeySet =
(*env)->GetMethodID(env, clsHashMap, "keySet", "()Ljava/util/Set;");
/* We have to make sure that method exists */
if (midKeySet == NULL) {
return -1; /* method not found */
}
/* Now, it's time for getting Set of keys */
jobject objKeySet = (*env)->CallObjectMethod(env, objarg, midKeySet);
/* Then, we can proceed to accessing keys */
jclass clsSet = (*env)->GetObjectClass(env, objKeySet);
/* The same story goes here - use javap to get propper descriptor
> javap -s -p java.util.Set | grep -A 1 toArray
public abstract java.lang.Object[] toArray();
descriptor: ()[Ljava/lang/Object;
*/
jmethodID midToArray =
(*env)->GetMethodID(env, clsSet, "toArray", "()[Ljava/lang/Object;");
if (midKeySet == NULL) {
return -2; /* method not found */
}
jobjectArray arrayOfKeys = (*env)->CallObjectMethod(env, objKeySet, midToArray);
int arraySize = (*env)->GetArrayLength(env, arrayOfKeys);
for (int i=0; i < arraySize; i++)
{
jstring objKey = (*env)->GetObjectArrayElement(env, arrayOfKeys, i);
const char* c_string_key = (*env)->GetStringUTFChars(env, objKey, 0);
/* Once we have key, we can retrieve value for that key */
jmethodID midGet =
(*env)->GetMethodID(env, clsHashMap, "get", "(Ljava/lang/Object;)Ljava/lang/Object;");
/* It's time to get Value for Key */
jobject objValue = (*env)->CallObjectMethod(env, objarg, midGet, objKey);
const char* c_string_value = (*env)->GetStringUTFChars(env, objValue, 0);
printf("[key, value] = [%s, %s]\n", c_string_key, c_string_value);
(*env)->ReleaseStringUTFChars(env, objKey, c_string_key);
(*env)->DeleteLocalRef(env, objKey);
(*env)->ReleaseStringUTFChars(env, objValue, c_string_value);
(*env)->DeleteLocalRef(env, objValue);
}
return 0;
}
有关完整的示例代码,请查看此处:recipeNo037
就我个人而言,我希望将 HashMap 替换为两个 Array 对象。这样,可以删除很多代码。
在此处 (recipeNo038) 查看替代方法:
这一次,我们要传递两个字符串数组。它们以这样的方式对齐,相应的索引包含来自 HashMap 的 key/value。这样,我们可以大大减少 C 中的代码,而 Java 中的开销不会那么大。
JNIEXPORT int JNICALL Java_recipeNo038_PassHashMap_displayHashMap
(JNIEnv *env, jclass obj, jobjectArray keys, jobjectArray values) {
/* We need to get array size. There is strong assumption that
keys and values have the same length
*/
int arraySize = (*env)->GetArrayLength(env, keys);
/* For all elements in array, we will convert them to C based strings
*/
for (int i=0; i < arraySize; i++)
{
/* First, we take key */
jstring objKey = (*env)->GetObjectArrayElement(env, keys, i);
const char* c_string_key = (*env)->GetStringUTFChars(env, objKey, 0);
/* Then, we take the value value */
jobject objValue = (*env)->GetObjectArrayElement(env, values, i);
const char* c_string_value = (*env)->GetStringUTFChars(env, objValue, 0);
/* And we print some info for user */
printf("[key, value] = [%s, %s]\n", c_string_key, c_string_value);
/* Make sure to release stuff */
(*env)->ReleaseStringUTFChars(env, objKey, c_string_key);
(*env)->DeleteLocalRef(env, objKey);
(*env)->ReleaseStringUTFChars(env, objValue, c_string_value);
(*env)->DeleteLocalRef(env, objValue);
}
return 0;
}
小问题:
如何将 jobject
转换为 cocos2d::ValueMap
?
详细问题:
我有Java部分:
public class MyCallback implements MyListener {
public native void callback(Object data);
public MyCallback(){}
@Override
public void onResponse(Map<String, String> data) {
callback(data);
}
}
我想 return 将数据映射到 Cocos2d Class。所以我写道:
JNIEXPORT void JNICALL Java_com_comp_ MyCallback_ callback
(JNIEnv *env, jobject obj, jobject data) {
我得到 jobject data
那么现在如何从 jobject
得到 ValueMap
?
cocos2d::ValueMap myData = ... ???
HashMap 是必须访问才能获取内容的对象。所以,前面还有很多代码 ;)
往下看:
#include <stdio.h>
#include "jni.h"
#include "recipeNo037_PassHashMap.h"
JNIEXPORT int JNICALL Java_recipeNo037_PassHashMap_displayHashMap
(JNIEnv *env, jclass obj, jobject objarg) {
/* Get objarg's class - objarg is the one we pass from
Java */
jclass clsHashMap = (*env)->GetObjectClass(env, objarg);
/* Remember that you can alway get method signature using javap tool
> javap -s -p java.util.HashMap | grep -A 1 key
public java.util.Set<K> keySet();
descriptor: ()Ljava/util/Set;
*/
jmethodID midKeySet =
(*env)->GetMethodID(env, clsHashMap, "keySet", "()Ljava/util/Set;");
/* We have to make sure that method exists */
if (midKeySet == NULL) {
return -1; /* method not found */
}
/* Now, it's time for getting Set of keys */
jobject objKeySet = (*env)->CallObjectMethod(env, objarg, midKeySet);
/* Then, we can proceed to accessing keys */
jclass clsSet = (*env)->GetObjectClass(env, objKeySet);
/* The same story goes here - use javap to get propper descriptor
> javap -s -p java.util.Set | grep -A 1 toArray
public abstract java.lang.Object[] toArray();
descriptor: ()[Ljava/lang/Object;
*/
jmethodID midToArray =
(*env)->GetMethodID(env, clsSet, "toArray", "()[Ljava/lang/Object;");
if (midKeySet == NULL) {
return -2; /* method not found */
}
jobjectArray arrayOfKeys = (*env)->CallObjectMethod(env, objKeySet, midToArray);
int arraySize = (*env)->GetArrayLength(env, arrayOfKeys);
for (int i=0; i < arraySize; i++)
{
jstring objKey = (*env)->GetObjectArrayElement(env, arrayOfKeys, i);
const char* c_string_key = (*env)->GetStringUTFChars(env, objKey, 0);
/* Once we have key, we can retrieve value for that key */
jmethodID midGet =
(*env)->GetMethodID(env, clsHashMap, "get", "(Ljava/lang/Object;)Ljava/lang/Object;");
/* It's time to get Value for Key */
jobject objValue = (*env)->CallObjectMethod(env, objarg, midGet, objKey);
const char* c_string_value = (*env)->GetStringUTFChars(env, objValue, 0);
printf("[key, value] = [%s, %s]\n", c_string_key, c_string_value);
(*env)->ReleaseStringUTFChars(env, objKey, c_string_key);
(*env)->DeleteLocalRef(env, objKey);
(*env)->ReleaseStringUTFChars(env, objValue, c_string_value);
(*env)->DeleteLocalRef(env, objValue);
}
return 0;
}
有关完整的示例代码,请查看此处:recipeNo037
就我个人而言,我希望将 HashMap 替换为两个 Array 对象。这样,可以删除很多代码。
在此处 (recipeNo038) 查看替代方法:
这一次,我们要传递两个字符串数组。它们以这样的方式对齐,相应的索引包含来自 HashMap 的 key/value。这样,我们可以大大减少 C 中的代码,而 Java 中的开销不会那么大。
JNIEXPORT int JNICALL Java_recipeNo038_PassHashMap_displayHashMap
(JNIEnv *env, jclass obj, jobjectArray keys, jobjectArray values) {
/* We need to get array size. There is strong assumption that
keys and values have the same length
*/
int arraySize = (*env)->GetArrayLength(env, keys);
/* For all elements in array, we will convert them to C based strings
*/
for (int i=0; i < arraySize; i++)
{
/* First, we take key */
jstring objKey = (*env)->GetObjectArrayElement(env, keys, i);
const char* c_string_key = (*env)->GetStringUTFChars(env, objKey, 0);
/* Then, we take the value value */
jobject objValue = (*env)->GetObjectArrayElement(env, values, i);
const char* c_string_value = (*env)->GetStringUTFChars(env, objValue, 0);
/* And we print some info for user */
printf("[key, value] = [%s, %s]\n", c_string_key, c_string_value);
/* Make sure to release stuff */
(*env)->ReleaseStringUTFChars(env, objKey, c_string_key);
(*env)->DeleteLocalRef(env, objKey);
(*env)->ReleaseStringUTFChars(env, objValue, c_string_value);
(*env)->DeleteLocalRef(env, objValue);
}
return 0;
}