2012-07-05 27 views
1

我看過類似這個問題,但情況並不完全相同,我也無法獲得適用於我的問題的答案。Android:如何從您的JNI代碼使用現有的C++靜態庫?

我有一個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; 
} 

的makefile

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端,這些都是文件:

HELLO-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文件時得到的錯誤代碼是「未定義符號」,因此,是simple_library.a中的函數列表(實際上有1個函數)對hello-jni.c不可見因爲它是C++而不是普通的C?

您可能會注意到的另一件事是我試圖在自己的生成文件上生成靜態庫,而不是使用Android.mk生成它;這是有原因的,但是在這一點上我也會很高興,如果這需要我必須在Android.mk生成它。

我看不出有什麼辦法在這裏添加附件,以便與項目共享一個zip文件。 讓我知道是否有什麼我失蹤..否則代碼是在bitbucket的倉庫,所以我可以輕鬆地與任何人在那裏有一個帳戶分享。

謝謝你的答案。

+0

你能夠生成「so」文件嗎?按照這個http://marakana.com/forums/android/examples/49.html – 2012-07-05 16:38:37

+0

「_我試圖讓後者使用CPP,但編譯器抱怨_」具體是什麼? @Viktor響應,雖然在技術上是100%正確的,但如果您打算在庫上認真對待** C++ **,則可能不適用。 – 2012-07-05 21:45:14

+0

我的確打算在C++上認真對待,所以恐怕他的解決方案不夠好。這不是他的錯,我猜想示例C++代碼與不使用任何C++特定功能一樣簡單。 – 2012-07-17 11:14:21

回答

6

你寫了很多正確的東西,但你只缺少一個。

該函數的名字在C++中受到了損壞。在.so文件中,您不會看到「添加」符號,而是像「Add @ 8i」。爲避免損壞,只需在.cpp文件和.h文件中使用

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

聲明。

通常一個還增加了

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

/// Your usual C-like declarations go here 

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

而且

extern "C" 

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

+0

在所有關於這個答覆的正確性方面,OP都在討論第三方作爲** C++ **庫的可用性。所以他可能想要使用一些C++的權力,然後他很快就會錯過這個混亂。 – 2012-07-05 21:43:39

+1

感謝您的評論。這是我發現的唯一真正的問題。 OP在使用Add()函數時會得到「未解析的符號」。我只提到添加對jni的C文件不可見。爲了解決這個問題,只需要添加extern「C」修飾符。它只涉及到Add函數(等等),沒有必要避免使用C++。 – 2012-07-05 22:13:20

+0

大家好,謝謝大家的發帖。我在回答編號1(使用extern關鍵字)中遵循了建議,它的作用就像魅力一樣。我現在可以通過以下方式構建JNI共享庫:1)將靜態庫生成爲Android.mk中的任務的一部分; 2)使用預先編譯的庫,這是首選選項。我唯一擔心的是Viktor發現的那個。示例庫非常簡單,但實際上我需要使用C++。我會添加一些C++功能,看看我得到什麼錯誤(如果有的話)。 – 2012-07-17 11:07:09

相關問題