NDK基础(java ,c/c++, jni之间的关系及java和c/c++之间的相互调用)

1.java,c/c++,和jni之间的关系


java和c/c++可以相互调用,是因为java虚拟机中的JNI。简单的说就是用c/c++编写一个动态链接库让Java虚拟机去调用。(在windows环境下动态链接库就是.dll文件,

在Linux下就是.so文件)

2.下面来看一个具体的例子

这个例子是来自书<<Android.NDK.Beginner-'s.Guide>>中的。我们先建一个java,类Store.这个类是用来封c/c++中的方法。我们先来看一下这个类的代码。

public class Store {
	
	static {
		System.loadLibrary("store");
	}
	
	public native void initializeStore();
	public native void finalizeStore();
	
	/**
	 * Getter/setters on primitives and objects.
	 */
	public native boolean getBoolean(String strKey)
		throws NotExistingKeyException, InvalidTypeException;
	public native void setBoolean(String strKey, boolean bValue);
	
	public native byte getByte(String strKey)
		throws NotExistingKeyException, InvalidTypeException;
	public native void setByte(String strKey, byte btValue);
	
	public native char getChar(String strKey)
		throws NotExistingKeyException, InvalidTypeException;
	public native void setChar(String strKey, char cValue);
	
	public native double getDouble(String strKey)
		throws NotExistingKeyException, InvalidTypeException;
	public native void setDouble(String strKey, double dValue);
	
	public native float getFloat(String strKey)
		throws NotExistingKeyException, InvalidTypeException;
	public native void setFloat(String strKey, float fValue);
	
	public native int getInteger(String strKey)
			throws NotExistingKeyException, InvalidTypeException;
	public native void setInteger(String strKey, int iVaule);
	
	public native long getLong(String strKey)
			throws NotExistingKeyException, InvalidTypeException;
	public native void setLong(String strKey, long lValue);
	
	public native short getShort(String strKey)
			throws NotExistingKeyException, InvalidTypeException;
	public native void setShort(String strKey, short sValue);
	
	public native String getString(String strKey)
			throws NotExistingKeyException, InvalidTypeException;
	public native void setString(String strKey, String strValue);
	
	public native Color getColor(String strKey)
			throws NotExistingKeyException, InvalidTypeException;
	public native void setColor(String strKey, Color color);
	
	/**
	 * Getter/setter on arrays
	 */
	public native boolean[] getBooleanArray(String strKey)
		throws NotExistingKeyException;
	public native void setBooleanArray(String strKey, boolean[] bArrayValue);
	
	public native byte[] getByteArray(String strKey)
			throws NotExistingKeyException;
	public native void setByteArray(String strKey, byte[] btArrayValue);
	
	public native char[] getCharArray(String strKey)
			throws NotExistingKeyException;
	public native void setCharArray(String strKey, char[] cArrayValue);
	
	public native double[] getDoubleArray(String strKey)
			throws NotExistingKeyException;
	public native void setDoubleArray(String strKey, double[] dArrayValue);
	
	public native float[] getFloatArray(String strKey)
			throws NotExistingKeyException;
	public native void setFloatArray(String strKey, float[] fArrayValue);
	
	public native int[] getIntegerArray(String strKey)
			throws NotExistingKeyException;
	public native void setIntegerArray(String strKey, int[] iArrayValue);
	
	public native long[] getLongArray(String strKey)
			throws NotExistingKeyException;
	public native void setLongArray(String strKey, long[] lArrayValue);
	
	public native short[] getShortArray(String strKey)
			throws NotExistingKeyException;
	public native void setShortArray(String strKey, short[] sArrayValue);
	
	public native String[] getStringArray(String strKey)
			throws NotExistingKeyException;
	public native void setStringArray(String strKey, String[] strArrayValue);
	
	public native Color[] getColorArray(String strKey)
			throws NotExistingKeyException;
	public native void setColorArray(String strKey, Color[] colorArray);
	
}


在一开始就加载动态链接库
<span style="color:#33cc00;">static {
		System.loadLibrary("store");//这个代码就是加载store库,就是用c/c++编译生成的libstore.so动态链接库,该文件在libs文件下面</span>
<span style="color:#33cc00;">	}</span>
每一个调用c/c++实现的方法时,前面都加上 native 关键字.c/c++我们以这个方法为例

public native boolean getBoolean(String strKey)

throws NotExistingKeyException, InvalidTypeException;

java 中的String的值到底是怎么怎么传递给c/c++的呢?前面的图说了,是JVM的JNI。JNI到底是怎么实现的呢?先看一下,8种基本类型是怎么传递

Java type

JNI type

C type

Stdint C type

boolean

Jboolean

unsigned char

uint8_t

byte

Jbyte

signed char

int8_t

char

Jchar

unsigned short

uint16_t

double

Jdouble

double

double

float

jfloat

float

float

int

jint

Int

int32_t

long

jlong

long long

int64_t

short

jshort

Short

int16_t

我们可以看出,都分别是通过JNI中的jboolean,jbyte,jchar,jdouble,jfloat,jint,jlong,jshort这些一一对应传递过去。
String是怎么传递过去呢,是通过JNI中的jstring.传递。自己写的类可以通过jobject,传递过去。下面,就建一个自己的Color类。
public class Color {
	private int miColor;
	
	public Color(String pColor) {
		super();
		miColor = android.graphics.Color.parseColor(pColor);
	}
	
	@Override
	public String toString() {
		return String.format("#%06X", miColor);
	}

}

下面有一个要用到的枚举
public enum StoreType {
	Boolean, Byte, Char, Double, Float, Integer, Long, Short,
	String, Color,
	
	BooleanArray, ByteArray, CharArray, DoubleArray, FloatArray,
	IntegerArray, LongArray, ShortArray, StringArray, ColorArray

}

上面是java中的相关代码,在c中的代码怎么和java相对接呢,先看一下c中代码
/*
 * com_packtpub_Store.h
 *
 *  Created on: May 18, 2015
 *      Author: Lioncraft
 */


#ifndef COM_PACKTPUB_STORE_H_
#define COM_PACKTPUB_STORE_H_

#include <jni.h>

#ifdef __cplusplus
extern "C" {//这个代码如果要时c++,就把接口强转成c的标准接口
#endif
/**
 * Class:	com_example_packtpub_Store
 * Method: initializeStore
 * Signature: ()V
 */
JNIEXPORT void JNICALL Java_com_example_packtpub_Store_initializeStore(JNIEnv *, jobject);

/**
 * Class:	com_example_packtpub_Store
 * Method:	finalizeStore
 * Signature:	()V
 */
JNIEXPORT	void JNICALL Java_com_example_packtpub_Store_finalizeStore(JNIEnv *, jobject);

/**
 * Class:	com_example_packtpub_Store
 * Method:	getBoolean
 * Signature: (Ljava/lang/String;)Z
 */
JNIEXPORT jboolean JNICALL Java_com_example_packtpub_Store_getBoolean(JNIEnv *, jobject, jstring);

/**
 * Class:	com_example_packtpub_Store
 * Method:	setBoolean
 * Signature: (Ljava/lang/String;Z)V
 */
JNIEXPORT void JNICALL Java_com_example_packtpub_Store_setBoolean(JNIEnv *, jobject, jstring, jboolean);

/**
 * Class:	com_example_packtpub_Store
 * Method:	getByte
 * Signature: (Ljava/lang/String;)B
 */
JNIEXPORT jbyte JNICALL Java_com_example_packtpub_Store_getByte(JNIEnv *, jobject, jstring);

/**
 * Class:	com_example_packtpub_Store
 * Method:	setByte
 * Signature: (Ljava/lang/String;B)V
 */
JNIEXPORT void JNICALL Java_com_example_packtpub_Store_setByte(JNIEnv *, jobject, jstring, jbyte);

/**
 * Class:	com_example_packtpub_Store
 * Method:	getChar
 * Signature: (Ljava/lang/String;)C
 */
JNIEXPORT jchar JNICALL Java_com_example_packtpub_Store_getChar(JNIEnv *, jobject, jstring);

/**
 * Class:	com_example_packtpub_Store
 * Method:	setChar
 * Signature: (Ljava/lang/String;C)V
 */
JNIEXPORT void JNICALL Java_com_example_packtpub_Store_setChar(JNIEnv *, jobject, jstring, jchar);

/**
 * Class:	com_example_packtpub_Store
 * Method:	getDouble
 * Signature: (Ljava/lang/String;)D
 */
JNIEXPORT jdouble JNICALL Java_com_example_packtpub_Store_getDouble(JNIEnv *, jobject, jstring);

/**
 * Class:	com_example_packtpub_Store
 * Method:	setDouble
 * Signature: (Ljava/lang/String;D)V
 */
JNIEXPORT void JNICALL Java_com_example_packtpub_Store_setDouble(JNIEnv *, jobject, jstring, jdouble);

/**
 * Class:	com_example_packtpub_Store
 * Method:	getFloat
 * Signature: (Ljava/lang/String;)F
 */
JNIEXPORT jfloat JNICALL Java_com_example_packtpub_Store_getFloat(JNIEnv *, jobject, jstring);

/**
 * Class:	com_example_packtpub_Store
 * Method:	setFloat
 * Signature: (Ljava/lang/String;F)V
 */
JNIEXPORT void JNICALL Java_com_example_packtpub_Store_setFloat(JNIEnv *, jobject, jstring, jfloat);

/**
 * Class:	com_example_packtpub_Store
 * Method:	getInteger
 * Signature: (Ljava/lang/String;)I
 */
JNIEXPORT jint JNICALL Java_com_example_packtpub_Store_getInteger(JNIEnv *, jobject, jstring);

/**
 * Class:	com_example_packtpub_Store
 * Method:	setInteger
 * Signature: (Ljava/lang/String;I)V
 */
JNIEXPORT void JNICALL Java_com_example_packtpub_Store_setInteger(JNIEnv *, jobject, jstring, jint);

/**
 * Class:	com_example_packtpub_Store
 * Method:	getLong
 * Signature: (Ljava/lang/String;)L
 */
JNIEXPORT jlong JNICALL Java_com_example_packtpub_Store_getLong(JNIEnv *, jobject, jstring);

/**
 * Class:	com_example_packtpub_Store
 * Method:	setLong
 * Signature: (Ljava/lang/String;L)V
 */
JNIEXPORT void JNICALL Java_com_example_packtpub_Store_setLong(JNIEnv *, jobject, jstring, jlong);

/**
 * Class:	com_example_packtpub_Store
 * Method:	getShort
 * Signature: (Ljava/lang/String;)S
 */
JNIEXPORT jshort JNICALL Java_com_example_packtpub_Store_getShort(JNIEnv *, jobject, jstring);

/**
 * Class:	com_example_packtpub_Store
 * Method:	setShort
 * Signature: (Ljava/lang/String;S)V
 */
JNIEXPORT void JNICALL Java_com_example_packtpub_Store_setShort(JNIEnv *, jobject, jstring, jshort);

/**
 * Class:	com_example_packtpub_Store
 * Method:	getString
 * Signature: (Ljava/lang/String;)Ljava/lang/String
 */
JNIEXPORT jstring JNICALL Java_com_example_packtpub_Store_getString(JNIEnv *, jobject, jstring);

/**
 * Class:	com_example_packtpub_Store
 * Method:	setString
 * Signature: (Ljava/lang/String;Ljava/lang/String)V
 */
JNIEXPORT void JNICALL Java_com_example_packtpub_Store_setString(JNIEnv *, jobject, jstring, jstring);

/**
 * Class:	com_example_packtpub_Store
 * Method:	getColor
 * Signature: (Ljava/lang/String;)Lcom/packtpub/Color;
 */
JNIEXPORT jobject JNICALL Java_com_example_packtpub_Store_getColor(JNIEnv *, jobject, jstring);

/**
 * Class:	com_example_packtpub_Store
 * Method:	setColor
 * Signature: (Ljava/lang/String;Lcom/packtpub/Color)V
 */
JNIEXPORT void JNICALL Java_com_example_packtpub_Store_setColor(JNIEnv *, jobject, jstring, jobject);




/**
 * Class:	com_example_packtpub_Store
 * Method:	getBooleanArray
 * Signature: (Ljava/lang/String;)[Z
 */
JNIEXPORT jbooleanArray JNICALL Java_com_example_packtpub_Store_getBooleanArray(JNIEnv *, jobject, jstring);

/**
 * Class:	com_example_packtpub_Store
 * Method:	setBooleanArray
 * Signature: (Ljava/lang/String;[Z)V
 */
JNIEXPORT void JNICALL Java_com_example_packtpub_Store_setBooleanArray(JNIEnv *, jobject, jstring, jbooleanArray);
/**
 * Class:	com_example_packtpub_Store
 * Method:	getByteArray
 * Signature: (Ljava/lang/String;)[B
 */
JNIEXPORT jbyteArray JNICALL Java_com_example_packtpub_Store_getByteArray(JNIEnv *, jobject, jstring);

/**
 * Class:	com_example_packtpub_Store
 * Method:	setByteArray
 * Signature: (Ljava/lang/String;[B)V
 */
JNIEXPORT void JNICALL Java_com_example_packtpub_Store_setByteArray(JNIEnv *, jobject, jstring, jbyteArray);

/**
 * Class:	com_example_packtpub_Store
 * Method:	getCharArray
 * Signature: (Ljava/lang/String;)[C
 */
JNIEXPORT jcharArray JNICALL Java_com_example_packtpub_Store_getCharArray(JNIEnv *, jobject, jstring);

/**
 * Class:	com_example_packtpub_Store
 * Method:	setCharArray
 * Signature: (Ljava/lang/String;[C)V
 */
JNIEXPORT void JNICALL Java_com_example_packtpub_Store_setCharArray(JNIEnv *, jobject, jstring, jcharArray);

/**
 * Class:	com_example_packtpub_Store
 * Method:	getDoubleArray
 * Signature: (Ljava/lang/String;)[D
 */
JNIEXPORT jdoubleArray JNICALL Java_com_example_packtpub_Store_getDoubleArray(JNIEnv *, jobject, jstring);

/**
 * Class:	com_example_packtpub_Store
 * Method:	setDoubleArray
 * Signature: (Ljava/lang/String;[D)V
 */
JNIEXPORT void JNICALL Java_com_example_packtpub_Store_setDoubleArray(JNIEnv *, jobject, jstring, jdoubleArray);

/**
 * Class:	com_example_packtpub_Store
 * Method:	getFloatArray
 * Signature: (Ljava/lang/String;)[F
 */
JNIEXPORT jfloatArray JNICALL Java_com_example_packtpub_Store_getFloatArray(JNIEnv *, jobject, jstring);

/**
 * Class:	com_example_packtpub_Store
 * Method:	setFloatArray
 * Signature: (Ljava/lang/String;[F)V
 */
JNIEXPORT void JNICALL Java_com_example_packtpub_Store_setFloatArray(JNIEnv *, jobject, jstring, jfloatArray);

/**
 * Class:	com_example_packtpub_Store
 * Method:	getIntegerArray
 * Signature: (Ljava/lang/String;)[I
 */
JNIEXPORT jintArray JNICALL Java_com_example_packtpub_Store_getIntegerArray(JNIEnv *, jobject, jstring);

/**
 * Class:	com_example_packtpub_Store
 * Method:	setIntegerArray
 * Signature: (Ljava/lang/String;[I)V
 */
JNIEXPORT void JNICALL Java_com_example_packtpub_Store_setIntegerArray(JNIEnv *, jobject, jstring, jintArray);

/**
 * Class:	com_example_packtpub_Store
 * Method:	getLongArray
 * Signature: (Ljava/lang/String;)[J
 */
JNIEXPORT jlongArray JNICALL Java_com_example_packtpub_Store_getLongArray(JNIEnv *, jobject, jstring);

/**
 * Class:	com_example_packtpub_Store
 * Method:	setLongArray
 * Signature: (Ljava/lang/String;[I)V
 */
JNIEXPORT void JNICALL Java_com_example_packtpub_Store_setLongArray(JNIEnv *, jobject, jstring, jlongArray);

/**
 * Class:	com_example_packtpub_Store
 * Method:	getShortArray
 * Signature: (Ljava/lang/String;)[S
 */
JNIEXPORT jshortArray JNICALL Java_com_example_packtpub_Store_getShortArray(JNIEnv *, jobject, jstring);

/**
 * Class:	com_example_packtpub_Store
 * Method:	setShortArray
 * Signature: (Ljava/lang/String;[S)V
 */
JNIEXPORT void JNICALL Java_com_example_packtpub_Store_setShortArray(JNIEnv *, jobject, jstring, jshortArray);

/**
 * Class:	com_example_packtpub_Store
 * Method:	getStringArray
 * Signature: (Ljava/lang/String;)[Ljava/lang/String;
 */
JNIEXPORT jobjectArray JNICALL Java_com_example_packtpub_Store_getStringArray(JNIEnv *, jobject, jstring);

/**
 * Class:	com_example_packtpub_Store
 * Method:	setStringArray
 * Signature: (Ljava/lang/String;[Ljava/lang/String;)V
 */
JNIEXPORT void JNICALL Java_com_example_packtpub_Store_setShortArray(JNIEnv *, jobject, jstring, jobjectArray);

/**
 * Class:	com_example_packtpub_Store
 * Method:	getColorArray
 * Signature: (Ljava/lang/String;)[Lcom/packtpub/Color;
 */
JNIEXPORT jobjectArray JNICALL Java_com_example_packtpub_Store_getColorArray(JNIEnv *, jobject, jstring);

/**
 * Class:	com_example_packtpub_Store
 * Method:	setColorArray
 * Signature: (Ljava/lang/String;[Lcom/packtpub/Color;)V
 */
JNIEXPORT void JNICALL Java_com_example_packtpub_Store_setColorArray(JNIEnv *, jobject, jstring, jobjectArray);



#ifdef __cplusplus
}
#endif

#endif /* COM_PACKTPUB_STORE_H_ */

这段代码就是对c++环境的处理

<span style="color:#009900;">#ifdef __cplusplus
extern "C" {//这个代码如果要时c++,就把接口强转成c的标准接口
#endif</span>

我们还以第一个函数为例
<pre name="code" class="cpp" style="font-size: 11px;">JNIEXPORT jboolean JNICALL Java_com_example_packtpub_Store_getBoolean(JNIEnv *, jobject, jstring);

JNIEXPORT 和 JNICALL 都是JNI的导出标志,下面我们来看一下函数名的规则:

Java_com_example_packtpub_Store_getBoolean  Java就是表示语言,基本固定不变,下面是包的名字com.example.packtpub,紧跟着是类名Store,

最后函数名getBoolean,中间全部用下划线分开。

参数(JNIEnv *, jobject,jstring),可以看到,从java那边传过来只有jsting一个参数,另外两个都是JNI默认传过来的。即使,java中是void函数,在c中也是

有JNIEnv*和jobject 这两个参数。JNIEnv*是JVM中的指针,另外,一个我也不清楚。希望知道的朋友可以告诉一下,谢谢!

下面,看以下c中的具体实现,代码如下

/*
 * com_packtpub_Store.c
 *
 *  Created on: May 18, 2015
 *      Author: Lioncraft
 */

#include "com_packtpub_Store.h"
#include <stdint.h>
#include <string.h>
#include "Store.h"

/**
 * Contains the unique store instance in a static variable created
 * when library is loaded.
 */
static Store mStore = {{}, 0};

/**
 * Initialization/Finialization.
 */
JNIEXPORT void JNICALL Java_com_example_packtpub_Store_initializeStore(JNIEnv *pEnv, jobject pThis)
{
	mStore.mLength = 0;
}

JNIEXPORT void JNICALL Java_com_example_packtpub_Store_finalizeStore(JNIEnv *pEnv, jobject pThis)
{
	StoreEntry* lEntry = mStore.mEntries;
	StoreEntry* lEntryEnd = lEntry + mStore.mLength;


	// Releases every entry in the store.
	while (lEntry < lEntryEnd) {
		free(lEntry->mKey);
		releaseEntryValue(pEnv, lEntry);

		++lEntry;
	}
	mStore.mLength = 0;
}

/*
 * Getter/setter on primitives and objects.
 */
JNIEXPORT jboolean JNICALL Java_com_example_packtpub_Store_getBoolean(JNIEnv *pEnv, jobject pThis, jstring pKey)
{
	StoreEntry* lEntry = findEntry(pEnv, &mStore, pKey, NULL);
	if (isEntryValid(pEnv, lEntry, StoreType_Boolean)) {
		return lEntry->mValue.mBoolean;
	} else {
		return 0;
	}
}

JNIEXPORT void JNICALL Java_com_example_packtpub_Store_setBoolean(JNIEnv *pEnv, jobject pThis, jstring pKey, jboolean pBoolean)
{
	// Creates a new entry (or finds it if it already exists) in the
	    // store.
	StoreEntry* lEntry = allocateEntry(pEnv, &mStore, pKey);
	if (lEntry != NULL) {
		// Updates entry content with the requested data.
		lEntry->mType = StoreType_Boolean;
		lEntry->mValue.mBoolean = pBoolean;
	}
}

JNIEXPORT jbyte JNICALL Java_com_example_packtpub_Store_getByte(JNIEnv *pEnv, jobject pThis, jstring pKey)
{
	StoreEntry* lEntry = findEntry(pEnv, &mStore, pKey, NULL);
	if (isEntryValid(pEnv, lEntry, StoreType_Byte)) {
		return lEntry->mValue.mByte;
	} else {
		return 0;
	}
}

JNIEXPORT void JNICALL Java_com_example_packtpub_Store_setByte(JNIEnv *pEnv, jobject pThis, jstring pKey, jbyte pByte)
{
	// Creates a new entry (or finds it if it already exists) in the
	    // store.
	StoreEntry* lEntry = allocateEntry(pEnv, &mStore, pKey);
	if (lEntry != NULL) {
		// Updates entry content with the requested data.
		lEntry->mType = StoreType_Byte;
		lEntry->mValue.mByte = pByte;
	}
}

JNIEXPORT jchar JNICALL Java_com_example_packtpub_Store_getChar(JNIEnv *pEnv, jobject pThis, jstring pKey)
{
	StoreEntry* lEntry = findEntry(pEnv, &mStore, pKey, NULL);
	if (isEntryValid(pEnv, lEntry, StoreType_Char)) {
		return lEntry->mValue.mChar;
	} else {
		return 0;
	}
}

JNIEXPORT void JNICALL Java_com_example_packtpub_Store_setChar(JNIEnv *pEnv, jobject pThis, jstring pKey, jchar pChar)
{
	// Creates a new entry (or finds it if it already exists) in the
	    // store.
	StoreEntry* lEntry = allocateEntry(pEnv, &mStore, pKey);
	if (lEntry != NULL) {
		// Updates entry content with the requested data.
		lEntry->mType = StoreType_Char;
		lEntry->mValue.mChar = pChar;
	}
}

JNIEXPORT jdouble JNICALL Java_com_example_packtpub_Store_getDouble(JNIEnv *pEnv, jobject pThis, jstring pKey)
{
	StoreEntry* lEntry = findEntry(pEnv, &mStore, pKey, NULL);
	if (isEntryValid(pEnv, lEntry, StoreType_Double)) {
		return lEntry->mValue.mDouble;
	} else {
		return 0;
	}
}

JNIEXPORT void JNICALL Java_com_example_packtpub_Store_setDouble(JNIEnv *pEnv, jobject pThis, jstring pKey, jdouble pDouble)
{
	// Creates a new entry (or finds it if it already exists) in the
	    // store.
	StoreEntry* lEntry = allocateEntry(pEnv, &mStore, pKey);
	if (lEntry != NULL) {
		// Updates entry content with the requested data.
		lEntry->mType = StoreType_Double;
		lEntry->mValue.mDouble = pDouble;
	}
}

JNIEXPORT jfloat JNICALL Java_com_example_packtpub_Store_getFloat(JNIEnv *pEnv, jobject pThis, jstring pKey)
{
	StoreEntry* lEntry = findEntry(pEnv, &mStore, pKey, NULL);
	if (isEntryValid(pEnv, lEntry, StoreType_Float)) {
		return lEntry->mValue.mFloat;
	} else {
		return 0;
	}
}

JNIEXPORT void JNICALL Java_com_example_packtpub_Store_setFloat(JNIEnv *pEnv, jobject pThis, jstring pKey, jfloat pFloat)
{
	// Creates a new entry (or finds it if it already exists) in the
	    // store.
	StoreEntry* lEntry = allocateEntry(pEnv, &mStore, pKey);
	if (lEntry != NULL) {
		// Updates entry content with the requested data.
		lEntry->mType = StoreType_Float;
		lEntry->mValue.mFloat = pFloat;
	}
}

JNIEXPORT jint JNICALL Java_com_example_packtpub_Store_getInteger(JNIEnv *pEnv, jobject pThis, jstring pKey)
{
	StoreEntry* lEntry = findEntry(pEnv, &mStore, pKey, NULL);
	if (isEntryValid(pEnv, lEntry, StoreType_Integer)) {
		return lEntry->mValue.mInteger;
	} else {
		return 0;
	}
}

JNIEXPORT void JNICALL Java_com_example_packtpub_Store_setInteger(JNIEnv *pEnv, jobject pThis, jstring pKey, jint pInteger)
{
	// Creates a new entry (or finds it if it already exists) in the
	    // store.
	StoreEntry* lEntry = allocateEntry(pEnv, &mStore, pKey);
	if (lEntry != NULL) {
		// Updates entry content with the requested data.
		lEntry->mType = StoreType_Integer;
		lEntry->mValue.mInteger = pInteger;
	}
}

JNIEXPORT jlong JNICALL Java_com_example_packtpub_Store_getLong(JNIEnv *pEnv, jobject pThis, jstring pKey)
{
	StoreEntry* lEntry = findEntry(pEnv, &mStore, pKey, NULL);
	if (isEntryValid(pEnv, lEntry, StoreType_Long)) {
		return lEntry->mValue.mLong;
	} else {
		return 0;
	}
}

JNIEXPORT void JNICALL Java_com_example_packtpub_Store_setLong(JNIEnv *pEnv, jobject pThis, jstring pKey, jlong pLong)
{
	// Creates a new entry (or finds it if it already exists) in the
	    // store.
	StoreEntry* lEntry = allocateEntry(pEnv, &mStore, pKey);
	if (lEntry != NULL) {
		// Updates entry content with the requested data.
		lEntry->mType = StoreType_Long;
		lEntry->mValue.mLong = pLong;
	}
}

JNIEXPORT jshort JNICALL Java_com_example_packtpub_Store_getShort(JNIEnv *pEnv, jobject pThis, jstring pKey)
{
	StoreEntry* lEntry = findEntry(pEnv, &mStore, pKey, NULL);
	if (isEntryValid(pEnv, lEntry, StoreType_Short)) {
		return lEntry->mValue.mShort;
	} else {
		return 0;
	}
}

JNIEXPORT void JNICALL Java_com_example_packtpub_Store_setShort(JNIEnv *pEnv, jobject pThis, jstring pKey, jshort pShort)
{
	// Creates a new entry (or finds it if it already exists) in the
	    // store.
	StoreEntry* lEntry = allocateEntry(pEnv, &mStore, pKey);
	if (lEntry != NULL) {
		// Updates entry content with the requested data.
		lEntry->mType = StoreType_Short;
		lEntry->mValue.mShort = pShort;
	}
}

JNIEXPORT jstring JNICALL Java_com_example_packtpub_Store_getString(JNIEnv *pEnv, jobject pThis, jstring pKey)
{
	StoreEntry* lEntry = findEntry(pEnv, &mStore, pKey, NULL);
	if (isEntryValid(pEnv, lEntry, StoreType_String)) {
		//// Converts a C string into a Java String.
		return (*pEnv)->NewStringUTF(pEnv, lEntry->mValue.mString);
	} else {
		return NULL;
	}
}

JNIEXPORT void JNICALL Java_com_example_packtpub_Store_setString(JNIEnv *pEnv, jobject pThis, jstring pKey, jstring pString)
{
	// Turns the Java string into a temporary C string.
	    // GetStringUTFChars() is used here as an example but
	    // Here, GetStringUTFChars() to show
	    // the way it works. But as what we want is only a copy,
	    // GetBooleanArrayRegion() would be be more efficient.
	const char* lStringTmp = (*pEnv)->GetStringUTFChars(pEnv, pString, NULL);
	if (lStringTmp == NULL) {
		return;
	}
	StoreEntry* lEntry = allocateEntry(pEnv, &mStore, pKey);
	if (lEntry != NULL) {

		lEntry->mType = StoreType_String;
		// Copy the temporary C string into its dynamically allocated
		        // final location. Then releases the temporary string.
		        // Malloc return value should theoretically be checked...
		jsize lStringLength = (*pEnv)->GetStringUTFLength(pEnv, pString);
		lEntry->mValue.mString = (char*) malloc(sizeof(char) * (lStringLength + 1));
		strcpy(lEntry->mValue.mString, lStringTmp);
	}
}

JNIEXPORT jobject JNICALL Java_com_example_packtpub_Store_getColor(JNIEnv *pEnv, jobject pThis, jstring pKey)
{

	  StoreEntry* lEntry = findEntry(pEnv, &mStore, pKey, NULL);
	    if (isEntryValid(pEnv, lEntry, StoreType_Color)) {
	        // Returns a Java object.
	        return lEntry->mValue.mColor;
	    } else {
	        return NULL;
	    }

}

JNIEXPORT void JNICALL Java_com_example_packtpub_Store_setColor(JNIEnv *pEnv, jobject pThis, jstring pKey, jobject pColor)
{
	// The Java Color is going to be stored on the native side.
	    // Need to keep a global reference to avoid a potential
	    // garbage collection after method returns.
	jobject lColor = (*pEnv)->NewGlobalRef(pEnv, pColor);
	if (lColor == NULL) {
		return;
	}

	// Save the Color reference in the store.
	StoreEntry * lEntry = allocateEntry(pEnv, &mStore, pKey);
	if (lEntry != NULL) {
		lEntry->mType = StoreType_Color;
		lEntry->mValue.mColor = lColor;
	} else {
		(*pEnv)->DeleteGlobalRef(pEnv, lColor);
	}
}

/*
 * Getter/setter on arrays.
 */

JNIEXPORT jbooleanArray JNICALL Java_com_example_packtpub_Store_getBooleanArray(JNIEnv *pEnv, jobject pThis, jstring pKey)
{

	StoreEntry* lEntry = findEntry(pEnv, &mStore, pKey, NULL);
	if (isEntryValid(pEnv, lEntry, StoreType_BooleanArray)) {
		jbooleanArray lJavaArray = (*pEnv)->NewBooleanArray(pEnv, lEntry->mLength);

		if (lJavaArray == NULL) {
			return NULL;
		}

		(*pEnv)->SetBooleanArrayRegion(pEnv, lJavaArray, 0, lEntry->mLength, lEntry->mValue.mBooleanArray);

		return lJavaArray;
	} else {
		return NULL;
	}
}

JNIEXPORT void JNICALL Java_com_example_packtpub_Store_setBooleanArray(JNIEnv *pEnv, jobject pThis, jstring pKey, jbooleanArray pBooleanArray)
{
	// Retrieves array content. Here, Get<Primitive>ArrayElements()
	// is used to show the way it works. But as what we want is only
	// a copy, GetBooleanArrayRegion() would be be more efficient.

	jboolean* lArrayTmp = (*pEnv)->GetBooleanArrayElements(pEnv, pBooleanArray, NULL);
	if (lArrayTmp == NULL) {
		return ;
	}

	// Finds/creates an entry in the store and fills its content.
	StoreEntry* lEntry = allocateEntry(pEnv, &mStore, pKey);

	if (lEntry != NULL) {
		lEntry->mType = StoreType_BooleanArray;
		// Allocates a new C buffer which is going to hold a copy of
		// the Java array.
		lEntry->mLength = (*pEnv)->GetArrayLength(pEnv, pBooleanArray);
		size_t lBufferLength = lEntry->mLength * sizeof(uint8_t);
		//Malloc return value should theoretically be checked...
		lEntry->mValue.mBooleanArray = (uint8_t*) malloc(lBufferLength);
		memcpy(lEntry->mValue.mBooleanArray, lArrayTmp, lBufferLength);
	}

	 // We have performed any modification on the array and thus do
	    // not plan to send any modified data back to Java. So uses
	    // JNI_ABORT flag for efficiency purpose.
	(*pEnv)->ReleaseBooleanArrayElements(pEnv, pBooleanArray, lArrayTmp, JNI_ABORT);
}

JNIEXPORT jbyteArray JNICALL Java_com_example_packtpub_Store_getByteArray(JNIEnv *pEnv, jobject pThis, jstring pKey)
{

	StoreEntry* lEntry = findEntry(pEnv, &mStore, pKey, NULL);
	if (isEntryValid(pEnv, lEntry, StoreType_ByteArray)) {
		jbyteArray lJavaArray = (*pEnv)->NewByteArray(pEnv, lEntry->mLength);

		if (lJavaArray == NULL) {
			return NULL;
		}

		(*pEnv)->SetByteArrayRegion(pEnv, lJavaArray, 0, lEntry->mLength, lEntry->mValue.mByteArray);

		return lJavaArray;
	} else {
		return NULL;
	}
}

JNIEXPORT void JNICALL Java_com_example_packtpub_Store_setByteArray(JNIEnv *pEnv, jobject pThis, jstring pKey, jbyteArray pByteArray)
{
	// Allocates a C array with the same size as the Java array.
	jsize lLength = (*pEnv)->GetArrayLength(pEnv, pByteArray);
	int8_t* lArray = (int8_t*) malloc(lLength * sizeof(int8_t));
	 // Copies Java array content directly in this new C array.
	(*pEnv)->GetByteArrayRegion(pEnv, pByteArray, 0, lLength, lArray);

	  // GetByteArrayRegion() does not return a value. Thus exceptions
	    // need to be checked explicitely (here, an IndexOutOfBound
	    // could theoretically occur).
	if ((*pEnv)->ExceptionCheck(pEnv)) {
		free(lArray);
		return;
	}

	 // Creates a new store entry containing the C array.
	StoreEntry* lEntry = allocateEntry(pEnv, &mStore, pKey);

	if (lEntry != NULL) {
		lEntry->mType = StoreType_ByteArray;
		lEntry->mLength = lLength;
		lEntry->mValue.mByteArray = lArray;
	} else {
		// If an error occurs, releases what has been allocated.
		free(lArray);
		return;
	}
}

JNIEXPORT jcharArray JNICALL Java_com_example_packtpub_Store_getCharArray(JNIEnv *pEnv, jobject pThis, jstring pKey)
{

	StoreEntry* lEntry = findEntry(pEnv, &mStore, pKey, NULL);
	if (isEntryValid(pEnv, lEntry, StoreType_CharArray)) {
		jcharArray lJavaArray = (*pEnv)->NewCharArray(pEnv, lEntry->mLength);

		if (lJavaArray == NULL) {
			return NULL;
		}

		(*pEnv)->SetCharArrayRegion(pEnv, lJavaArray, 0, lEntry->mLength, lEntry->mValue.mCharArray);

		return lJavaArray;
	} else {
		return NULL;
	}
}

JNIEXPORT void JNICALL Java_com_example_packtpub_Store_setCharArray(JNIEnv *pEnv, jobject pThis, jstring pKey, jcharArray pCharArray)
{
	// Allocates a C array with the same size as the Java array.
	jsize lLength = (*pEnv)->GetArrayLength(pEnv, pCharArray);
	int16_t* lArray = (int16_t*) malloc(lLength * sizeof(int16_t));
	 // Copies Java array content directly in this new C array.
	(*pEnv)->GetByteArrayRegion(pEnv, pCharArray, 0, lLength, lArray);

	  // GetByteArrayRegion() does not return a value. Thus exceptions
	    // need to be checked explicitely (here, an IndexOutOfBound
	    // could theoretically occur).
	if ((*pEnv)->ExceptionCheck(pEnv)) {
		free(lArray);
		return;
	}

	 // Creates a new store entry containing the C array.
	StoreEntry* lEntry = allocateEntry(pEnv, &mStore, pKey);

	if (lEntry != NULL) {
		lEntry->mType = StoreType_CharArray;
		lEntry->mLength = lLength;
		lEntry->mValue.mCharArray = lArray;
	} else {
		// If an error occurs, releases what has been allocated.
		free(lArray);
		return;
	}
}

JNIEXPORT jdoubleArray JNICALL Java_com_example_packtpub_Store_getDoubleArray(JNIEnv *pEnv, jobject pThis, jstring pKey)
{

	StoreEntry* lEntry = findEntry(pEnv, &mStore, pKey, NULL);
	if (isEntryValid(pEnv, lEntry, StoreType_DoubleArray)) {
		jdoubleArray lJavaArray = (*pEnv)->NewDoubleArray(pEnv, lEntry->mLength);

		if (lJavaArray == NULL) {
			return NULL;
		}

		(*pEnv)->SetDoubleArrayRegion(pEnv, lJavaArray, 0, lEntry->mLength, lEntry->mValue.mDoubleArray);

		return lJavaArray;
	} else {
		return NULL;
	}
}

JNIEXPORT void JNICALL Java_com_example_packtpub_Store_setDoubleArray(JNIEnv *pEnv, jobject pThis, jstring pKey, jdoubleArray pDoubleArray)
{
	// Allocates a C array with the same size as the Java array.
	jsize lLength = (*pEnv)->GetArrayLength(pEnv, pDoubleArray);
	double* lArray = (double*) malloc(lLength * sizeof(double));
	 // Copies Java array content directly in this new C array.
	(*pEnv)->GetDoubleArrayRegion(pEnv, pDoubleArray, 0, lLength, lArray);

	  // GetByteArrayRegion() does not return a value. Thus exceptions
	    // need to be checked explicitely (here, an IndexOutOfBound
	    // could theoretically occur).
	if ((*pEnv)->ExceptionCheck(pEnv)) {
		free(lArray);
		return;
	}

	 // Creates a new store entry containing the C array.
	StoreEntry* lEntry = allocateEntry(pEnv, &mStore, pKey);

	if (lEntry != NULL) {
		lEntry->mType = StoreType_DoubleArray;
		lEntry->mLength = lLength;
		lEntry->mValue.mDoubleArray = lArray;
	} else {
		// If an error occurs, releases what has been allocated.
		free(lArray);
		return;
	}
}

JNIEXPORT jfloatArray JNICALL Java_com_example_packtpub_Store_getFloatArray(JNIEnv *pEnv, jobject pThis, jstring pKey)
{

	StoreEntry* lEntry = findEntry(pEnv, &mStore, pKey, NULL);
	if (isEntryValid(pEnv, lEntry, StoreType_FloatArray)) {
		jfloatArray lJavaArray = (*pEnv)->NewFloatArray(pEnv, lEntry->mLength);

		if (lJavaArray == NULL) {
			return NULL;
		}

		(*pEnv)->SetFloatArrayRegion(pEnv, lJavaArray, 0, lEntry->mLength, lEntry->mValue.mFloatArray);

		return lJavaArray;
	} else {
		return NULL;
	}
}

JNIEXPORT void JNICALL Java_com_example_packtpub_Store_setFloatArray(JNIEnv *pEnv, jobject pThis, jstring pKey, jfloatArray pFloatArray)
{
	// Allocates a C array with the same size as the Java array.
	jsize lLength = (*pEnv)->GetArrayLength(pEnv, pFloatArray);
	float* lArray = (float*) malloc(lLength * sizeof(float));
	 // Copies Java array content directly in this new C array.
	(*pEnv)->GetFloatArrayRegion(pEnv, pFloatArray, 0, lLength, lArray);

	  // GetByteArrayRegion() does not return a value. Thus exceptions
	    // need to be checked explicitely (here, an IndexOutOfBound
	    // could theoretically occur).
	if ((*pEnv)->ExceptionCheck(pEnv)) {
		free(lArray);
		return;
	}

	 // Creates a new store entry containing the C array.
	StoreEntry* lEntry = allocateEntry(pEnv, &mStore, pKey);

	if (lEntry != NULL) {
		lEntry->mType = StoreType_FloatArray;
		lEntry->mLength = lLength;
		lEntry->mValue.mFloatArray = lArray;
	} else {
		// If an error occurs, releases what has been allocated.
		free(lArray);
		return;
	}
}

JNIEXPORT jintArray JNICALL Java_com_example_packtpub_Store_getIntegerArray(JNIEnv *pEnv, jobject pThis, jstring pKey)
{

	StoreEntry* lEntry = findEntry(pEnv, &mStore, pKey, NULL);
	if (isEntryValid(pEnv, lEntry, StoreType_IntegerArray)) {
		jintArray lJavaArray = (*pEnv)->NewIntArray(pEnv, lEntry->mLength);

		if (lJavaArray == NULL) {
			return NULL;
		}

		(*pEnv)->SetIntArrayRegion(pEnv, lJavaArray, 0, lEntry->mLength, lEntry->mValue.mIntegerArray);

		return lJavaArray;
	} else {
		return NULL;
	}
}

JNIEXPORT void JNICALL Java_com_example_packtpub_Store_setIntegerArray(JNIEnv *pEnv, jobject pThis, jstring pKey, jintArray pIntegerArray)
{
	// Allocates a C array with the same size as the Java array.
	jsize lLength = (*pEnv)->GetArrayLength(pEnv, pIntegerArray);
	int32_t* lArray = (int32_t*) malloc(lLength * sizeof(int32_t));
	 // Copies Java array content directly in this new C array.
	(*pEnv)->GetIntArrayRegion(pEnv, pIntegerArray, 0, lLength, lArray);

	  // GetByteArrayRegion() does not return a value. Thus exceptions
	    // need to be checked explicitely (here, an IndexOutOfBound
	    // could theoretically occur).
	if ((*pEnv)->ExceptionCheck(pEnv)) {
		free(lArray);
		return;
	}

	 // Creates a new store entry containing the C array.
	StoreEntry* lEntry = allocateEntry(pEnv, &mStore, pKey);

	if (lEntry != NULL) {
		lEntry->mType = StoreType_IntegerArray;
		lEntry->mLength = lLength;
		lEntry->mValue.mIntegerArray = lArray;
	} else {
		// If an error occurs, releases what has been allocated.
		free(lArray);
		return;
	}
}


JNIEXPORT jlongArray JNICALL Java_com_example_packtpub_Store_getLongArray(JNIEnv *pEnv, jobject pThis, jstring pKey)
{

	StoreEntry* lEntry = findEntry(pEnv, &mStore, pKey, NULL);
	if (isEntryValid(pEnv, lEntry, StoreType_LongArray)) {
		jlongArray lJavaArray = (*pEnv)->NewLongArray(pEnv, lEntry->mLength);

		if (lJavaArray == NULL) {
			return NULL;
		}

		(*pEnv)->SetLongArrayRegion(pEnv, lJavaArray, 0, lEntry->mLength, lEntry->mValue.mLongArray);

		return lJavaArray;
	} else {
		return NULL;
	}
}

JNIEXPORT void JNICALL Java_com_example_packtpub_Store_setLongArray(JNIEnv *pEnv, jobject pThis, jstring pKey, jlongArray pLongArray)
{
	// Allocates a C array with the same size as the Java array.
	jsize lLength = (*pEnv)->GetArrayLength(pEnv, pLongArray);
	int64_t* lArray = (int64_t*) malloc(lLength * sizeof(int64_t));
	 // Copies Java array content directly in this new C array.
	(*pEnv)->GetIntArrayRegion(pEnv, pLongArray, 0, lLength, lArray);

	  // GetByteArrayRegion() does not return a value. Thus exceptions
	    // need to be checked explicitely (here, an IndexOutOfBound
	    // could theoretically occur).
	if ((*pEnv)->ExceptionCheck(pEnv)) {
		free(lArray);
		return;
	}

	 // Creates a new store entry containing the C array.
	StoreEntry* lEntry = allocateEntry(pEnv, &mStore, pKey);

	if (lEntry != NULL) {
		lEntry->mType = StoreType_LongArray;
		lEntry->mLength = lLength;
		lEntry->mValue.mLongArray = lArray;
	} else {
		// If an error occurs, releases what has been allocated.
		free(lArray);
		return;
	}
}


JNIEXPORT jshortArray JNICALL Java_com_example_packtpub_Store_getShortArray(JNIEnv *pEnv, jobject pThis, jstring pKey)
{

	StoreEntry* lEntry = findEntry(pEnv, &mStore, pKey, NULL);
	if (isEntryValid(pEnv, lEntry, StoreType_ShortArray)) {
		jshortArray lJavaArray = (*pEnv)->NewShortArray(pEnv, lEntry->mLength);

		if (lJavaArray == NULL) {
			return NULL;
		}

		(*pEnv)->SetShortArrayRegion(pEnv, lJavaArray, 0, lEntry->mLength, lEntry->mValue.mShortArray);

		return lJavaArray;
	} else {
		return NULL;
	}
}

JNIEXPORT void JNICALL Java_com_example_packtpub_Store_setShortArray(JNIEnv *pEnv, jobject pThis, jstring pKey, jshortArray pShortArray)
{
	// Allocates a C array with the same size as the Java array.
	jsize lLength = (*pEnv)->GetArrayLength(pEnv, pShortArray);
	int16_t* lArray = (int16_t*) malloc(lLength * sizeof(int16_t));
	 // Copies Java array content directly in this new C array.
	(*pEnv)->GetIntArrayRegion(pEnv, pShortArray, 0, lLength, lArray);

	  // GetByteArrayRegion() does not return a value. Thus exceptions
	    // need to be checked explicitely (here, an IndexOutOfBound
	    // could theoretically occur).
	if ((*pEnv)->ExceptionCheck(pEnv)) {
		free(lArray);
		return;
	}

	 // Creates a new store entry containing the C array.
	StoreEntry* lEntry = allocateEntry(pEnv, &mStore, pKey);

	if (lEntry != NULL) {
		lEntry->mType = StoreType_ShortArray;
		lEntry->mLength = lLength;
		lEntry->mValue.mShortArray = lArray;
	} else {
		// If an error occurs, releases what has been allocated.
		free(lArray);
		return;
	}
}


JNIEXPORT jobjectArray JNICALL Java_com_example_packtpub_Store_getStringArray(JNIEnv *pEnv, jobject pThis, jstring pKey)
{

	StoreEntry* lEntry = findEntry(pEnv, &mStore, pKey, NULL);
	if (isEntryValid(pEnv, lEntry, StoreType_StringArray)) {
		// An array of String in Java is in fact an array of object.
		jclass lStringClass = (*pEnv)->FindClass(pEnv, "java/lang/String");
		if (lStringClass == NULL) {
			return NULL;
		}
		jobjectArray lJavaArray = (*pEnv)->NewObjectArray(pEnv, lEntry->mLength, lStringClass, NULL);

		if (lJavaArray == NULL) {
			return NULL;
		}

		// Creates a new Java String object for each C string stored.
		        // Reference to the String can be removed right after it is
		        // added to the Java array, as the latter holds a reference
		        // to the String object.
		int32_t i;
		for (i = 0; i < lEntry->mLength; ++i) {
			jstring lString = (*pEnv)->NewStringUTF(pEnv, lEntry->mValue.mStringArray[i]);
			if (lString == NULL) {
				return NULL;
			}

			 // Puts the new string in the array. Exception are
			 // checked because of SetObjectArrayElement() (can raise
			 // an ArrayIndexOutOfBounds or ArrayStore Exception).
			 // If one occurs, any object created here will be freed
			 // as they are all referenced locally only.
			(*pEnv)->SetObjectArrayElement(pEnv, lJavaArray, i, lString);
			// Note that DeleteLocalRef() can still be called safely
			            // even if an exception is raised.
			(*pEnv)->DeleteLocalRef(pEnv, lString);
			if ((*pEnv)->ExceptionCheck(pEnv)) {
				return NULL;
			}
		}

		return lJavaArray;
	} else {
		return NULL;
	}
}

JNIEXPORT void JNICALL Java_com_example_packtpub_Store_setStringArray(JNIEnv *pEnv, jobject pThis, jstring pKey, jobjectArray pStringArray)
{
	// Allocates a C array with the same size as the Java array.
	jsize lLength = (*pEnv)->GetArrayLength(pEnv, pStringArray);
	char** lArray = (char**) malloc(lLength * sizeof(char*));

	// Fills the C array with a copy of each input Java string.
	int32_t i,j;
	for (i = 0; i < lLength; ++i) {
		// Gets the current Java String from the input Java array.
		// Object arrays can be accessed element by element only.
		jstring lString = (*pEnv)->GetObjectArrayElement(pEnv, pStringArray, i);
		if ((*pEnv)->ExceptionCheck(pEnv)) {
			for (j = 0; j < i; ++j) {
				free(lArray[j]);
			}
			free(lArray);
			return;
		}

		jsize lStringLength = (*pEnv)->GetStringUTFLength(pEnv, lString);
		// Malloc return value should theoretically be checked...
		lArray[i] = (char*) malloc(sizeof(char) * (lStringLength + 1));
		// Directly copies the Java String into our new C buffer.
		// This is usually faster than GetStringUTFChars() which
		// requires copying manually.
		(*pEnv)->GetStringUTFRegion(pEnv, lString, 0, lStringLength, lArray[i]);
		if ((*pEnv)->ExceptionCheck(pEnv)) {
			for (j = 0; j < i; ++j) {
				free(lArray[j]);
			}
			free(lArray);
			return;
		}
		// No need to keep a reference to the Java string anymore.
		(*pEnv)->DeleteLocalRef(pEnv, lString);

	}

	// Creates a new entry with the new String array.
	StoreEntry* lEntry = allocateEntry(pEnv, &mStore, pKey);

	if (lEntry != NULL) {
		lEntry->mType = StoreType_StringArray;
		lEntry->mLength = lLength;
		lEntry->mValue.mStringArray = lArray;
	} else {
		// If an error occurs, releases what has been allocated.
		for (j = 0; j < lLength; ++j) {
			free(lArray[j]);
		}
		free(lArray);
		return;
	}
}

JNIEXPORT jobjectArray JNICALL Java_com_example_packtpub_Store_getColorArray(JNIEnv *pEnv, jobject pThis, jstring pKey)
{

	StoreEntry* lEntry = findEntry(pEnv, &mStore, pKey, NULL);
	if (isEntryValid(pEnv, lEntry, StoreType_ColorArray)) {
		// Creates a new array with objects of type Id.
		jclass lColorClass = (*pEnv)->FindClass(pEnv, "com/example/packtpub/Color");
		if (lColorClass == NULL) {
			return NULL;
		}
		jobjectArray lJavaArray = (*pEnv)->NewObjectArray(pEnv, lEntry->mLength, lColorClass, NULL);

		if (lJavaArray == NULL) {
			return NULL;
		}

		// Fills the array with the Color objects stored on the native
		        // side, which keeps a global reference to them. So no need
		        // to delete or create any reference here.
		int32_t i;
		for (i = 0; i < lEntry->mLength; ++i) {

			(*pEnv)->SetObjectArrayElement(pEnv, lJavaArray, i, lEntry->mValue.mColorArray[i]);

			if ((*pEnv)->ExceptionCheck(pEnv)) {
				return NULL;
			}
		}

		return lJavaArray;
	} else {
		return NULL;
	}
}

JNIEXPORT void JNICALL Java_com_example_packtpub_Store_setColorArray(JNIEnv *pEnv, jobject pThis, jstring pKey, jobjectArray pColorArray)
{
	// Allocates a C array with the same size as the Java array.
	jsize lLength = (*pEnv)->GetArrayLength(pEnv, pColorArray);
	jobject* lArray = (jobject*) malloc(lLength * sizeof(jobject));

	// Fills the C array with a copy of each input Java object.
	int32_t i,j;
	for (i = 0; i < lLength; ++i) {
		// Gets the current Java Color from the input Java array.
		// Object arrays can be accessed element by element only.
		jobject llocalColor = (*pEnv)->GetObjectArrayElement(pEnv, pColorArray, i);
		if (NULL == llocalColor) {
			for (j = 0; j < i; ++j) {
				(*pEnv)->DeleteGlobalRef(pEnv, lArray[j]);
			}
			free(lArray);
			return;
		}

		// The Java Color is going to be stored on the native side.
		        // Need to keep a global reference to avoid a potential
		        // garbage collection after method returns.
		// Malloc return value should theoretically be checked...
		lArray[i] = (*pEnv)->NewGlobalRef(pEnv,llocalColor);

		if (NULL == lArray[i]) {
			for (j = 0; j < i; ++j) {
				(*pEnv)->DeleteGlobalRef(pEnv, lArray[j]);
			}
			free(lArray);
			return;
		}
		// We have a global reference to the Color, so we can now get
		        // rid of the local one.
		(*pEnv)->DeleteLocalRef(pEnv, llocalColor);

	}

	// Creates a new entry with the new String array.
	StoreEntry* lEntry = allocateEntry(pEnv, &mStore, pKey);

	if (lEntry != NULL) {
		lEntry->mType = StoreType_ColorArray;
		lEntry->mLength = lLength;
		lEntry->mValue.mColorArray = lArray;
	} else {
		 // If an exception happens, global references must be
		        // carefully destroyed or objects will never get garbage
		        // collected (as we finally decide not to store them).
		for (j = 0; j < i; ++j) {
			(*pEnv)->DeleteGlobalRef(pEnv, lArray[j]);
		}
		free(lArray);
		return;
	}
}

我们来看一下getBoolean是怎么获得值的

StoreEntry* lEntry = findEntry(pEnv, &mStore, pKey, NULL);
	if (isEntryValid(pEnv, lEntry, StoreType_Boolean)) {
		return lEntry->mValue.mBoolean;
	} else {
		return 0;
	}
StoreEntry 是一个结构体,里面存储被保存的信息,findEntry查找存储中是否有要找的值,有就返回,没有就返回0;

再来看一下是怎么设置值。以setBoolean为例

// Creates a new entry (or finds it if it already exists) in the
	    // store.
	StoreEntry* lEntry = allocateEntry(pEnv, &mStore, pKey);
	if (lEntry != NULL) {
		// Updates entry content with the requested data.
		lEntry->mType = StoreType_Boolean;
		lEntry->mValue.mBoolean = pBoolean;
	}

我们要新生成一个StoreEntry对象,把传过的类型,和值存储再StoreEntry中。

下面,再看两个特殊的类型传递,一个是String,一个是对象。

getString

JNIEXPORT jstring JNICALL Java_com_example_packtpub_Store_getString(JNIEnv *pEnv, jobject pThis, jstring pKey)
{
	StoreEntry* lEntry = findEntry(pEnv, &mStore, pKey, NULL);
	if (isEntryValid(pEnv, lEntry, StoreType_String)) {
		//// Converts a C string into a Java String.
		return (*pEnv)->NewStringUTF(pEnv, lEntry->mValue.mString);
	} else {
		return NULL;
	}
}
注意这里返回的时候用到了NewStringUTF函数,简单的说是把,c中的字符串转化为java中的字符串。

setString

JNIEXPORT void JNICALL Java_com_example_packtpub_Store_setString(JNIEnv *pEnv, jobject pThis, jstring pKey, jstring pString)
{
	// Turns the Java string into a temporary C string.
	    // GetStringUTFChars() is used here as an example but
	    // Here, GetStringUTFChars() to show
	    // the way it works. But as what we want is only a copy,
	    // GetBooleanArrayRegion() would be be more efficient.
	const char* lStringTmp = (*pEnv)->GetStringUTFChars(pEnv, pString, NULL);
	if (lStringTmp == NULL) {
		return;
	}
	StoreEntry* lEntry = allocateEntry(pEnv, &mStore, pKey);
	if (lEntry != NULL) {

		lEntry->mType = StoreType_String;
		// Copy the temporary C string into its dynamically allocated
		        // final location. Then releases the temporary string.
		        // Malloc return value should theoretically be checked...
		jsize lStringLength = (*pEnv)->GetStringUTFLength(pEnv, pString);
		lEntry->mValue.mString = (char*) malloc(sizeof(char) * (lStringLength + 1));
		strcpy(lEntry->mValue.mString, lStringTmp);
	}
}

把JNI中的jstring转成c 的字符串

const char* lStringTmp = (*pEnv)->GetStringUTFChars(pEnv, pString, NULL);
判断jstring数组长度,
<pre name="code" class="cpp">jsize lStringLength = (*pEnv)->GetStringUTFLength(pEnv, pString);


并在c中new 一个同样的大小的数组,把他给拷贝过去。

lEntry->mValue.mString = (char*) malloc(sizeof(char) * (lStringLength + 1));
		strcpy(lEntry->mValue.mString, lStringTmp);

对象的也相对简单直接返回jobject对象

JNIEXPORT jobject JNICALL Java_com_example_packtpub_Store_getColor(JNIEnv *pEnv, jobject pThis, jstring pKey)
{

	  StoreEntry* lEntry = findEntry(pEnv, &mStore, pKey, NULL);
	    if (isEntryValid(pEnv, lEntry, StoreType_Color)) {
	        // Returns a Java object.
	        return lEntry->mValue.mColor;
	    } else {
	        return NULL;
	    }

}
再设置对象的时候

JNIEXPORT void JNICALL Java_com_example_packtpub_Store_setColor(JNIEnv *pEnv, jobject pThis, jstring pKey, jobject pColor)
{
	// The Java Color is going to be stored on the native side.
	    // Need to keep a global reference to avoid a potential
	    // garbage collection after method returns.
	jobject lColor = (*pEnv)->NewGlobalRef(pEnv, pColor);
	if (lColor == NULL) {
		return;
	}

	// Save the Color reference in the store.
	StoreEntry * lEntry = allocateEntry(pEnv, &mStore, pKey);
	if (lEntry != NULL) {
		lEntry->mType = StoreType_Color;
		lEntry->mValue.mColor = lColor;
	} else {
		(*pEnv)->DeleteGlobalRef(pEnv, lColor);
	}
}
先用函数NewGlobalRef把对象转换成C中可识别的jobject。实质上就是再c中new 一个jobject对象, 再无法赋值的时候要用DeleteGlobalRef释放。

数组的传递,有代码。大家可以自己看。完整的demo最后,会给出。

下面类看一下,c中是怎么调java中的内容。下面是一个Java的异常类。

package com.example.exception;

@SuppressWarnings("serial")
public class InvalidTypeException extends Exception{

	public InvalidTypeException() {
		super();
	}
	
	public InvalidTypeException(String strDetailMessage, Throwable throwable) {
		super(strDetailMessage, throwable);
	}
	
	public InvalidTypeException(String strDetailMessage) {
		super(strDetailMessage);
	}
	
	public InvalidTypeException(Throwable throwable) {
		super(throwable);
	}
}

在c中使用如下代码就可调用

void throwInvalidTypeException(JNIEnv* pEnv)
{
    jclass lClass = (*pEnv)->FindClass(pEnv,
        "com/example/exception/InvalidTypeException");
    if (NULL != lClass) {
        (*pEnv)->ThrowNew(pEnv, lClass, "Type is invalid.");
    }
    (*pEnv)->DeleteLocalRef(pEnv, lClass);
}
FindClass 的后一个参数就是包的名加上类的名称。

然后调用ThrowNew函数把对用的值传入java中的构造函数。

最后,释放类的引用。



下面给出完整的demo,https://github.com/lishihaojie/NDK/tree/master/ndk1/MyNDK


阅读更多
想对作者说点什么?

博主推荐

换一批

没有更多推荐了,返回首页