两个关键字的定义都可以在jni_md.h下找到
均用于定义与平台相关的宏
用于标识函数用途
//Windows下的定义
#define JNIEXPORT __declspec(dllexport)
#define JNIIMPORT __declspec(dllimport)
#define JNICALL __stacall
//Linux下的定义(实际是空定义)
#define JNIEXPORT
#define JNIIMPORT
#define JNICALL
即根据JNI所约定的命名规则来指定函数的命名,具体规则如下:Java_类全路径_方法名
JNIEXPORT jstring JNICALL Java_com_kqli_jni_JniTest_getStringFromC(JNIEnv *env, jclass jclass);
JNIEXPORT jstring JNICALL Jave_com_test_jni_HelloWord_func(JNIEnv* env, jclass class, jstring str);
//函数原型
jint RegisterNatives(JNIEnv *env, jclass clazz, const JNINativeMethod *methods, jint nMethods);
typedef struct {
char *name; //java方法名称
char *signature;//java方法签名
void *fnPtr;//c/c++的函数指针
} JNINativeMethod;
nMethods = sizeof(methods) / sizeof(JNINativeMethod);
java
package com.test.jni;
public class A{
static{
System.loadLibrary("A");
}
public static native int a(String str);
public static native boolean b();
public static native int c(Object obj);
public static void main(String[] args){
......
}
}
native
jint a(JNIEnv *env ,jclass class, jstring str){
....
}
jboolean b(JNIEnv *env ,jclass class){
....
}
jint c(JNIEnv *env ,jclass class, jobject obj){
....
}
static JNINativeMethod method_table[] =
{
{"a", "(Ljava/lang/String;)I", (void *)a},
{"b", "()Z", (void *)b},
{"c", "(Ljava/lang/Object;)I", (void *)c},
};
jint JNI_OnLoad(JavaVM* vm, void* reserved)
{
......
jclass clz = env ->FindClass(JNIREG_CLASS);
env ->RegisterNatives(clz, method_table, sizeof(method_table) / sizeof(JNINativeMethod));
......
}
类: 例如String的签名为Ljava/lang/String; 注意: 包名和类名用/隔开, 结尾有一个;
数组:用[表示数组签名, 例如int[]的签名为[I
JNI通过jstring来处理字符串数据,但是jstring是指向JVM内部的字符串,和C风格的字符串类型char * 不同,因此必须使用合适的JNI函数来访问JVM内部的字符串。
因为Java默认使用unicode编码,而C/C++默认使用UTF编码,所以要注意进行编码转换。
const char* GetStringUTFChars(jstring str, jbbolean *isCopy);
通过GetStringUTFChars获取到字符串并返回的为源字符串拷贝后,在使用完毕要记得释放内存。
void ReleaseStringUTFChars(jstring str, const char* utf);
jstring NewStringUTF(const char * bytes);