从C代码调用时安卓动态库中OpenCV imwrite未找到问题
问题:Android aarch64架构下调用OpenCV imwrite函数出现符号未找到错误
环境与配置详情
1. CMake工具链配置
... set(CMAKE_C_COMPILER /home/username/Android/SDK/ndk/25.1.8937393/toolchains/llvm/prebuilt/linux-x86_64/bin/aarch64-linux-android21-clang) set(CMAKE_CXX_COMPILER /home/username/Android/SDK/ndk/25.1.8937393/toolchains/llvm/prebuilt/linux-x86_64/bin/aarch64-linux-android21-clang++) set(CMAKE_SYSTEM_NAME Android) set(CMAKE_SYSTEM_VERSION 21) set(CMAKE_ANDROID_ARCH_ABI arm64-v8a) set(CMAKE_ANDROID_NDK /home/username/Android/Sdk/ndk/25.1.8937393) set(CMAKE_SYSTEM_PROCESSOR aarch64) set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_EXTENSIONS OFF) set(CMAKE_CXX_STANDARD_REQUIRED ON) ...
2. CMakeLists.txt配置
... set(OpenCV_DIR ${CMAKE_CURRENT_LIST_DIR}/opencv-4.6.0-android-sdk/OpenCV-android-sdk/sdk/native/jni/abi-arm64-v8a) target_include_directories(${PROJECT_NAME} PUBLIC ${CMAKE_CURRENT_LIST_DIR}/opencv-4.6.0-android-sdk/OpenCV-android-sdk/sdk/native/jni/include) find_package(OpenCV REQUIRED) ... target_link_libraries(${PROJECT_NAME} PRIVATE opencv_highgui) ...
3. 头文件(myheader.h)
#ifdef __cplusplus extern "C" { #endif bool imwriteC(Bitmap *bitmap, const char *filename); #ifdef __cplusplus } #endif
4. 实现代码(cpp文件)
#include <opencv2/opencv.hpp> #include "myheader.h" ... bool imwriteWrapper(Bitmap *bitmap, const char *filename) { Mat mat; // ... // bitmap to mat conversion here // ... return imwrite(filename, mat); } bool imwriteC(Bitmap *bitmap, const char *filename) { return imwriteWrapper(bitmap, filename); }
错误信息
加载库时出现以下错误:
Unable to load library 'testlibrary': "_ZN2cv7imwriteERKNSt6_ndk112basic_stringlcNS0_11char_traitslcEENS0_9allocatorlcEEEERKNS_11_InputArrayERKNS0_6vectorliNS4_liEEEE" referenced by ... "/path/to/testlibrary.so"...
问题分析
从错误符号来看,表面像是C++名字修饰不匹配,但核心问题有两个:
- 链接的OpenCV模块错误:
imwrite函数属于opencv_imgcodecs模块,而非当前链接的opencv_highgui,导致库中缺少该函数的符号。 - STL版本可能不匹配:错误中的
NSt6_ndk1表示当前代码使用NDK的libc++,若OpenCV Android SDK使用了其他STL(如gnustl),也会导致符号修饰不兼容。
解决方案
1. 修正OpenCV模块链接
修改CMakeLists.txt中的链接配置,添加opencv_imgcodecs模块:
target_link_libraries(${PROJECT_NAME} PRIVATE opencv_highgui opencv_imgcodecs)
2. 确保STL版本一致
检查OpenCV配置文件中的STL类型:
- 打开
${OpenCV_DIR}/OpenCVConfig.cmake,查找OpenCV_STL的定义(例如c++_shared)。 - 在你的CMake工具链配置中添加对应STL设置:
注意:如果OpenCV用的是静态STL,就设置为set(CMAKE_ANDROID_STL_TYPE c++_shared)c++_static,保持完全一致。
3. 验证链接结果
重新编译后,使用nm工具检查生成的testlibrary.so,确认imwrite的符号已被正确引入:
aarch64-linux-android-nm -D /path/to/testlibrary.so | grep imwrite
内容的提问来源于stack exchange,提问作者Flippy
相关产品推荐
相关产品推荐

