使用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文件中的一个问题。
有谁能告诉我这里我做错了什么?
答案 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)