请教一个动态链接库构建的问题 (c++) (android) (opencv)

2020-12-24 19:57:00 +08:00
 nthhdy

各位大佬

正在开发一个安卓 app,用到 jni,在 c++ 里调用 opencv 。但是 opencv 始终不能连接成功,链接时错误日志(截几行)如下:

/Users/rqs/proj/android_robot/build/intermediates/ndkBuild/release/obj/local/arm64-v8a/objs/native-lib/native_jni.o: In function `String':
/Users/rqs/proj/android_robot/opencv_prebuilt/sdk/native/jni/include/opencv2/core/cvstd.hpp:602: undefined reference to `cv::String::allocate(unsigned long)'
/Users/rqs/proj/android_robot/build/intermediates/ndkBuild/release/obj/local/arm64-v8a/objs/native-lib/native_jni.o: In function `Java_com_turingvideo_robot_jni_NativeHelper_drawText':
/Users/rqs/proj/android_robot/src/main/jni/native_jni.cpp:150: undefined reference to `cv::putText(cv::_InputOutputArray const&, cv::String const&, cv::Point_<int>, int, double, cv::Scalar_<double>, int, int, bool)'
/Users/rqs/proj/android_robot/build/intermediates/ndkBuild/release/obj/local/arm64-v8a/objs/native-lib/native_jni.o: In function `~String':
/Users/rqs/proj/android_robot/opencv_prebuilt/sdk/native/jni/include/opencv2/core/cvstd.hpp:648: undefined reference to `cv::String::deallocate()'
/Users/rqs/proj/android_robot/build/intermediates/ndkBuild/release/obj/local/arm64-v8a/objs/native-lib/native_jni.o: In function `String':
/Users/rqs/proj/android_robot/opencv_prebuilt/sdk/native/jni/include/opencv2/core/cvstd.hpp:602: undefined reference to `cv::String::allocate(unsigned long)'
/Users/rqs/proj/android_robot/build/intermediates/ndkBuild/release/obj/local/arm64-v8a/objs/native-lib/native_jni.o: In function `Java_com_turingvideo_robot_jni_NativeHelper_drawText':
/Users/rqs/proj/android_robot/src/main/jni/native_jni.cpp:151: undefined reference to `cv::putText(cv::_InputOutputArray const&, cv::String const&, cv::Point_<int>, int, double, cv::Scalar_<double>, int, int, bool)'
/Users/rqs/proj/android_robot/build/intermediates/ndkBuild/release/obj/local/arm64-v8a/objs/native-lib/native_jni.o: In function `~String':
/Users/rqs/proj/android_robot/opencv_prebuilt/sdk/native/jni/include/opencv2/core/cvstd.hpp:648: undefined reference to `cv::String::deallocate()'
/Users/rqs/proj/android_robot/build/intermediates/ndkBuild/release/obj/local/arm64-v8a/objs/native-lib/native_jni.o: In function `String':
/Users/rqs/proj/android_robot/opencv_prebuilt/sdk/native/jni/include/opencv2/core/cvstd.hpp:602: undefined reference to `cv::String::allocate(unsigned long)'
/Users/rqs/proj/android_robot/build/intermediates/ndkBuild/release/obj/local/arm64-v8a/objs/native-lib/native_jni.o: In function `Java_com_turingvideo_robot_jni_NativeHelper_drawText':
/Users/rqs/proj/android_robot/src/main/jni/native_jni.cpp:153: undefined reference to `cv::putText(cv::_InputOutputArray const&, cv::String const&, cv::Point_<int>, int, double, cv::Scalar_<double>, int, int, bool)'
/Users/rqs/proj/android_robot/build/intermediates/ndkBuild/release/obj/local/arm64-v8a/objs/native-lib/native_jni.o: In function `~String':
/Users/rqs/proj/android_robot/opencv_prebuilt/sdk/native/jni/include/opencv2/core/cvstd.hpp:648: undefined reference to `cv::String::deallocate()'
/Users/rqs/proj/android_robot/build/intermediates/ndkBuild/release/obj/local/arm64-v8a/objs/native-lib/native_jni.o: In function `String':
/Users/rqs/proj/android_robot/opencv_prebuilt/sdk/native/jni/include/opencv2/core/cvstd.hpp:602: undefined reference to `cv::String::allocate(unsigned long)'


我理解 undefined reference 就是链接时找不到某个符号的实现,一般是因为某个库的缺失、某个库的版本不对,类型不匹配。

我找到了构建工具执行的链接语句,也比较长:


/Users/rqs/Library/Android/sdk/ndk/21.3.6528147/toolchains/llvm/prebuilt/darwin-x86_64/bin/clang++\
        -Wl,-soname,libnative-lib.so\
        -shared\
        /Users/rqs/proj/android_robot/build/intermediates/ndkBuild/debug/obj/local/arm64-v8a/objs-debug/native-lib/native_jni.o\
        /Users/rqs/proj/android_robot/build/intermediates/ndkBuild/debug/obj/local/arm64-v8a/objs-debug/native-lib/src/arucotag.o\
        /Users/rqs/proj/android_robot/build/intermediates/ndkBuild/debug/obj/local/arm64-v8a/objs-debug/native-lib/src/utils.o\
        /Users/rqs/proj/android_robot/build/intermediates/ndkBuild/debug/obj/local/arm64-v8a/objs-debug/native-lib/src/occupancy_grid.o\
        /Users/rqs/proj/android_robot/build/intermediates/ndkBuild/debug/obj/local/arm64-v8a/objs-debug/native-lib/src/occupancy_grid_jni.o\
        /Users/rqs/proj/android_robot/build/intermediates/ndkBuild/debug/obj/local/arm64-v8a/objs-debug/native-lib/src/virtual_wall_grid_jni.o\
        /Users/rqs/proj/android_robot/build/intermediates/ndkBuild/debug/obj/local/arm64-v8a/objs-debug/native-lib/src/virtual_wall_grid.o\
        /Users/rqs/proj/android_robot/opencv_prebuilt/sdk/native/staticlibs/arm64-v8a/libopencv_aruco.a\
        /Users/rqs/proj/android_robot/opencv_prebuilt/sdk/native/staticlibs/arm64-v8a/libopencv_highgui.a\
        /Users/rqs/proj/android_robot/opencv_prebuilt/sdk/native/staticlibs/arm64-v8a/libopencv_calib3d.a\
        /Users/rqs/proj/android_robot/opencv_prebuilt/sdk/native/staticlibs/arm64-v8a/libopencv_imgproc.a\
        /Users/rqs/proj/android_robot/opencv_prebuilt/sdk/native/3rdparty/libs/arm64-v8a/libcpufeatures.a\
        /Users/rqs/proj/android_robot/opencv_prebuilt/sdk/native/3rdparty/libs/arm64-v8a/libtegra_hal.a\
        /Users/rqs/proj/android_robot/opencv_prebuilt/sdk/native/staticlibs/arm64-v8a/libopencv_core.a\
        -lgcc\
        -Wl,--exclude-libs,libgcc.a\
        -Wl,--exclude-libs,libgcc_real.a\
        -latomic\
        -Wl,--exclude-libs,libatomic.a\
        /Users/rqs/proj/android_robot/build/intermediates/ndkBuild/debug/obj/local/arm64-v8a/libc++_shared.so\
        -target\
        aarch64-none-linux-android21\
        -no-canonical-prefixes\
        -Wl,--build-id\
        -ljnigraphics\
        -nostdlib++\
        -Wl,--no-undefined\
        -Wl,--fatal-warnings\
        -llog -ldl -lz -lm -lc -lm\
        -o /Users/rqs/proj/android_robot/build/intermediates/ndkBuild/debug/obj/local/arm64-v8a/libnative-lib.so
        

拿错误里提到的cv::String::deallocate() 来说,我在我指定的 libopencv_core 这个静态库中能够找到这个实现,nm 显示如下:


[19:44:57] rqs:opencv_prebuilt git:(1e0923e*) $ nm -CA /Users/rqs/proj/android_robot/opencv_prebuilt/sdk/native/staticlibs/arm64-v8a/libopencv_core.a | grep deallocate | grep ' T '
/Users/rqs/proj/android_robot/opencv_prebuilt/sdk/native/staticlibs/arm64-v8a/libopencv_core.a:matrix.cpp.o: 0000000000000000 T cv::Mat::deallocate()
/Users/rqs/proj/android_robot/opencv_prebuilt/sdk/native/staticlibs/arm64-v8a/libopencv_core.a:stl.cpp.o: 0000000000000000 T cv::String::deallocate()
/Users/rqs/proj/android_robot/opencv_prebuilt/sdk/native/staticlibs/arm64-v8a/libopencv_core.a:umatrix.cpp.o: 0000000000000000 T cv::UMat::deallocate()

可见里面有代码段的全局的 cv::String::deallocate,它是一个不接受参数的函数,所以不会因为参数类型不匹配导致整体不匹配。

既然提供了这个静态链接库,库里面也有它的实现,为什么还是会有链接错误呢?请指教,谢谢!

2553 次点击
所在节点    C++
21 条回复
mingl0280
2020-12-26 13:55:08 +08:00
@nthhdy 你对 libopencv_core.a 做一个 objdump,然后 dump 出来的.o 文件跑一下 nm,仔细看一下是不是 CPU 架构不太一样。有时候真就这个问题。

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/738701

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX