0

I want to include a static library built for the C++ code provided, I tried linking the static library, but build cannot link the library. I am getting the following error:

undefined reference to 'Test_C_Interface'

I am new to Java NDK/cmake. Please help me with this

This is the cpp code used(native-lib.cpp)

    extern int Test_C_Interface();

    extern "C" JNIEXPORT jstring JNICALL

    Java_com_example_tvgui_MainActivity_stringFromJNI(JNIEnv *env, jobject /* this */) {
        std::string hello = "From C++";

        int ret_val;

        ret_val = Test_C_Interface();

        if(ret_val == 100){
            hello = "From C";
        }
       return env->NewStringUTF(hello.c_str());
    }

This is the c code used to make the static library(sample.c/libsample.a)[Library built using NDK ARM-v7a ToolChain]

    #include<stdio.h>

    int Test_C_Interface(void)
    {
        printf("Inside C Library\n");

        return 100;
    }

This is the cmake file

    cmake_minimum_required(VERSION 3.4.1)

    add_library(
            native-lib
            SHARED
            native-lib.cpp)

    find_library( 
            log-lib
            log)

    target_link_libraries(
            native-lib
            ${log-lib}
            ${CMAKE_CURRENT_SOURCE_DIR}/../../../libs/libsample.a)

I need to build a application from like :

libsample.a
             \
              \
                ====libnative-lib.so + Java = .apk 
              /
             /
native-lib.cpp

UPDATE The problem was solved by modifying the code as below :

extern "C"{ 
     int Test_C_Interface();
}
Maddy26
  • 107
  • 1
  • 10

2 Answers2

2

You should put your libsample.a into directories in below structure according to your ABI, e.g.

libs
│   ├── x86/libsample.a
│   ├── x86_64/libsample.a
│   ├── arm64-v8a/libsample.a
│   ├── armeabi-v7a/libsample.a

And then update your cmakefile as below:

target_link_libraries(
            native-lib
            ${log-lib}
            ${CMAKE_CURRENT_SOURCE_DIR}/../../../libs/<ANDROID_ABI>/libsample.a)

Please ensure that ${CMAKE_CURRENT_SOURCE_DIR}/../../../libs is a correct path.

For the CMake variables, e.g. ANDROID_ABI, you can refer to Android NDK path variable in CMake build tool chain

shizhen
  • 12,251
  • 9
  • 52
  • 88
  • As per above modification, CMakeCache.txt looks like this ://Dependencies for the target native-lib_LIB_DEPENDS:STATIC=general;C:/Users/no101/AppData/Local/Android/Sdk/ndk-bundle/toolchains/llvm/prebuilt/windows-x86_64/sysroot/usr/lib/arm-linux-androideabi/16/liblog.so;general;C:/Users/no101/AndroidStudioProjects/TVGUI/app/src/main/cpp/../../../libs/armeabi-v7a/libsample.a;----- but getting the same error – Maddy26 May 27 '19 at 05:26
  • You need to ensure two things in the first place: 1. your `libsample.a` was built with Android NDK, if you did this correctly, then you should have a output directory like `/x86/libsample.a`, `/x86_64/libsample.a`, `/arm64-v8a/libsample.a` and `/armeabi-v7a/libsample.a`. 2, you should ensure `${CMAKE_CURRENT_SOURCE_DIR}/../../../libs` is a real existing path. – shizhen May 27 '19 at 07:44
  • building on a different machine is fine, but it should (HAS TO) be built with Android NDK tool chains. – shizhen May 27 '19 at 07:52
  • You are welcome! I answer stack overflow questions for earning reputation, please vote up my answer if it is helpful to you. Thanks! – shizhen May 27 '19 at 08:01
0

You can use android-ndk samples as an example (examples below). Here is the link to android dev manuals - explanation of Native libraries. And here is a same question on stack - link.

On ubuntu the path to static/shared libraries are here (it's android-ndk example):

hello-jni/app/src/main/jniLibs/ [processor] / [your library]

[ Including a library, java file ]

static {
        System.loadLibrary("hello-jni");
}

[ Cmake file ]

cmake_minimum_required(VERSION 3.4.1)

add_library(hello-jni SHARED
            hello-jni.c)

#Include libraries needed for hello-jni lib
target_link_libraries(hello-jni
                      android
                      log)
piet.t
  • 11,718
  • 21
  • 43
  • 52
Bulat
  • 720
  • 7
  • 15
  • But i need to link a static library which has been built on a different machine – Maddy26 May 27 '19 at 07:02
  • "Accoding to the JEP 178 you linked to in your comment, you don't have to do anything differently. System.loadLibrary will now load both dynamic and static libraries" and "/app/src/main/jniLibs/ [processor] / [your library]" – Bulat May 27 '19 at 07:02
  • Still i have the error : error: undefined reference to 'Test_C_Interface()' clang++.exe: error: linker command failed with exit code 1 (use -v to see invocation) ninja: build stopped: subcommand failed. Even though the library path is updated in CMakeCache.txt – Maddy26 May 27 '19 at 07:10
  • Hello Maddy! It's possible that you got these .a static binaries without building them using Android NDK toolchain. Even Linux static files on build generate .a files. So you must be clear that the .a file that you are trying to link was generated using Android NDK tool chain. – Rathnavel Jan 07 '20 at 07:14