2

これに似た質問を見たことがありますが、シナリオはまったく同じではなく、問題に有効な回答を得ることもできません。

C++ ライブラリのソース コードがあります。このライブラリを Android アプリケーションの一部として使用する必要がありますが、サードパーティが C++ ライブラリとして使用できるようにする必要もあります。

ndk のコンパイラを使用して、ライブラリのソース コードから .a ファイルを生成するメイクファイルがあります。それが純粋な C++ の部分です。

Java 部分では、ボタンを含む単純なアクティビティを含む単純なデモ プロジェクトがあります。ボタンが押されると、ネイティブ コードが呼び出されます。

JNI 関数からライブラリの関数を呼び出そうとしない限り、すべて正常に動作します。

ライブラリのソースは次のとおりです。

SimpleMath.h

int Add(int aNumber1, int aNumberB);

SimpleMath.cpp

#include "SimpleMath.h"

int Add(int aNumberA, int aNumberB)
{
  return aNumberA + aNumberB;
}

メイクファイル

APP      = simple_app
LIBRARY  = simple_library.a
OBJECTS  = SimpleMath.o
CFLAGS   = -Wall -pedantic
NDK_PATH = /home/jug/perforce/jug_navui_personal_main/Env/Linux/Android/ndk/r7c
CXX      = $(NDK_PATH)/toolchains/arm-linux-androideabi-4.4.3/prebuilt/linux-x86/bin/arm-linux-androideabi-g++
AR       = $(NDK_PATH)/toolchains/arm-linux-androideabi-4.4.3/prebuilt/linux-x86/bin/arm-linux-androideabi-ar
SYSTEM_LIBS = -lstdc++ -lm
INCLUDE_PATH += ${NDK_PATH}/platforms/android-9/arch-arm/usr/include

all: $(LIBRARY)

$(LIBRARY): 
    $(CXX) -c SimpleMath.c
    $(AR) rcs simple_library.a SimpleMath.o

clean:
    rm *.o *.a

Java 側のファイルは次のとおりです。

こんにちは-jni.c

#include <string.h>
#include <jni.h>

#include "../../../native/simple_library/SimpleMath.h"

jstring Java_com_amstapps_samples_draft08jni_MainActivity_helloJni(JNIEnv* env, jobject obj)
{
    // Uncommenting the line below results in undefined-symbol compile error
    //int d = Add(1, 2);

    return (*env)->NewStringUTF(env, "Hello from JNI!");
}

Android.mk

LOCAL_PATH:= $(call my-dir)

include $(CLEAR_VARS)
LOCAL_MODULE := my_simple_library
LOCAL_ARM_MODE := arm
LOCAL_SRC_FILES := ../../../native/simple_library/simple_library.a
include $(PREBUILT_STATIC_LIBRARY)
#include $(BUILD_STATIC_LIBRARY)

include $(CLEAR_VARS)
LOCAL_MODULE_TAGS    := eng
LOCAL_ARM_MODE       := arm
#LOCAL_PRELINK_MODULE := false
LOCAL_MODULE         := hello-jni
LOCAL_SRC_FILES      := hello-jni.c
LOCAL_C_INCLUDES     := ../../../android/native/simple_library
LOCAL_STATIC_LIBRARIES := my_simple_library
#LOCAL_WHOLE_STATIC_LIBRARIES := my_simple_library
include $(BUILD_SHARED_LIBRARY)

アプリケーション.mk

APP_MODULES := my_simple_library hello-jni

先ほど言ったように、Java アプリケーションで jni ネイティブ コードからライブラリの機能を実際に利用するときに問題が発生します。

現在、問題が静的ライブラリの makefile にあるのか、Android.mk にあるのかわかりません。最初はライブラリ自体の生成に関係しているに違いないと思っていましたが、この時点で、Android.mk には私が知らなかった多くのオプションがあることを知ったので、手がかりがないことを認めざるを得ません。

ほかに何か..?

そうそう、私の純粋な C++ ライブラリは cpp 拡張機能を使用しているのに対し、Java プロジェクトの jni コードは c 拡張機能を使用していることにも気付きました。後者もcppを使用しようとしましたが、コンパイラーは文句を言います。これは問題の一部でしょうか?

Android.mk ファイルをコンパイルしようとしたときに表示されるエラー コードは「未定義のシンボル」であるため、simple_library.a の関数のリスト (実際には 1 つの関数があります) は、hello-jni.c には表示されません。 C++ であり、プレーン C ではありませんか?

お気づきかもしれませんが、Android.mk で静的ライブラリを生成するのではなく、独自の makefile で静的ライブラリを構築しようとしています。それには理由がありますが、この時点で、それが必要な場合は Android.mk によって生成されなければならない場合も嬉しく思います。

プロジェクトと zip を共有するために、ここに添付ファイルを追加する方法がわかりません。不足しているものがあれば教えてください。それ以外の場合、コードは bitbucket のデポにあるので、そこにアカウントを持っている人と簡単に共有できます。

回答ありがとうございます。

4

1 に答える 1

7

あなたはたくさんの正しいことを書いていますが、1つだけ欠けています。

関数の名前はC++で混乱します。また、.soファイルでは、「追加」記号は表示されませんが、「Add@8i」のような記号が表示されます。マングリングを回避するには、

extern "C" int Add(int x, int y)

.cppファイルおよび.hでの宣言。

通常、1つはまた追加します

/// Some .h file
#ifdef __cplusplus
extern "C" {
#endif

/// Your usual C-like declarations go here

#ifdef __cplusplus
} // extern "C"
#endif

そしてその

extern "C"

.cppファイルでエクスポートされた関数ごとに。

于 2012-07-05T20:35:19.200 に答える