Android NDK / JNI - 对自定义头文件中定义的函数的未定义引用

时间:2014-03-03 22:46:08

标签: android c++ c android-ndk java-native-interface

使用JNI,我正在尝试为Android NDK编写一个本机C ++方法,该方法调用自定义头文件中定义的C函数。但是,我的C函数调用收到了一个未定义的引用错误。

这是我的C ++代码,它调用C函数并将其结果作为jstring返回给Java:

#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));
}

这是我的C函数:

#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";
}

这是我的Android.mk代码:

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)

显然,似乎找不到自定义头文件(gesture_detector.h)中定义的函数定义。我认为这可能是我的Android.mk文件中的一个问题。

有谁能告诉我这里我做错了什么?

2 个答案:

答案 0 :(得分:32)

“未定义的引用”错误来自链接器。您的头文件只满足编译器。

但是,由于您正在混合使用C和C ++,因此问题很可能name mangling。基本上,您需要告诉C ++编译器您尝试调用的函数是由C编译器而不是C ++编译器创建的,因此没有将参数类型代码移植到其名称上。现在它不知道,所以试图通过C ++样式修饰的名称调用该函数,该名称不同于链接器实际可用的函数的普通C名称。

在gesture_detector.h文件的开头添加:

#ifdef __cplusplus
extern "C" {
#endif

最后这个

#ifdef __cplusplus
}
#endif

进行干净的重建。

如果您的真正的jni胶合逻辑与此处提供的版本一样简单,那么切换到C版本也可以是一个选项 - 但要注意J和C语言在C和C ++中是不同的,所以你不能只是改变文件扩展名。

答案 1 :(得分:17)

简单地使用本机C ++ -

之间的代码
extern "C" {
    your code
}

某些事情并非总是有效 - 因为您可以查看here

尝试添加到Android.mk文件:

LOCAL_ALLOW_UNDEFINED_SYMBOLS := true

在这里您可以找到关于它的更多info