使用JNI 调用第三方c++动态库
来源:互联网 发布:异形知乎 编辑:程序博客网 时间:2024/05/08 09:48
昨天晚上到今天一直在折腾这个第三方库文件,唉,要哭了,一直就是各种问题。现在详细说说怎么做,踩过哪些坑。
现有个第三方的C++动态库(libModel.so),这个libModel.so是要能被android调用的arm库啊,需要在android中,使用java直接调用,那么一般是两种方式:
1:libModel.so 符合JNI规范,能够直接在java层调用
2:libModel.so不符合规范,只是普通的c++动态库,那么只能是在JNI,写个c/c++函数,调用这个libModel.so库里面的函数,然后重新编译为libhello.so库,android调用这个libModel.so;其实就像给libModel.so再封装一层。
由于libModel.so不符合JNI规范,我只能采用第二种方式。
首先,创建一个HelloTest的android程序,然后在HelloTest中新建一个jni文件,在jni文件中仔创建一个prebuilt文件夹,里面存放libmodel.so,并且新建一个Android.mk。
Android.mk的内容如下:
LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS) LOCAL_MODULE := model LOCAL_SRC_FILES := libModel.so include $(PREBUILT_SHARED_LIBRARY)
然后在jni里面新建Android.mk
LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS) LOCAL_MODULE := hello LOCAL_SRC_FILES := hello.cpp LOCAL_LDLIBS := -llog LOCAL_SHARED_LIBRARIES := model LOCAL_ALLOW_UNDEFINED_SYMBOLS := true //避免出现undefined的错误 include $(BUILD_SHARED_LIBRARY)include $(LOCAL_PATH)/prebuilt/Android.mk //包含prebuilt下的Android.mk
因为我jni里面的具体函数使用到了,所以需要添加一个Application.mk,Application.mk内容如下:
APP_STL := stlport_static
在这里也遇到了坑,一定要确保你是.cpp文件,不然Application.mk没有作用,依然会报:
error :can not find iostream的错误,因为这个stlport_static是供c++使用的。
在APK运行时,报了如下的错误,无法加载库,那是因为apk没有找到库文件:
01-02 03:50:05.655: E/AndroidRuntime(32314): Caused by: java.lang.UnsatisfiedLinkError: Cannot load library: reloc_library[1285]: 2824 cannot locate '_ZN13CVQASSESSMENTC1Ev'...
我之前尝试使用如下方式进行打包,不创建prebuilt文件夹 ,直接在jni的Android.mk,加入libModel.so库,:
LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS) LOCAL_MODULE := libModel LOCAL_SRC_FILES := libModel.so include $(PREBUILT_SHARED_LIBRARY) include $(CLEAR_VARS) LOCAL_MODULE := modeljni LOCAL_SRC_FILES := modeTest LOCAL_SHARED_LIBRARY := libModel include $(BUILD_SHARED_LIBRARY)
以上面的方式打包,在apk运行的时候,就找不到库,我也没有想明白为什么,还是我的打包有问题,用第一种方式执行成功。
还有在java端调用库的时候,两个库都要包含进去,且顺序是先libModel.so,在调用新生成的。
static { System.loadLibrary("Model"); System.loadLibrary("hello"); }
其次就是c++库需要传递结构体参数,我是这样做的,在JAVA定义一个包含结构体所需参数的类,然后呢,java向jni中的C++ 传递 一个对象,c++解析java的对象,再重构第三方库需要的结构体参数, java 与c 传参 博客写的挺好的,具体的实现是:
首先在java申明native 方法:
public native int getInput(SideInfo sideInfo);
然后,使用javah 生成头文件,将头文件拷贝至jni中, jni中c++具体的实现如下:
//java 向c 传递对象jint Java_com_example_hellotest_MainActivity_getInput(JNIEnv * env, jobject jthis, jobject sideInfo){CVQASSESSMENT VqAssessUnit;jmethodID methodId;//获得sideInfo对象的句柄jclass cls_objClass=env->GetObjectClass(sideInfo);//获得sideInput对象中特定方法getI_Audio_sample_rate的idmethodId=env->GetMethodID(cls_objClass,"getI_Audio_sample_rate","()I");//第三个是方法的签名,可以通过 javap -s XX.class的方式查看方法的签名。//调用sideInfo对象的特定方法getI_Audio_sample_ratejint jrate=(jint)env->CallIntMethod(sideInfo,methodId,NULL); //获取不同的值,有不同的CallXXMethod方法。return jrate;}
通过这样的方法,就可以向c++ 传递java对象了。
- 使用JNI 调用第三方c++动态库
- android JNI 调用第三方动态库
- Android-jni 调用第三方动态库
- JNI 如何使用dlopen,dlsym调用第三方自定义的 .so库( JNI->C,C++)
- JNI技术之Java调用C/C++编写的第三方dll-动态链接库
- android JNI学习之二 调用第三方动态库
- android jni开发 调用 第三方 动态链接库
- android JNI 使用的两种形式 --自己实现c和调用第三方so库
- 使用JNI调用第三方.so文件
- Java调用C/C++编写的第三方dll动态链接库(非native API)--- JNI
- Java调用C/C++编写的第三方dll动态链接库(非native API)--- JNI
- Java调用C/C++编写的第三方dll动态链接库(非native API)--- JNI
- Java调用C/C++编写的第三方dll动态链接库(非native API)--- JNI
- Java调用C/C++编写的第三方dll动态链接库(非native API)--- JNI
- Java调用C/C++编写的第三方dll动态链接库(非native API)--- JNI
- Java调用C/C++编写的第三方dll动态链接库(非native API)--- JNI
- Java调用C/C++编写的第三方dll动态链接库(非native API)--- JNI
- Java调用C/C++编写的第三方dll动态链接库(非native API)--- JNI
- iOS获取本机wifi的IP地址
- POJ 1088滑雪的一种非记忆搜索的解法
- boost中的socket的async_read_some() 方法会导致严重的阻塞
- 引入样式表 及脚本文件
- spring简单的AOP编程小结
- 使用JNI 调用第三方c++动态库
- 安家贴,从此踏上计算机的坑,不回头。
- Java Web 初级程序员 -第7天学习内容:泛型
- 对数组的操作方法
- Android-图片三级缓存(网络-本地-内存)
- 生日相同的概率
- hdu 5480 Conturbatio
- 校招算法之冒泡排序的优化
- Android之自定义实现BaseAdapter(优化布局)