2014-03-03 39 views
18

使用JNI,我想爲Android NDK編寫一個本地C++方法,它調用定製頭文件中定義的C函數。但是,我正在爲C函數調用收到未定義的引用錯誤。Android NDK/JNI - 未定義的自定義頭文件中定義的函數引用

這裏是我的C++代碼,可以調用C函數和它的結果返回給Java作爲一個的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)); 
} 

這裏是我的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文件中的問題。

誰能告訴我我在這裏做錯了什麼?

回答

16

簡單地做你的本地C++ - 代碼

之間

extern "C" { 
    your code 
} 
的東西,並不一定必然的工作 - 你可以檢查 here

嘗試添加到Android.mk文件:

LOCAL_ALLOW_UNDEFINED_SYMBOLS := true 

這裏你可以找到進一步info它。

+2

也許,但有風險。這將掩蓋問題,直到運行時。但是,如果在這一點上無法解決,程序將崩潰。 –

+0

@ChrisStratton - 感謝您的評論。其他一些建議? –

+1

是的,考慮到C/C++拆分它可能是一個名稱修復問題。 –

30

「未定義參考」錯誤來自鏈接器。您的頭文件只滿足編譯器。

但是,由於您正在混合使用C和C++,因此您的問題可能是name mangling。基本上,你需要告訴C++編譯器你試圖調用的函數是由C編譯器創建的,而不是C++編譯器創建的,因此沒有將參數類型代碼嫁接到其名稱上。現在它不知道,所以試圖通過C++風格裝飾名稱來調用該函數,該名稱不同於鏈接器實際可用的函數的純C名稱。在結束

#ifdef __cplusplus 
} 
#endif 

#ifdef __cplusplus 
extern "C" { 
#endif 

而這,做一個乾淨的重建:

你gesture_detector.h文件的開頭添加這一點。

如果你真正的jni glue logic與這裏提供的版本一樣微不足道,切換到C版本也可能是一個選項 - 但要注意jni語法在C和C++中是不同的,所以你不能只是更改文件擴展名。

+0

是的,你是這個答案! –