JNI_1

JNI
JAVA调用C
Java访问C库的方法

  1. 加载C库
    System.loadLibrary
  2. 建立Java函数名到C库函数名的映射关系

方法描述符

	隐式建立
		类a.b.c.d.JNIDemo要调用hello函数
		C语言中要实现Java_a_b_c_d_JNIDemo_hello
		可以用工具生成头文件
			javac -d . JNIDemo.java
			javah -jni a.b.c.d.JNIDemo
	显示建立
		JNI_OnLoad
			加载C库时就会调用这个函数
		RegisterNatives
			定义一个映射数组JNINativeMethod[]
				每个数组项含3个成员
					Java里调用的函数名
					JNI字段描述符
						
						用"["表示数组,比如"int []"表示为"[I"
						对于类,要用全称"L包.子包.类名;"(前面有"L",后面有";"),比如"Ljava/lang/String;"
						除String类外,其他的类都用Object表示,即"Ljava/lang/Object;"
					C语言实现的本地函数
			注册这个数组
				(*env)->RegisterNatives(JNIEnv *env, jclass clazz, const JNINativeMethod *methods, jint nMethods)
	注意:C函数比Java里的声明多2个参数: (JNIEnv *env, jclass cls)
		env提供一些辅助函数,后面有例子
		cls是对Java类或实例的引用
			如果是static方法,则cls是对Java类的引用
			否则,cls是对类的实例化对象的引用
  1. 在Java程序里调用函数
    简单例子
    Java和C库传递数据
    传递基本类型数据
    直接使用、直接返回
    传递字符串 (jni.pdf P39)
    传递数组 (jni.pdf P48
    C调用JAVA (jni.pdf P97)
    1. 创建虚拟机
    2. 获得class
    3. 实例化对象
      对于静态方法,不需要实例化对象
      也是通过调用JAVA方法实现
  2. 调用JAVA方法
    1. 获得方法ID
    2. 构造参数
    3. 调用方法
  3. 其他
    设置属性
    1. 获得属性ID
    2. 设置属性
    3. 读取属性
static const JNINativeMethod methods[] = {
  {"hello","(I)I",(void *)c_hello},
};
JNIEXPORT jint JNICALL
JNI_OnLoad(JavaVM *jvm, void *reserved)
{
JNIEnv *env;
jclass cls;
cached_jvm = jvm; /* cache the JavaVM pointer */
if ((*jvm)->GetEnv(jvm, (void **)&env, JNI_VERSION_1_2)) {
return JNI_ERR; /* JNI version not supported */
}
cls = (*env)->FindClass(env, "C");
if (cls == NULL) {
return JNI_ERR;
}
/* Use weak global ref to allow C class to be unloaded */
Class_C = (*env)->NewWeakGlobalRef(env, cls);
if (Class_C == NULL) {
return JNI_ERR;
}
/* Compute and cache the method ID */
MID_C_g = (*env)->GetMethodID(env, cls, "g", "()V");
if (MID_C_g == NULL) {
return JNI_ERR;
}
return JNI_VERSION_1_2;
}
  1. 编译so
gcc -I/usr/lib/jvm/jdk1.8.0_121/include/ -I/usr/lib/jvm/jdk1.8.0_121/include/linux/ -fPIC -shared -o libnative.so native.c 
  1. 运行
    export LD_LIBRARY_PATH=.
    java JniDemo

  2. 生成jni描述符
    a. 先在native方法的java类目录下执行
    javac JniTest.java 生成.class文件
    b. 退到androidstudio工程的java目录下,执行
    javah -jni com.aispeech.xytttest.callnative.NativeWakeup

  3. 碰到的问题:

a. libnativewakeup.so: has text relocations
参考
调用.so文件时报如下错误:
libcooee.so: has text relocations
说明编译.so文件时使用了较低版本sdk
而project 中的配置 targetSdkVersion22 大于so编译时使用的sdkversion,所以只需要把功能中
的targetSdkVersion降低即可

defaultConfig {
applicationId “com.example”
minSdkVersion 16
targetSdkVersion 22 
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值