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 |
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);StoreEntry 是一个结构体,里面存储被保存的信息,findEntry查找存储中是否有要找的值,有就返回,没有就返回0;
if (isEntryValid(pEnv, lEntry, StoreType_Boolean)) {
return lEntry->mValue.mBoolean;
} else {
return 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)注意这里返回的时候用到了NewStringUTF函数,简单的说是把,c中的字符串转化为java中的字符串。
{
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;
}
}
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)先用函数NewGlobalRef把对象转换成C中可识别的jobject。实质上就是再c中new 一个jobject对象, 再无法赋值的时候要用DeleteGlobalRef释放。
{
// 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);
}
}
数组的传递,有代码。大家可以自己看。完整的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)FindClass 的后一个参数就是包的名加上类的名称。
{
jclass lClass = (*pEnv)->FindClass(pEnv,
"com/example/exception/InvalidTypeException");
if (NULL != lClass) {
(*pEnv)->ThrowNew(pEnv, lClass, "Type is invalid.");
}
(*pEnv)->DeleteLocalRef(pEnv, lClass);
}
然后调用ThrowNew函数把对用的值传入java中的构造函数。
最后,释放类的引用。
下面给出完整的demo,https://github.com/lishihaojie/NDK/tree/master/ndk1/MyNDK