0

I'm trying to modify this tutorial to include a prebuilt C library in my Android Studio project (ie. not using the experimental Gradle plugin) http://kvurd.com/blog/compiling-a-cpp-library-for-android-with-android-studio/

The library itself is coming from a client who won't reveal the source code, therefore I have no control over that part of the build process, however they are already following the same tutorial.

The project builds, load-library works and the NDK link (/jni/my-wrapper.c) works fine, until I try to call the actual library function defined in my prebuild header. The error I'm receiving is:

$ ndk-build [arm64-v8a] Compile : my-wrapper <= my-wrapper.c [arm64-v8a] SharedLibrary : libmy-wrapper.so /Users/me/AndroidStudioProjects/MyProject/app/obj/local/arm64-v8a/objs/my-wrapper/my-wrapper.o: In function `Java_com_my_project_SignInActivity_CallFunction': /Users/me/AndroidStudioProjects/MyProject/app/jni/my-wrapper.c:44: undefined reference to `MyFunction' collect2: error: ld returned 1 exit status make: *** [/Users/me/AndroidStudioProjects/MyProject/app/obj/local/arm64-v8a/libmy-wrapper.so] Error 1 

Here's my Android.mk:

LOCAL_PATH := $(call my-dir) # static library info include $(CLEAR_VARS) LOCAL_MODULE := libMyLib LOCAL_MODULE_FILENAME := libMyLib LOCAL_SRC_FILES := ../prebuild/libMyLib.a LOCAL_EXPORT_C_INCLUDES := ../prebuild/include include $(PREBUILT_STATIC_LIBRARY) # wrapper info include $(CLEAR_VARS) LOCAL_C_INCLUDES += ../prebuild/include LOCAL_MODULE := my-wrapper LOCAL_SRC_FILES := my-wrapper.c LOCAL_STATIC_LIBRARIES := libMyLib include $(BUILD_SHARED_LIBRARY) 

And MyLib.h (note that foobar() works fine as it's in the header but as long as I'm calling MyFunction from within my-wrapper.c the ndk-build fails):

#include <math.h> #include <setjmp.h> #include <stdio.h> #include <stdlib.h> #include <string.h> int MyFunction(some stuff); int foobar(){return 1;}; 

Finally, my-wrapper.c:

#include <MyLib.h> jbyte Java_com_my_project_SignInActivity_MyFunction(JNIEnv *env, jobject thiz, some other stuff){ // return MyFunction(some other stuff which I cast to C types); //linker fails if uncommented return foobar(); //works fine } 
2
  • 1
    Are you sure that MyFunction actually exists in the library? Since you don't have access to the source code, it's probably worth making sure. You can verify this using the nm tool included in the Android NDK. Commented Sep 14, 2016 at 13:02
  • nm libMyLib.a results in 0000458c T _Z12MyFunctionP9my_structPhS1_S1_ - so it looks like it's there unless there's some subtlety I'm missing Commented Sep 14, 2016 at 15:33

1 Answer 1

1

That's a C++ mangled name. You can only use it from C++, not from C.

If you really need to call it from C, you might be able to do it like so:

extern int _Z12MyFunctionP9my_structPhS1_S1_(/* whatever the function args are */); jbyte Java_com_my_project_SignInActivity_MyFunction( JNIEnv *env, jobject thiz, some other stuff) { return _Z12MyFunctionP9my_structPhS1_S1_(args); } 

That depends on the code you're calling being compatible as such (if that's the case, you should ask the client to build their APIs as extern "C").

I'd really recommend just moving your code to C++ though.

Sign up to request clarification or add additional context in comments.

3 Comments

Incredible! The client is insistent it's a C library though - is it possible they mistakenly compiled a C source to mangle the names into C++, by blindly following step 1 from kvurd.com/blog/… ? Would there be any side-effects to me simply transitioning the wrapper code to C++, in which case I should go back to them and ask to build the C lib properly. Sorry for basic questions, a C++ developer I am not!
Turns out the client had all their C code in .CPP files, which is what was confusing their compiler into producing mangled names instead of pure C libs.
Yeah, .cpp files will produce C++ mangled names by default. If they want to keep the .cpp files but still keep their API C compatible they just need to wrap their function decls with extern "C" (within #ifdef __cplusplus like the last snippet in stackoverflow.com/a/67985/632035).

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.