Question

Using JNI, I am trying to write a native C++ method for the Android NDK that makes a call to a C function defined in a custom header file. However, I am getting an undefined reference error for my C function call.

Here is my C++ code that makes a call to the C function and returns its result to Java as a jstring:

#include <jni.h>

#include "gesture_detector.h"

JNIEXPORT jstring JNICALL Java_com_example_bmtitest_JavaAbstractionLayer_callGestureAnalysis(JNIEnv *env, jobject obj, jfloat previousX, jfloat previousY, jfloat currentX, jfloat currentY) {
    return env->NewStringUTF(gestureAnalysis(previousX, previousY, currentX, currentY));
}

Here is my C function:

#include <stdio.h>

#include "gesture_detector.h"

//implemented from gesture_detector.h
const char* gestureAnalysis(float previousX, float previousY, float currentX, float currentY)
{
    float xOffset = currentX - previousX;
    float yOffset = currentY - previousY;

    if(xOffset == 0 && yOffset == 0)
    {
        return "TAP";
    }
    return "0";
}

Here is my Android.mk code:

LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)

LOCAL_MODULE    := gestureDetector
LOCAL_SRC_FILES := gestureDetector.c NativeAbstractionLayer.cpp
LOCAL_LDLIBS    := -landroid

include $(BUILD_SHARED_LIBRARY)

Apparently, it seems the function definition defined in the custom header file (gesture_detector.h) isn't being found. I think it may be a problem in my Android.mk file.

Could anyone tell me what am I doing wrong here?

No correct solution

OTHER TIPS

An "undefined reference" error comes from the linker. Your header file only satisfied the compiler.

However, since you are mixing C and C++ your problem is likely name mangling. Basically, you need to tell the C++ compiler that the function you are trying to call was created by a C compiler rather than a C++ one, and so does not have argument type codes grafted onto its name. Right now it doesn't know that, so is trying to call the function by a C++ style decorated name which differs from the plain C name of the function the linker actually has available.

Add this at the beginning of your gesture_detector.h file:

#ifdef __cplusplus
extern "C" {
#endif

And this at the end

#ifdef __cplusplus
}
#endif

And do a clean rebuild.

If your real jni glue logic is as trivial as the version presented here, switching to a C version of that could also be an option - but beware that jni syntax is different in C and C++, so you can't just change the file extension.

Simply doing your native C++- code between

extern "C" {
    your code
}

Is something that not always will necessarily work - as you can check here.

Try adding to the Android.mk file:

LOCAL_ALLOW_UNDEFINED_SYMBOLS := true

Here you find further info about it.

In my case, my project was building properly but it started giving the 'undefined reference' error after I added two new files somefile.h and somefile.c. I added these files to the source directory of a existing library I built so no changes in cmake were required for referring to the new files. Cleaning and rebuilding project didn't work. However, I made some redundant changes in my CMakeLists.txt file and then did a clean rebuild. The build was successful. After that I removed this change (since it is redundant) and tried doing a clean rebuild again and the code was working. Maybe the build system was fetching some objects from cache, and changing CMakeLists.txt forced it to build the objects again from scratch. If anyone knows why such behaviour is observed please let me know. Thanks!

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top