简体   繁体   English

将CPP应用程序移植到Android

[英]Porting a CPP application to Android

I need to port a CPP project to Android but I somehow got stuck because of the following things that I am not sure of: 我需要将CPP项目移植到Android但是由于以下不确定的原因,我被卡住了:

  1. Do I need to use some kind of java wrapper for my CPP project at all, ie is it necessarily that I use Android SDK to integrate my application with Android ? 我的CPP项目是否需要使用某种Java包装器,即是否一定要使用Android SDK将应用程序与Android集成? If there is another way, which one would that be? 如果还有另一种方法,那将是哪一种?

  2. I have seen some people claiming they have been able to manipulate their cmake file and some custom android-cmake toolchain to build their “.so” or eventually an “.apk” from their project. 我见过有人声称他们已经能够操纵自己的cmake文件和一些自定义的android-cmake toolchain来从其项目中构建其“.so”或最终成为“.apk” Would it be possible without a java wrapper to manipulate the cmake files of the cpp project to build your project? 如果没有java包装器,是否有可能操纵cpp项目的cmake文件来构建您的项目? (source: Build Android NDK project with Cmake ) (来源: 使用Cmake构建Android NDK项目

From my experience, I would go with using the android java entry point, otherwise you will most likely bump into problems (you can make full native android apps , but I strongly advise against it). 根据我的经验,我会使用android java入口点,否则您很可能会遇到麻烦(您可以制作完整的本机android应用程序,但我强烈建议您这样做)。

One of the reasons is that you will want SDK function calls from inside your CPP, and using reflection on the java environment from CPP isn't trivial. 原因之一是您希望从CPP内部调用SDK函数,并且在CPP上对Java环境进行反射并不是一件容易的事。

The steps would be the following : 步骤如下:

  1. Create a very simple C code that will server as bridge to your CPP code . 创建一个非常简单的C代码,它将作为您CPP代码的桥梁。 Here are some sample C functions that I've commonly used : 这是我常用的一些示例C函数:
    • OnApplicationStart OnApplicationStart
    • OnApplicationPaused OnApplicationPaused
    • OnApplicationResumed OnApplicationResumed
    • OnApplicationUpdate OnApplicationUpdate
    • OnTouchReceived OnTouchReceived
  2. Export these functions and load them in your Java code (lookup JNI on how to do this) 导出这些函数并将其加载到您的Java代码中(有关如何执行此操作的查找JNI)
  3. Handle all Android-specific actions in Java, and all application specific actions in cpp 处理Java中所有Android特定操作,以及cpp中所有应用特定操作

So the answer to your 1st question is that a java wrapper isn't mandatory, but it's HIGHLY recommended. 因此,第一个问题的答案是Java包装器不是必需的,但强烈建议使用。

To answer your 2nd question : 要回答您的第二个问题:

Yes, you can use cmkae, ant, cygwin , allot of command tools that will end up creating your apk (It's up to you on how you feel comfortable).You will still use the android compiler since you are targeting arm. 是的,您可以使用cmkae,ant,cygwin,命令工具分配,这些命令工具最终将创建apk(取决于您的舒适程度)。由于您的目标是arm,因此您仍将使用android编译器。

The difference is that you need to change in your manifest.xml the entry point of the application from a normal activity to a native activity ( http://developer.android.com/reference/android/app/NativeActivity.html ) . 区别在于,您需要在manifest.xml中将应用程序的入口点从正常活动更改为本地活动( http://developer.android.com/reference/android/app/NativeActivity.html )。

As you can see, the difference isn't the build system, it's the way you define your entry point. 如您所见,差异不是构建系统,而是定义入口点的方式。

As a friendly advice, try using the minimal java wrapper approach. 作为友好的建议,请尝试使用最少的Java包装器方法。 You might get to better results sooner, and it won't take you more then 1 week of research on the web on how to link java code to cpp. 您可能会更快地获得更好的结果,并且在Web上花了不到1周的时间进行有关如何将Java代码链接到cpp的研究。

EDIT : 编辑:

As of demand, I will shortly explain how I would approach the process of porting a CPP application to Android : 根据需求,我将简要说明如何将CPP应用程序移植到Android的过程:

  1. Rethink your application to work as a shared library , using a C entry point : 使用C入口点重新考虑将应用程序用作共享库:

a.Create a simple C application that will load yourCPPApp.dll (or .so if you are on linux) 创建一个简单的C应用程序,该应用程序将加载yourCPPApp.dll(如果在Linux上则为.so)

b. In your .dll create the minimum necessary extern "C" functions to be exported in order for you to give the necessary information to your dll 在您的.dll中,创建要导出的最小必需的extern“ C”函数,以便为您的dll提供必要的信息

For simplicity, we'll assume we have 3 methods : 为了简单起见,我们假设我们有3种方法:

 void StartApplication();
 bool OnApplicationUpdate();
 void OnScreenTouched(int x, int y);

c. C。 Implement the simple C project that will make the calls to these methods externaly (so the .exe will call the methods from the .dll ! ) 实现一个简单的C项目,该项目将在外部调用这些方法(因此.exe将从.dll调用这些方法!)

Sample code : 样例代码:

 #include "myCPPapp.h"
 int main(int arg, char** argv)
 {
      StartApplication();
      srand(time(NULL));
      while (OnApplicationUpdate())
      {
          // we assume we have a 480x640 resolution
          OnScreenTouched(rand()%480,rand()%640);
      }
      return 0;
 }
  1. Now that we have things working in full native with a .exe and a .dll , time to make it work with a .apk and a .so 现在,我们已经可以使用.exe和.dll在完全本机环境中工作,现在可以使用.apk和.so了。

a. 一种。 Rename the exposed methods from myCppApp into java compatible prototypes 将myCppApp中公开的方法重命名为Java兼容的原型

extern "C" {
    JNIEXPORT void JNICALL Java_com_sample_nativebridge_OnApplicationStart(JNIEnv env, jobject thiz);
    JNIEXPORT jboolean JNICALL Java_com_sample_nativebridge_OnApplcationUpdate(JNIEnv env, jobject thiz);
    JNIEXPORT void JNICALL Java_com_sample_nativebridge_OnScreenTouched(JNIEnv env, jobject thiz, jint x, jint y);
}

b. create the java class nativebridge (case sensitive) in the package com.sample (you need t respect the names in order for correct linkage to native) 在com.sample包中创建java类nativebridge(区分大小写)(您无需尊重名称即可正确链接到native)

class nativebridge {
    public static native void OnApplicationStart();
    public static native boolean OnApplicationUpdate();
    public static native void OnScreenTouched(int x, int y);
}

c. C。 add the load library statement in the native bridge in order to have your library loaded at runtime 在本机桥中添加加载库语句,以便在运行时加载您的库

class nativebridge {
  ....
  static {
    System.loadLibrary("myCppApp"); 
    // notice that the lib prefix and .so sufix aren't part of the name
  }
}

d. d。 compile your CPP code with the armeabi compiler and create libmyCPPApp.so (ndk build system , or whatever you'd like... i would go with the ndk, it's quite easy , just go into the folder with Android.mk and call $ANDROID_NDK_BUILD_PATH/build ) 使用armeabi编译器编译CPP代码并创建libmyCPPApp.so(ndk构建系统,或者您想要的任何东西...我会使用ndk,这很容易,只需使用Android.mk进入文件夹并调用$ ANDROID_NDK_BUILD_PATH / build)

At this point you will need to createa a .mk file that will compile your myCppApp code, but this is out of scope, you will need to do this research on your own (it's quite trivial once you get the hang of it). 此时,您将需要创建一个.mk文件,该文件将编译myCppApp代码,但是这超出了范围,您将需要自己进行这项研究(一旦掌握了它,这很简单)。

c. C。 use the native methods from the bridge inside your java app wherever you see fit. 在您认为合适的地方,使用Java应用程序内部桥中的本机方法。

A very good tip would be to go through a hello world sample of ndk : 一个很好的技巧是遍历ndk的世界示例:

http://www.ntu.edu.sg/home/ehchua/programming/android/android_ndk.html http://www.ntu.edu.sg/home/ehchua/programming/android/android_ndk.html

Enjoy. 请享用。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM