简体   繁体   中英

Android ndk-build linker fails to find prebuilt library function

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
}

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM