c++ – Android NDK / JNI – undefined reference to function defined in custom header file-ThrowExceptions

Exception or error:

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?

How to solve:

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.

Leave a Reply

Your email address will not be published. Required fields are marked *