Home > Enterprise >  "imwrite" within CC Dynamic Android Library not found when beeing called from C-Code
"imwrite" within CC Dynamic Android Library not found when beeing called from C-Code

Time:11-30

I am using OpenCV 4.6.0 Android SDK which I downloaded from sourceforge and use it within my shared library/.so. This library is called from within my android app (aarch64). Building works fine using my android.toolchain.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)
...

And 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)
...

My .h

#ifdef __cplusplus
extern "C"
{
#endif
   bool imwriteC(Bitmap *bitmap, const char *filename);
#ifdef __cplusplus
}
#endif

And .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);
}

I call my imwriteC from C-Code. My error message looks like name-mangling

Unable to load library 'testlibrary':
"_ZN2cv7imwriteERKNSt6_ndk112basic_stringlcNS0_11char_traitslcEENS0_9allocatorlcEEEERKNS_11_InputArrayERKNS0_6vectorliNS4_liEEEE" referenced by ... "/path/to/testlibrary.so"...

So it seems like OpenCVs imwrite can't be found due to name mangling issues(?).

CodePudding user response:

It's not about mangling, you just didn't link with all the OpenCV libraries that you need.

You're using OpenCV version 4.6.0. I see that you're calling imwrite, and you're linking with the highgui module. Well, once upon a time (in 2.4.x) that would have worked, but IIRC since 3.x (and definitely in 4.x) this function resides in imgcodecs module. So you should change that target_link_libraries statement to something like

target_link_libraries(${PROJECT_NAME} PRIVATE opencv_imgcodecs)

Furthermore, since you're using a Mat there, you might need the core module. Often you can figure out the name of the module from the documentation (best look at the URL -- for imwrite there's group__imgcodecs.html in the middle, and the module name is after the two underscores).


Of course, as you found out, since you find_package(OpenCV REQUIRED), you can also take the shortcut and link with ${OpenCV_LIBS}, which ends up trying all the OpenCV modules. I guess that's good enough choice, although personally I prefer to explicitly specify exactly what I need and no more.

  • Related