web-dev-qa-db-ja.com

Android NDK / JNI-カスタムヘッダーファイルで定義された関数への未定義の参照

JNIを使​​用して、Android NDKがカスタムヘッダーファイルで定義されたC関数を呼び出す)のネイティブC++メソッドを書き込もうとしています。しかし、未定義の参照エラーが発生します私のC関数呼び出し。

C関数を呼び出し、その結果をjstringとしてJavaに返す私のC++コードは次のとおりです。

#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ファイルに問題があると思います。

私はここで何が間違っているのか誰かに教えてもらえますか?

20
Pink Jazz

「未定義の参照」エラーは、リンカーから発生します。ヘッダーファイルはコンパイラのみを満たしています。

ただし、CとC++を混在させているため、問題はおそらく name mangling です。基本的に、C++コンパイラーに、呼び出そうとしている関数がC++ではなくCコンパイラーによって作成されたものであることを伝える必要があるため、引数の型コードがその名前に移植されていません。現時点ではそれが分からないので、リンカが実際に使用できる関数のプレーンなC名とは異なるC++スタイルの装飾名で関数を呼び出そうとしています。

これをあなたのジェスチャー_検出器.hファイルの最初に追加してください:

#ifdef __cplusplus
extern "C" {
#endif

そしてこれが最後に

#ifdef __cplusplus
}
#endif

そして、クリーンな再構築を行います。

実際のjniグルーロジックがここに示すバージョンと同じくらい簡単な場合は、Cバージョンに切り替えることもオプションになります。ただし、jni構文がCとC++では異なるため、ファイル拡張子を変更するだけでは不十分です。 。

32
Chris Stratton

単純にネイティブC++コードを実行する

extern "C" {
    your code
}

ここ で確認できるように、常に機能するとは限りません。

Android.mkファイルに追加してみてください。

LOCAL_ALLOW_UNDEFINED_SYMBOLS := true

ここでは、それについてさらに info を見つけます。

17
Jessica Cohen