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?
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With