Android and iOS development support C++ development, you can use a set of code for multiple platforms. At the same time, C++ is difficult to decompile features can also bring code secrecy for Android development, and another native feature can also improve the running efficiency of code.

Why C/C++

  1. Portable, libraries written in C/C++ can be easily reused on other platforms.
  2. Code protection, because Java layer code is easy to be decompiled, and C/C++ library integration is more difficult.
  3. To improve the efficiency of program execution, the application logic that requires high performance is developed in C/C++, thus improving the efficiency of application execution.
  4. To access an existing open source library, you need to access the underlying API or reference some C/C++ only library.

Ii. Introduction of development tools

Although Android Studio can write C++ and Java code at the same time, it can be compiled and run, but it is not very friendly to association and error prompts. I suggest that the overall code of C++ should be compiled and developed by Visual Studio or Xcode. The association function is very friendly and the compilation speed is very fast. Debugging is also very convenient.

  • Visual Studio (PC)
  • Xcode (Mac)
  • Android Studio (Multi-platform)
  • Eclipse (Multi-platform)

Third, the first line of code

1. How to use C++ in Objective-C projects

Using C/C++ in Objective-C is very easy, just change the.m file to.mm and use C++, we don’t usually write.mm files throughout the project, but design an interface that Bridges the two languages, and they interact only through this interface.

Important: String conversion
NSString * ocString = @"Hello World,OC";
std::string cppString = [ocString UTF8String];
std::cout<Copy the code

Remember to include related files

2. Programming with JNI in normal JAVA projects

Since I work on a MAC, here's how to do JNI development on a MAC, and Virtual Studio on Windows is very simple.

Step 1: create a normal C++ project under Xcode

Step 2: Associate the JavaVM Framework

Path:

/System/Library/Frameworks/JavaVM.framework/Frameworks/JavaNativeFoundation.framework/

Step 3: Create a header file to interact with Java cn_TAOWeiji_Nativemodule_nativeDemo.h
extern "C" {
    JNIEXPORT jint JNICALL Java_cn_taoweiji_nativemodule_NativeDemo_add
    (JNIEnv *, jclass, jint, jint);
    JNIEXPORT void JNICALL Java_cn_taoweiji_nativemodule_NativeDemo_say
    (JNIEnv *, jclass, jstring);
    JNIEXPORT jstring JNICALL Java_cn_taoweiji_nativemodule_NativeDemo_getInfo
    (JNIEnv *, jclass);
    JNIEXPORT void JNICALL Java_cn_taoweiji_nativemodule_NativeDemo_nativeToJava
    (JNIEnv *, jclass, jobject);Copy the code
Step 4: Create an implementation of NativeDemo.cpp
JNIEXPORT jint JNICALL Java_cn_taoweiji_nativemodule_NativeDemo_add(JNIEnv *, jclass, jint param1, jint param2)
    jint result = param1 + param2;
    return result;
    JNIEXPORT void JNICALL Java_cn_taoweiji_nativemodule_NativeDemo_say(JNIEnv *env, jclass, jstring param)
    const char *param_char = env->GetStringUTFChars(param, NULL);
    std::string str = param_char;
    JNIEXPORT jstring JNICALL Java_cn_taoweiji_nativemodule_NativeDemo_getInfo(JNIEnv *env, jclass)
    std::string str = "Hi,I am C++.";
    jstring result =  env->NewStringUTF(str.c_str());
    return result;
    JNIEXPORT void JNICALL Java_cn_taoweiji_nativemodule_NativeDemo_nativeToJava(JNIEnv * env, jclass, jobject obj)
    jclass cls = env->FindClass("cn/taoweiji/nativemodule/NativeDemo");
    jmethodID mid = env->GetMethodID(cls, "subtract", "(II)I");
    int result = (int) env->CallIntMethod(obj, mid, 10, 2);Copy the code
Step 5: Build and generate the JNI file, press ⌘+B (Product -> Build).

Compiled file

According to their own computer environment, to find the compiled file, my path is

/Users/Wiki/Library/Developer/Xcode/DerivedData/DEMO_MAC_JNI-clxymnzifegyfaajsaattzgxqfbr/Build/Products/Debug/DEMO_MAC_ JNI

Step 6: Write the JNI interface
package cn.taoweiji.nativemodule; Cn_taoweiji_nativemodule_nativedemo. h public class NativeDemo {public static native int add(int param1, int param2); public static native void say(String name); public static native String getInfo(); public static native void nativeToJava(NativeDemo nativeDemo); public int subtract(int param1, int param2) { System.out.println("NativeDemo:" + String.format("%s - %s = %s", param1, param2, param1 - param2)); return param1 - param2;Copy the code
Step 7: call C++
public class Main { static { System.load("/Users/Wiki/Library/Developer/Xcode/DerivedData/DEMO_MAC_JNI-clxymnzifegyfaajsaattzgxqfbr/Build/Products/De bug/DEMO_MAC_JNI"); public static void main(String[] args) { System.out.println("Hello World!" ); int result = NativeDemo.add(1, 2); System.out.println("1+2=" + String.valueOf(result)); NativeDemo.say("Hello,I am Java."); System.out.println("getInfo:" + NativeDemo.getInfo()); NativeDemo.nativeToJava(new NativeDemo());Copy the code

3. Use NDK in ANDROID projects

Android JNI development, C++ files must be written in a separate module, Java interface code can be written in app(module), and C++ in the same module, through gradle association. Detailed code please download demo to browse

Gradle configuration (NativeModule) apply plugin: Library 'android {compileSdkVersion 23 buildToolsVersion "24.0.0rc2" defaultConfig {minSdkVersion 14 TargetSdkVersion 23 versionCode 1 versionName "1.0" buildTypes {release {minifyEnabled false proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' NDK {moduleName "joyrun" STL "stlport_static" ldLibs "log"// used to resolve __android_log_print abiFilters "armeabi", "armeabi-v7a", "x86", "x86_64", "arm64-v8a" //add -fexceptions to allow throw error //add -w to "format not a string literal and no format arguments [-Werror=format-security" cFlags "-w -fexceptions" dependencies { compile fileTree(dir: 'libs', include: ['*.jar'])Copy the code

Write the JNI interface

// NativeDemo.java
package cn.taoweiji.nativemodule;
public class NativeDemo {
    public static native int add(int param1, int param2);Copy the code

Write C++ interface code, JNI file directory default is module/ SRC /main/ JNI, can be changed through gradle configuration

// cn_taoweiji_nativemodule_NativeDemo.h
#include 
#ifndef _Included_cn_taoweiji_nativemodule_NativeDemo
#define _Included_cn_taoweiji_nativemodule_NativeDemo
#ifdef __cplusplus
extern "C" {
#endif
 * Class:     cn_taoweiji_nativemodule_NativeDemo
 * Method:    add
 * Signature: (II)I
 JNIEXPORT jint JNICALL Java_cn_taoweiji_nativemodule_NativeDemo_add(JNIEnv *, jclass, jint, jint);
#ifdef __cplusplus
#endif
#endifCopy the code

// NativeDemo.cpp
#include "cn_taoweiji_nativemodule_NativeDemo.h"
JNIEXPORT jint JNICALL Java_cn_taoweiji_nativemodule_NativeDemo_add(JNIEnv *, jclass, jint param1, jint param2)
    jint result = param1 + param2;
    return result;Copy the code

call

Static {system.loadLibrary ("joyrun"); Int result = nativedemo.add (1,2); Log.i("1+2=",String.valueOf(result));Copy the code

Key points of NDK development

Compile file analysis

Zip: jNI: armeabi, armeabi-v7a, x86, x86_64, arm64-v8a, etc. To open so you can see in the lib prefix format file, it is the native is compiled file, we usually refer to third-party libraries (baidu map) is also to add these files to our libs folder, different names represents a different platform related to compile files, most of mobile phones on the market are the arm CPU, X86 phones are almost not used (GenyMotion emulator belongs to x86 platform), so we usually release APP without considering x86 platform and just add armeabi file. However, it is suggested to add X86 SO file during development to facilitate us to run on the emulator.

The runtime

The Android platform comes with a miniature C runtime support library called the system runtime. The runtime does not support the C standard library, exception support, and RTTI support. The NDK provides several additional C++ runtimes to complement the system runtime functionality.

C + + runtime C++ exception support C++RTTI C + + standard library
System libraries No No No
GAbi++ No Yes No
STLport No Yes Yes
GNU STL Yes Yes Yes
  1. STLport

    STLport is an open source, multi-platform implementation of the C standard library. It provides a complete collection of C library headers and RTTI support.

  2. GNU STL

    The GNU standard C library, also called libstDC-v3, is the most comprehensive standard C runtime for the Android NDK. It is an open source project being developed to implement the ISO standard C library.

Gradle configuration

  1. STL runtime reference
  2. Armeabi, Armeabi-V7A, x86, X86_64, ARM64-V8A and other platform configurations
  3. C++ output logcat configuration
  4. A compilation exception resolved
  5. Exception handling
    STL "stlport_static"//gnustl_static // abiFilters "armeabi", "armeabi-v7a", "x86", "x86_64", Add-fexceptions to allow throw error //add -w to "format not a string literal and no format arguments [-Werror=format-security" cFlags "-w -fexceptions"Copy the code

LOGCAT output

#include 
#define LOGI(...)  __android_log_print(ANDROID_LOG_INFO, "tag_joyrun", __VA_ARGS__)
#define LOGE(...)  __android_log_print(ANDROID_LOG_ERROR, "tag_joyrun", __VA_ARGS__)
LOGE("Hello Logcat");Copy the code

Type conversion

// std::string -> jstring std::string str = "Hello World"; jstring result = env->NewStringUTF(str.c_str()); // jstring -> std::string jstring param; const char *param_char = env->GetStringUTFChars(param, NULL); std::string str = param_char; // jboolean Two values JNI_TRUE and JNI_FALSECopy the code

C++ calls JAVA code

//Java

public static native void nativeToJava(NativeDemo nativeDemo);
public int subtract(int param1, int param2) {
Log.e("NativeDemo", String.format("%s - %s = %s", param1, param2, param1 - param2));
return param1 - param2;Copy the code

//C++

JNIEXPORT void JNICALL Java_cn_taoweiji_nativemodule_NativeDemo_nativeToJava(JNIEnv * env, jclass, Jobject obj) / / call the Java method jclass CLS = env - > FindClass (" cn/taoweiji nativemodule/NativeDemo "); jmethodID mid = env->GetMethodID(cls, "subtract", "(II)I"); int result = (int) env->CallIntMethod(obj, mid, 10, 2); //String getInfo(); //-> ()Ljava/lang/String; //PackageInfo getPackageInfo(String packageName, int flags); //-> (Ljava/lang/String; I)Landroid/content/pm/PackageInfo;;Copy the code

One-click generation of JAVA to C++ interface code scripts

File: autojavah. Sh

#! /bin/sh export ProjectPath=$(cd ".. /$(dirname "$1")"; pwd) export TargetClassName="co.runner.app.jni.NativeDemo" export SourceFile="${ProjectPath}/app/src/main/java" export TargetPath="${ProjectPath}/jni-joyrun/src/main/jni" cd "${SourceFile}" javah -d ${TargetPath} -classpath "${SourceFile}"  "${TargetClassName}" echo -d ${TargetPath} -classpath "${SourceFile}" "${TargetClassName}"Copy the code

C++ object-oriented and standard library introduction

C + + class definition
class Demo{
public:
    std::string name;
    int age = 0;
    void say();
    static int add(int param1,int param2)
        return param1 + param2;Copy the code
Class method implementation
void Demo::say()
    std::cout<<"name = "<Copy the code

Object creates and accesses members of the object
Demo d1; Demo * d2 = new Demo; d1.say(); d2->say(); Int result = Demo: : add (1, 2); std::cout<<"1 + 2 = "<Copy the code

LIST the LIST
std::list * demos = new std::list; Demo * demo = new Demo; demo->name = "Wiki"; demo->age = 24; demos->push_back(*demo); demo = new Demo; demo->name = "Wiki2"; demo->age = 25; demos->push_front(*demo); for (std::list::iterator iter = demos->begin(); iter ! = demos->end(); ++iter) { iter->say(); for (std::list::reverse_iterator iter = demos->rbegin(); iter ! = demos->rend(); ++iter) { iter->say(); std::list::iterator iter = demos->begin(); advance(iter, 1); iter->say();Copy the code
Pointers, references, and values

In C++, functions can pass parameters in many different ways, such as through Pointers, references, or directly.

void handle1(Demo *p);
void handle1(Demo& p);
void handle1(Demo *demo);Copy the code

Understanding heap and stack
  • Stack: automatically distributed by the operating system to store function parameter values, local variable values, etc. It operates like a stack in a data structure;
  • Heap: usually allocated and released by the programmer. If not, the program may be recycled by the OS at the end of the program. Allocation is similar to a linked list.
    Demo d1;
    Demo * d2 = new Demo;
    char c; 
    char *p = new char[3]; Copy the code
The garbage collection

The new and C++ delete operators are used to dynamically allocate and delete memory.

Vi. Common Methods and precautions in Development (pit)

  • Time stamp method.

  • Pay attention to so file security problems.

  • Try to avoid calling platform-specific methods to avoid migration problems.
  • The package name of the JNI interface cannot contain the underscore '_'.
Related source code: