跳至主要內容
  • Hostloc 空間訪問刷分
  • 售賣場
  • 廣告位
  • 賣站?

4563博客

全新的繁體中文 WordPress 網站
  • 首頁
  • 请教一个动态链接库构建的问题 (c++) (android) (opencv)
未分類
17 12 月 2020

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

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

資深大佬 : nthhdy 5

各位大佬

正在开发一个安卓 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,它是一个不接受参数的函数,所以不会因为参数类型不匹配导致整体不匹配。

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

大佬有話說 (21)

  • 資深大佬 : GeruzoniAnsasu

    链接命令行里压根就没有 opencv 相关的库

    你只 include 到了 cv 的头文件,没有指定链接库

  • 資深大佬 : pursuer

    有符号不一定有实现吧,有的符号是外部符号,就没有实现

  • 資深大佬 : GeruzoniAnsasu

    不好意思我瞎了 但看起来中间那几行把.a 文件跟.o 一起作为输入文件的地方不太正常。。。 感觉拼编译-链接参数的时候写得不对?

  • 資深大佬 : mingl0280

    根据你这个编译结果……你找下你代码里面有没有用 using namespace std 和 std::string?

  • 主 資深大佬 : nthhdy

    @pursuer 这个符号类型是 T,也就是全局征文段,放在代码区的,应该有实现的。

  • 主 資深大佬 : nthhdy

    @GeruzoniAnsasu 不好意思,命令太长,我也觉得贴出来太乱,有什么好办法吗? log 也没法高亮或者排版。

    其实这个编译命令是工具自动生成的,不是我敲的,不知道它根据什么生成这样的。是 gradle 使用了 ndk build,后者又生成了这个命令。

  • 主 資深大佬 : nthhdy

    @mingl0280 缺失的是 `cv::String` 的相关方法,不是 `std::string` 吧

  • 主 資深大佬 : nthhdy

    @GeruzoniAnsasu 读了读 ndk build 的源码,完全是 make file 语法,一堆 if else,超级多变量展开。makefile 本身可读性就有些低,这样一搞,读起来学习曲线还是挺大的。感觉是要把自己玩死。相比之下 gradle 用 groovy 语法就优雅多了。

  • 資深大佬 : wutiantong

    @nthhdy 我怀疑你这个 arm64-v8a/libopencv_core.a 是 iOS 平台的编译产物

  • 資深大佬 : wutiantong

    @wutiantong 即便它确实是 Android 的静态库,如果是二进制拿来用的话,ndk 的版本差异可能也会导致各种问题。

  • 主 資深大佬 : nthhdy

    @wutiantong 这个思路有道理。
    但是 opencv 这些 .a 是我自己编译的,编译时特意指定了 abi 为 arm64-v8a 的(有可能是指定没生效?),ndk 的版本我确认是一致的。
    请问检查平台是否一致,有什么方法、工具吗?

  • 資深大佬 : wutiantong

    @nthhdy Mac 的话可以用 file 命令查看一下 libopencv_core.a

  • 資深大佬 : waruqi

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

    命名空间不对哈,你 jni 里面 报 cv::String::deallocate 符号找不到, 你从库里面只找到 cv::Mat::deallocate,命名空间都不同,符号名都不一样,能链接通过才怪了。。

  • 資深大佬 : waruqi

    当我没说,眼瞎,后面 看到 cv::String::deallocate 了。

  • 資深大佬 : kaler

    -shared 是连接的命令吗?还有连接的顺序也可能造成这种问题。

  • 主 資深大佬 : nthhdy

    @kaler -shared 表示输出的是动态链接库,不是可执行文件

    链接顺序的话,我试了把 libopencv_core.a 作为那些 .a 的最后一个,也是同样的错误

  • 資深大佬 : mingl0280

    @nthhdy 因为有可能是引用错误啊……比方说你本来用的 std::string,但是因为 using 的关系匹配到了 cv::string 就炸了……

  • 主 資深大佬 : nthhdy

    @mingl0280 明白你意思,using 的确很容易出问题。使用一个变量时,它的实际的命名空间有可能跟想的不一样。

    但是代码里的确用的是 cv::String,不是 std::string 。
    再说 std::string 也没有 deallocate 方法,而且一个是 string ( s 小写)一个是 String ( S 大写),不会匹配错的。
    另外,除了 String 类,还有许多别的类也 undefined reference,不会都是因为这个原因的。

    我感觉 using 出的编译错误会更多,一般不会到链接这步。因为就算两个同名的类出现在两个不同的 namespace 里,它们的用法也基本上不会完全一致的,那单个文件编译都过不了。

  • 資深大佬 : mingl0280

    @nthhdy 我知道你啥意思,不过我真遇到过类似的坑爹问题,就是提一下。其实你还有个测试方法:你找到输出的.o 文件,然后手动运行一下链接命令,看看是不是即使手动链接也不认。如果是这种情况的话 90%以上可能性是你的库的 abi 不兼容,用 objdump 之类的检查一下……

  • 主 資深大佬 : nthhdy

    @mingl0280 我就是把这条命令 copy 出来手动运行的啊。还不停地把它试着该来改去,加点参数、减点参数什么的。到现在还没成功。如果是 abi 不兼容,错误信息也不提示一下吗。。。而且应该不是 abi,明明各处都指定了 arm64-v8a 的。感觉这个问题还有其它我未知“维度”,再搜吧。

    跨平台编译链接要考虑的问题太多了,cpu 架构、指令集、操作系统约定、各层库版本、工具链、各种路径配置、各种编译链接细节,还有我好多叫得出名字但是不明所以的术语。越贴近底层,要了解的东西就越多。任何一个维度都有可能造成这个问题,还不清楚是哪一环出得问题。感觉这件事儿急不得,也没法“突击”,从基本的知识了解吧。

  • 資深大佬 : mingl0280

    @nthhdy 你对 libopencv_core.a 做一个 objdump,然后 dump 出来的.o 文件跑一下 nm,仔细看一下是不是 CPU 架构不太一样。有时候真就这个问题。

文章導覽

上一篇文章
下一篇文章

AD

其他操作

  • 登入
  • 訂閱網站內容的資訊提供
  • 訂閱留言的資訊提供
  • WordPress.org 台灣繁體中文

51la

4563博客

全新的繁體中文 WordPress 網站
返回頂端
本站採用 WordPress 建置 | 佈景主題採用 GretaThemes 所設計的 Memory
4563博客
  • Hostloc 空間訪問刷分
  • 售賣場
  • 廣告位
  • 賣站?
在這裡新增小工具