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(?).
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.