2011-06-21 56 views
34

所有ndk樣本僅使用在頭文件中聲明爲extern並在cpp文件中定義的基本C函數。然後在包含jni回調的C文件中包含頭文件後,一切正常。在Android中使用C++ ndk/jni

是否有可能使用android ndk的C++類?我的應用程序不會是一個本地活動,它仍然有一個重要的Java部分,但它會調用CPU密集型計算的本機C代碼(已經用C++編寫,帶有類和其他C++東西)。

這是我打招呼世界狀晶格結構現在:

文件 「first.h」

#ifndef FIRST_H 
#define FIRST_H 

class Test 
{}; 

#endif /* FIRST_H */ 

文件 「second.cpp」

#include <jni.h> 
#include "first.h" 

#ifdef __cplusplus 
extern "C" { 
#endif 

jint Java_com_example_twolibs_TwoLibs_add(JNIEnv* env, 
             jobject this, 
             jint  x, 
             jint  y) 
{ 
    Test t; 
    return 0; 
} 

#ifdef __cplusplus 
} 
#endif 

最後Android.mk

LOCAL_PATH := $(call my-dir) 

include $(CLEAR_VARS) 

LOCAL_MODULE := libtwolib-second 
LOCAL_SRC_FILES := second.cpp 

include $(BUILD_SHARED_LIBRARY) 

Prett Ÿ基本但不能編譯。在.c文件中加入second.cpp會引發包含頭文件的錯誤,我想這是因爲它不是C++文件。

error: expected '=', ',', ';', 'asm' or '__attribute__' before 'Test' 

製作它的.cpp引發以下錯誤:

make: *** No rule to make target `/cygdrive/c/android-ndk-r5c/samples/twolibs/jni/second.c', needed by `/cygdrive/c/android-ndk-r5c/samples/two-libs/obj/local/armeabi/objs/twolib-second/second.o'. Stop. 

任何想法,我怎麼可以讓那個東西編譯?

謝謝

回答

15

您可以將C++與NDK一起使用,但使用C++代碼的文件必須具有.cpp擴展名。

ANDROID-MK.html

Note that the default extension for C++ source files is '.cpp'. It is however possible to specify a different one by defining the variable LOCAL_CPP_EXTENSION. Don't forget the initial dot (i.e. '.cxx' will work, but not 'cxx').

+0

看起來好像回調C代碼(包含諸如Java_com_example_twolibs_TwoLibs_add之類的調用的文件將從java端調用)必須位於.c文件(不是.cpp)中。否則,它不會在我的機器上編譯。因此,當我試圖包含一個包含類聲明的頭文件時,會出現相同的錯誤。 – user745189

+1

將一切轉換成.cpp文件給了我一個make:***沒有規則來製作目標錯誤,這意味着make文件找不到源文件......但是,如果我將它們轉換爲.c文件,一個路徑問題我猜想 – user745189

+0

它必須編譯,但是你需要爲所有JNI函數添加'external「C」'。你是否改變了makefile中的源文件擴展名? – Michael

3

您將不得不重新編譯所有專用於Android的本機庫。您確實需要所有您計劃使用的第三方本機庫的源代碼,因爲通常當我們在Android之外編譯和鏈接這些庫時,它們鏈接到glibc,但不幸的是Android由於顯示和性能問題而沒有使用glibc。 Android使用名爲libc的減水版glibc。對於大多數常用功能,它具有與glibc匹配的符號名稱。但據我所知,libc沒有與strings相關的一些功能,它絕對不支持posix。如果您的本機庫正在使用任何已棄用的功能,您必須通過使用libc支持的替代功能並相應地編碼您的庫來爲這些功能找到解決方法。

另外,正如你指出的那樣,你將不得不使用NDK將Java(Android app/fwk)連接到本地(C++)。

雖然這聽起來很簡單,但根據我的經驗,編譯Android上的本機庫(Android移植)傳統上非常耗時且不保證成功。

+0

感謝您的回答。實際上,我甚至無法開始移植我的第三方庫,因爲一旦我在其中使用了類,我甚至無法得到一個簡單的hello-world-like測試來編譯。第一步是創建一個幾乎空的本機C++測試類,並在我的jni回調C文件中使用它。只是爲了看看是否編譯。 – user745189

0

error: expected '=', ',', ';', 'asm' or '__ attribute __' before 'class'

缺少的經典案例 ';' class關鍵字之前?想象一下

int functionname(int p) 
class X { } ; 

這可能會導致您的編譯器消息很容易。一個常見的複雜因素是,當它實際上看起來像

#include "someheader.h" 
class X { } ; 

和錯誤是裏面someheader.h /或任何遞歸包含文件的最後聲明/;)

+0

這就是我一開始想的,但我檢查過,這不是一個語法錯誤 – user745189

1

關於你的編譯錯誤,好像你首先將其稱爲「second.c」,稍後將其重命名爲「second.cpp」,但目標文件中仍有「second.c」名稱,因此在編譯(bdk-build)之前,需要刪除* .o和* .d文件在/ cygdrive/c/android-ndk-r5c/samples/two-libs/obj/local/armeabi/objs/twolib-second /目錄中

0

運行:

ndk-build clean 

修改錯誤的Android.mk後,或者即使您修改了配置,構建也可能會繼續失敗。

我認爲這是OP的意思on this comment

0

編輯Android.mk

修改LOCAL_SRC_FILES的實例,並從每行的begginning除去./。