为了账号安全,请及时绑定邮箱和手机立即绑定

请问该如何加载ndk库?如何在jni中注册native函数?

/ 猿问

请问该如何加载ndk库?如何在jni中注册native函数?

烙印99 2019-09-14 14:11:43

如何加载ndk库?如何在jni中注册native函数


查看完整描述

5 回答

?
函数式编程

android源码中native方法的使用并不是你所想的那样,能够去查看的它的具体定义。其实它的具体的定义是在库(比如lib/hello-jni.c或者.cpp文件)中实现的。比如在package\app下有个ServiceMenu,它里面有相应的.cpp文件,用native方法修饰的函数就...

查看完整回答
反对 回复 2019-09-17
?
繁星淼淼

1. ndk支持的库很少,所以用以前最好先看看自己需要的功能是不是已经包括了,省得白忙活。
2. 注册函数的方法是不同的。举例说,在com/evan129/jnitest/jniutils.java有个native int foo()方法,需要在jni中实现
在ndk中,只要实现这个函数,然后函数名是以jint java_com_evan129_jnitest_jniutils_foo(jnienv* env, jobject thiz) 命名既可。也就是说,如果jni只要实现这个函数,并且功能也很简单的话,那么jni c/cpp文件里只需要这一个函数就完事了。
但在android源码中编译jni代码是不同的,jni中的函数名无所谓。不过至少还需要加一个
jniexport jint jnicall jni_onload(javavm* vm, void* reserved)方法,这个方法可以找个现有的复制一把就行,检查运行环境的。然后主要是这个方法中会调用(*env).registernatives函数,在这里把jni中的方法和java文件中的方法关联起来。
3. 有个很诡异的区别,自动传入的jnienv* env好像不是一个东西。因为在android源码中使用这个env一般是如env->newstringutf(…),而ndk中sample里的一处是(*env)->newstringutf(…) 这env和*env差很大。但两处函数传入的都是jnienv* env,只能怀疑jnienv的定义是不是都是不同的。


查看完整回答
反对 回复 2019-09-17
?
慕森王

1. ndk支持的库很少,所以用以前最好先看看自己需要的功能是不是已经包括了,省得白忙活。不过人家是有解释的,说ndk里有的库才是稳定的,其它的建议你不要用。嗯,google总是这一套说辞,不公开的api也是。至于要看android源码中多了哪些库,make modules后grep一下lib开头的应该就是了,不过也不是所有都能用啦。

2. 注册函数的方法是不同的。举例说,我在com/evan129/jnitest/jniutils.java有个native int foo()方法,需要在jni中实现
在ndk中,你只要实现这个函数,然后函数名是以jint java_com_evan129_jnitest_jniutils_foo(jnienv* env, jobject thiz) 命名既可。也就是说,如果你的jni只要实现这个函数,并且功能也很简单的话,那么你的jni c/cpp文件里只需要这一个函数就完事了。
但在android源码中编译jni代码是不同的,jni中的函数名无所谓。不过你至少还需要加一个
jniexport jint jnicall jni_onload(javavm* vm, void* reserved)方法,这个方法你可以找个现有的复制一把就行,检查运行环境的。然后主要是这个方法中会调用(*env).registernatives函数,在这里把jni中的方法和java文件中的方法关联起来。
看起来像是ndk自动补上了这部分工作,我并不清楚原理啦。

3. 有个很诡异的区别,自动传入的jnienv* env好像不是一个东西。因为在android源码中使用这个env一般是如env->newstringutf(…),而ndk中sample里的一处是(*env)->newstringutf(…) 这env和*env差很大吧。但两处函数传入的都是jnienv* env,我只能怀疑jnienv的定义是不是都是不同的。
末了,就是说下我这个很简单的jni折腾了我两天的一个问题。如前所说,我是用android源码来编译的,自己在packages/app/下建了pinyinjni工程,下面有个jni目录,每次直接用mmm packages/app/pinyinjni/jni来编译。jni目录下的android.mk中指定的名字是这样的local_module := libpinyin 每次编译都很顺利,生成了libpinyin.so。但是我在java文件里,system.loadlibrary(“libpinyin”)总是失败。感谢paranoia@newsmth帮我解决了这个问题,告诉我在loadlibrary时用”pinyin”。但是,这个事情实在太奇怪了,那文件名是libpinyin.so啊,而且我在这里用/data/data/…/libpinyin.so这种完整路径也会失败,我以前虽然没写过jni,但调用过,用完整路径指定jni so文件应该不会有问题的。或者,从另一个角度想,如果我local_module的名字不是用lib开头的,那它调用时应该用什么名字?这个”lib”前缀又是哪步删除的?我没有多做测试了,但是猜想ndk中应该是没有这种诡异的问题的。


查看完整回答
反对 回复 2019-09-17

添加回答

回复

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信