2011-06-21 58 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除去./。