簡體   English   中英

Android:如何使用JNI代碼中的現有C ++靜態庫?

[英]Android: How to use an existing C++ static library from your JNI code?

我見過與此問題類似的問題,但情況並不完全相同,也無法獲得適用於我的問題的答案。

我有C ++庫的源代碼。 我們需要將此庫用作android應用程序的一部分,但也需要第三方將其用作C ++庫。

我有一個makefile,它使用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)

Application.mk

APP_MODULES := my_simple_library hello-jni

就像我說的那樣,問題出在我真正利用Java應用程序中jni本機代碼中庫中的功能時。

現在,我不再確定我的問題是在靜態庫的makefile中還是在Android.mk中。 我首先認為它一定與庫本身的生成有關,但是在這一點上,看到Android.mk中有很多我不知道的選項之后,我不得不承認我毫無頭緒。

還有什么..?

哦,是的,我還注意到我的純C ++庫正在使用cpp擴展名,而Java項目中的jni代碼正在使用c擴展名。 我試圖讓后者也使用cpp,但是編譯器抱怨。 這可能是問題的一部分嗎?

我嘗試編譯Android.mk文件時收到的錯誤代碼是“未定義符號”,因此hello-jni.c無法看到simple_library.a中的功能列表(實際上有1個功能) C ++而不是普通的C?

您可能會注意到的另一件事是,我正在嘗試在自己的Makefile上構建靜態庫,而不是使用Android.mk生成它。 這是有原因的,但是在這一點上,如果需要這樣做的話,我也很高興如果必須將其由Android.mk生成。

我看不到在此處添加附件以便與項目共享zip的任何方法。 讓我知道是否丟失了某些內容。否則,代碼位於bitbucket的軟件倉庫中,因此我也可以輕松地與那里有帳戶的任何人共享該代碼。

謝謝你的回答。

您寫了很多正確的東西,但您只缺少其中的一件。

該函數的名稱在C ++中被修飾。 在.so文件中,您不會獲得“添加”符號,而是會出現“ Add @ 8i”之類的符號。 為避免損壞,請使用

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

.cpp文件和.h中的聲明。

通常情況下,還會添加

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

/// Your usual C-like declarations go here

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

而且

extern "C"

.cpp文件中的每個導出函數。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM