+ All Categories
Home > Documents > Android NDKmobile.web.unc.edu/files/2017/04/gradlecture_ndk.pdfBranching constructs (if/else,...

Android NDKmobile.web.unc.edu/files/2017/04/gradlecture_ndk.pdfBranching constructs (if/else,...

Date post: 19-Mar-2020
Category:
Upload: others
View: 14 times
Download: 0 times
Share this document with a friend
53
Android NDK Federico Menozzi & Srihari Pratapa
Transcript
Page 1: Android NDKmobile.web.unc.edu/files/2017/04/gradlecture_ndk.pdfBranching constructs (if/else, switch) are identical to Java Looping constructs (for/while/do-while) are also identical

Android NDKFederico Menozzi & Srihari Pratapa

Page 3: Android NDKmobile.web.unc.edu/files/2017/04/gradlecture_ndk.pdfBranching constructs (if/else, switch) are identical to Java Looping constructs (for/while/do-while) are also identical

Android Stack

Page 4: Android NDKmobile.web.unc.edu/files/2017/04/gradlecture_ndk.pdfBranching constructs (if/else, switch) are identical to Java Looping constructs (for/while/do-while) are also identical

NDK? JNI? What?● NDK

○ Native Development Kit○ Allows developers to create Android applications with C/C++○ Uses JNI to allow for Java/native interop

● JNI○ Java Native Interface○ Allows for Java to call native (i.e. C/C++) code and vice-versa○ Used as a bridge between Android system and native code

Page 5: Android NDKmobile.web.unc.edu/files/2017/04/gradlecture_ndk.pdfBranching constructs (if/else, switch) are identical to Java Looping constructs (for/while/do-while) are also identical

What is C++?● High-performance systems-level programming language● Supports imperative, object-oriented, and functional programming patterns● Created to be a (nearly) strict superset of C

○ This means most C programs are also valid C++ programs

Page 6: Android NDKmobile.web.unc.edu/files/2017/04/gradlecture_ndk.pdfBranching constructs (if/else, switch) are identical to Java Looping constructs (for/while/do-while) are also identical

Who Cares About C++?● Literally everyone● People who care about performance● People who care about abstraction● Masochists● Used to create operating systems, web browsers, compilers/interpreters,

network stacks, database, graphics/game engines, etc.

Page 7: Android NDKmobile.web.unc.edu/files/2017/04/gradlecture_ndk.pdfBranching constructs (if/else, switch) are identical to Java Looping constructs (for/while/do-while) are also identical

C++ for Idiots Java Programmers

Page 8: Android NDKmobile.web.unc.edu/files/2017/04/gradlecture_ndk.pdfBranching constructs (if/else, switch) are identical to Java Looping constructs (for/while/do-while) are also identical

A Quick Word About C++...● Fiendishly complicated● Outrageously complex● Tutorial will focus on writing very basic C++ in a similar manner to Java

○ But C++ can do SO much more...

Page 9: Android NDKmobile.web.unc.edu/files/2017/04/gradlecture_ndk.pdfBranching constructs (if/else, switch) are identical to Java Looping constructs (for/while/do-while) are also identical

C++ Basics● Compiled, statically-typed (like Java)● Nearly backwards-compatible with C● Separates class/function declarations from definitions (unlike Java)

○ Declarations stored in header files (.h, .hpp, .hxx, etc.)○ Definitions stored in source files (.cc, .cpp, .cxx, etc.)

● Source files are compiled into object files, which then pass through the linker to become the final executable

Page 10: Android NDKmobile.web.unc.edu/files/2017/04/gradlecture_ndk.pdfBranching constructs (if/else, switch) are identical to Java Looping constructs (for/while/do-while) are also identical

C++ Program Lifecycle

Page 11: Android NDKmobile.web.unc.edu/files/2017/04/gradlecture_ndk.pdfBranching constructs (if/else, switch) are identical to Java Looping constructs (for/while/do-while) are also identical

Hello WorldHelloWorld.java (Java)

public class HelloWorld { public static void main(String[] args) { System.out.println( “Hello, World!” ); }}

Compile and run:

javac HelloWorld.java && java HelloWorld

HelloWorld.cpp (C++)

#include <iostream>

int main(int argc, char* argv[]) { std::cout << “Hello, World!\n” ;

return 0;}

Compile and run (uses GCC):

g++ HelloWorld.cpp -o hello && ./hello

Page 12: Android NDKmobile.web.unc.edu/files/2017/04/gradlecture_ndk.pdfBranching constructs (if/else, switch) are identical to Java Looping constructs (for/while/do-while) are also identical

C++ Basics - Primitive Types● Compared with Java’s nine primitive types (boolean, byte, char, short,

int, long, float, double, and void), C++ has many primitive types

Page 13: Android NDKmobile.web.unc.edu/files/2017/04/gradlecture_ndk.pdfBranching constructs (if/else, switch) are identical to Java Looping constructs (for/while/do-while) are also identical

C++ Basics - Control Flow● Branching constructs (if/else, switch) are identical to Java● Looping constructs (for/while/do-while) are also identical to Java

○ One exception: Java’s “for each” construct (for (Type t : collection) { … } ) is only available in C++11 and onwards

Page 14: Android NDKmobile.web.unc.edu/files/2017/04/gradlecture_ndk.pdfBranching constructs (if/else, switch) are identical to Java Looping constructs (for/while/do-while) are also identical

C++ Basics - Functions● Unlike Java, functions in C++ can be free-floating and not tied to a class● Otherwise, quite similar to Java

#include <cstdio>

// Print some values using C’s printf() functionvoid foo(int i, float f, bool b) {

std::printf(“i: %d, f: %f, b: %d\n”, i, f, b); }

Page 15: Android NDKmobile.web.unc.edu/files/2017/04/gradlecture_ndk.pdfBranching constructs (if/else, switch) are identical to Java Looping constructs (for/while/do-while) are also identical

C++ Basics - Functions

myfunc.h

// Declare function prototypevoid foo(int a);

myfunc.cpp

#include “myfunc.h”

// Define functionvoid foo(int a) {

// ...}

● Typically, C++ functions (and classes) are split into their declarations (header file) and their definitions (source file)

Page 16: Android NDKmobile.web.unc.edu/files/2017/04/gradlecture_ndk.pdfBranching constructs (if/else, switch) are identical to Java Looping constructs (for/while/do-while) are also identical

C++ Basics - Classes● Also fairly similar to Java● Can be defined with either class or struct keywords

○ struct member visibility defaults to public, class to private

● Unlike Java, classes can either be allocated on the stack or on the heap○ We’ll get back to this

Page 17: Android NDKmobile.web.unc.edu/files/2017/04/gradlecture_ndk.pdfBranching constructs (if/else, switch) are identical to Java Looping constructs (for/while/do-while) are also identical

C++ Basics - Classes

MyClass.h

// Declare class prototypeclass MyClass {public: MyClass(int n); // Constructor int n; // Fieldprivate: void foo(); // Method};

MyClass.cpp

#include “MyClass.h”

MyClass::MyClass( int n) {// ...

}

void MyClass::foo() {// ...

}

● Like functions, C++ classes are split into their declarations (header file) and their definitions (source file)

Page 18: Android NDKmobile.web.unc.edu/files/2017/04/gradlecture_ndk.pdfBranching constructs (if/else, switch) are identical to Java Looping constructs (for/while/do-while) are also identical

Detour - Stack vs Heap

Page 19: Android NDKmobile.web.unc.edu/files/2017/04/gradlecture_ndk.pdfBranching constructs (if/else, switch) are identical to Java Looping constructs (for/while/do-while) are also identical

C++ Basics - Classes#include “MyClass.h”

int main() {// Create new class instance on stack (memory// deallocated automatically at end of main())MyClass m1(1);m1.n = 42;

// Create new class instance on heap (memory// must be deallocated manually via delete!)MyClass* m2 = new MyClass(2);if (m2 != NULL) { // Or nullptr in C++11 and onwards

m2->n = 42;}delete m2;

}

Page 20: Android NDKmobile.web.unc.edu/files/2017/04/gradlecture_ndk.pdfBranching constructs (if/else, switch) are identical to Java Looping constructs (for/while/do-while) are also identical

C++ Basics - Arrays● Inherits arrays directly from C● Unlike Java arrays, C/C++ arrays can be allocated on either the stack or the

heap● Unlike Java arrays, C/C++ arrays are not objects

○ Basically just pointers to blocks of memory (whether stack or heap allocated)○ Don’t carry their length around with them

● So-called C-style strings are just arrays of char○ WARNING: C-style strings must include room for the null terminator ‘\0’

Page 21: Android NDKmobile.web.unc.edu/files/2017/04/gradlecture_ndk.pdfBranching constructs (if/else, switch) are identical to Java Looping constructs (for/while/do-while) are also identical

C++ Basics - Arraysint main() {

// Allocate an uninitialized array of 20 ints on stackint arr1[20];arr1[0] = 1;

// Allocate and initialize an array of 5 ints on stackint arr2[] = {1,2,3,4,5};

// Allocate an array of 20 ints on heap. Must be freed// manually using delete[] (note the brackets for arrays!)int* arr3 = new int[20];delete[] arr3;

}

Page 22: Android NDKmobile.web.unc.edu/files/2017/04/gradlecture_ndk.pdfBranching constructs (if/else, switch) are identical to Java Looping constructs (for/while/do-while) are also identical

C++ Basics - Arraysint main() {

// Allocate an uninitialized string of length 19 (plus null// terminator) on stackchar str1[20];

// Allocate and initialize a string of length 5 on stack with// room for the null terminatorchar str2[] = {‘H’, ‘e’, ‘l’, ‘l’, ‘o’, ‘\0’];

// Allocate and initialize a string from a string literal on stack, // which automatically includes the null terminator for youchar str3[] = “Hello”;

// Get pointer to READ-ONLY literal (stored in static section, can’t// be modified)const char* str4 = “Hello”;

// Allocate a string of length 19 (plus null terminator) on heap. // Must be freed manually using delete[] (note the brackets for arrays!)char* str5 = new char[20];delete[] str5;

}

Page 23: Android NDKmobile.web.unc.edu/files/2017/04/gradlecture_ndk.pdfBranching constructs (if/else, switch) are identical to Java Looping constructs (for/while/do-while) are also identical

Arrays and C-Style Strings Suck● Don’t use them

○ Too many ways to do it wrong○ Must manually keep track of length/capacity○ If dynamically allocated, must free memory yourself

● They exist purely for compatibility with C● For C++, we have std::vector<T> and std::string, respectively

Page 24: Android NDKmobile.web.unc.edu/files/2017/04/gradlecture_ndk.pdfBranching constructs (if/else, switch) are identical to Java Looping constructs (for/while/do-while) are also identical

std::vector<T>

● Analogous to Java’s ArrayList<T>● See http://www.cplusplus.com/reference/vector/vector/

#include <vector>#include <cstdio>

int main() {std::vector<int> v;v.push_back(1);v.push_back(2);v.push_back(3);

if (v.size() == 3) {// Can also use v.at(2) to access value with bounds checkingstd::printf(“Three things. Last item: %d\n”, v[2]);

}} // v’s memory is automatically freed here

Page 25: Android NDKmobile.web.unc.edu/files/2017/04/gradlecture_ndk.pdfBranching constructs (if/else, switch) are identical to Java Looping constructs (for/while/do-while) are also identical

std::string

● Analogous to Java’s String● See http://www.cplusplus.com/reference/string/string/

#include <string>#include <cstdio>

int main() {std::string s1 = “Hello”;std::string s2 = “World”;

if (s1 != s2) {std::string greeting = s1 + “, “ + s2 + “!”;std::printf(“%s\n”, greeting.c_str()); // .c_str() gets the underlying char*

}} // s1’s/s2’s memory is automatically freed here

Page 26: Android NDKmobile.web.unc.edu/files/2017/04/gradlecture_ndk.pdfBranching constructs (if/else, switch) are identical to Java Looping constructs (for/while/do-while) are also identical

C++ Tips● If you don’t need polymorphism or nullable objects, don’t use pointers

○ Stack allocation is easier to keep track of (at the cost of performance for large objects)○ If you do need polymorphism, don’t use raw new/delete: smart pointers like

std::unique_ptr<T> and std::shared_ptr<T> manage memory for you (if you’re using C++11)

● Prefer C++ to C when writing C++○ Don’t use raw arrays; use std::vector<T> instead○ Don’t use raw char* strings; use std::string instead

Page 27: Android NDKmobile.web.unc.edu/files/2017/04/gradlecture_ndk.pdfBranching constructs (if/else, switch) are identical to Java Looping constructs (for/while/do-while) are also identical

CMake● Cross-platform meta-build system

○ De-facto standard C++ build system for cross-platform projects

● Meta-build system○ Generates other build files that do the actual building○ Can generate Makefiles (Linux), Xcode projects (MacOS), Visual Studio solutions (Windows),

and many more

● Build process is described using CMake’s custom scripting language in a file called CMakeLists.txt

Page 28: Android NDKmobile.web.unc.edu/files/2017/04/gradlecture_ndk.pdfBranching constructs (if/else, switch) are identical to Java Looping constructs (for/while/do-while) are also identical

CMakeLists.txt# Set minimum CMake versioncmake_minimum_required(VERSION 3.0)

# Set project nameproject(hello-world)

# Create SOURCES variableset(SOURCES src/main.cpp)

# Create executable named main from SOURCES variableadd_executable(main ${SOURCES})

Page 29: Android NDKmobile.web.unc.edu/files/2017/04/gradlecture_ndk.pdfBranching constructs (if/else, switch) are identical to Java Looping constructs (for/while/do-while) are also identical

CMake - Hello World.|___ build|___ CMakeLists.txt|___ src |___ main.cpp

src/main.cpp

#include <cstdio>

int main() {std::printf(“Hello, World!\n”);

return 0;}

Page 30: Android NDKmobile.web.unc.edu/files/2017/04/gradlecture_ndk.pdfBranching constructs (if/else, switch) are identical to Java Looping constructs (for/while/do-while) are also identical
Page 31: Android NDKmobile.web.unc.edu/files/2017/04/gradlecture_ndk.pdfBranching constructs (if/else, switch) are identical to Java Looping constructs (for/while/do-while) are also identical

What We Didn’t Cover● Polymorphism● References● Special Member Functions/Rule of 3/5/0● Operator Overloading● Const-Correctness● Standard library● Most Standard Template Library (STL) containers and algorithms● Rvalue references and move semantics● Smart pointers● Templates● Advanced CMake

Page 32: Android NDKmobile.web.unc.edu/files/2017/04/gradlecture_ndk.pdfBranching constructs (if/else, switch) are identical to Java Looping constructs (for/while/do-while) are also identical

Project Prerequisites - Get the Tools

Page 33: Android NDKmobile.web.unc.edu/files/2017/04/gradlecture_ndk.pdfBranching constructs (if/else, switch) are identical to Java Looping constructs (for/while/do-while) are also identical

Sample Project

Page 34: Android NDKmobile.web.unc.edu/files/2017/04/gradlecture_ndk.pdfBranching constructs (if/else, switch) are identical to Java Looping constructs (for/while/do-while) are also identical

Set your paths● Remember to make sure you set your NDK path…● ndk.dir=$YourPATH$/Android/sdk/ndk-bundle

Page 35: Android NDKmobile.web.unc.edu/files/2017/04/gradlecture_ndk.pdfBranching constructs (if/else, switch) are identical to Java Looping constructs (for/while/do-while) are also identical

Changes in gradle● CMake Compile options…

externalNativeBuild {

cmake {

path "src/main/cpp/CMakeLists.txt"

argumetns '-DANDROID_TOOLCHAIN=clang', '-DANDROID_TOOLCHAIN=clang'

cppFlags '...'

cFlags '...'

}

}

Page 36: Android NDKmobile.web.unc.edu/files/2017/04/gradlecture_ndk.pdfBranching constructs (if/else, switch) are identical to Java Looping constructs (for/while/do-while) are also identical

Native Functions● Java functions that are used to call functions in your C/C++ code.

● Use the keyword native to distinguish from other functions.

public native ReturnType FuncName(argruments...);

● Declare all the native functions in your one place (MainActivity)

Page 37: Android NDKmobile.web.unc.edu/files/2017/04/gradlecture_ndk.pdfBranching constructs (if/else, switch) are identical to Java Looping constructs (for/while/do-while) are also identical

Native functions● Example Declarations

// Return type string. Void parameterspublic native String stringFromJNI();

//Return type void. Int parameters

public native void SetWidth(int width);

//Function to add two numbers

public native int AddNums(int a, int b);

Page 38: Android NDKmobile.web.unc.edu/files/2017/04/gradlecture_ndk.pdfBranching constructs (if/else, switch) are identical to Java Looping constructs (for/while/do-while) are also identical

Load the C/C++ library● Let Java know about the function calls in your C/C++

System.loadLibrary("LibName");

LibName - Library built from your C/C++ code

● Make sure to include that code in static block

Static {

System.loadLibrary("LibName");

}

Page 39: Android NDKmobile.web.unc.edu/files/2017/04/gradlecture_ndk.pdfBranching constructs (if/else, switch) are identical to Java Looping constructs (for/while/do-while) are also identical

Java JNI interface C/C++● Java provides a way(not exactly an interface) for C/C++ functions to be

callable from JAVA.

● #include<jni.h> ( A Header file)

● Defines two variables JNIEnv* , JavaVM*

● Make sure you include this header file in your C/C++ code

● All declarations, data types, preprocessing definitions are in this header file

Page 40: Android NDKmobile.web.unc.edu/files/2017/04/gradlecture_ndk.pdfBranching constructs (if/else, switch) are identical to Java Looping constructs (for/while/do-while) are also identical

JNI data types

Page 41: Android NDKmobile.web.unc.edu/files/2017/04/gradlecture_ndk.pdfBranching constructs (if/else, switch) are identical to Java Looping constructs (for/while/do-while) are also identical

JNI reference types

Page 42: Android NDKmobile.web.unc.edu/files/2017/04/gradlecture_ndk.pdfBranching constructs (if/else, switch) are identical to Java Looping constructs (for/while/do-while) are also identical

JNI C Code// Java Code

public native ReturnType FuncName(argruments...);

Application ID: Mentioned in gradle file

// C Code#include<jni.h>

……...

…....

JNIEXPORT JNIReturnType JNICALL

Java_ApplicationID_ClassName_FuncName( JNIEnv* env, jobject thiz,

arguments... ) { …… };

Page 43: Android NDKmobile.web.unc.edu/files/2017/04/gradlecture_ndk.pdfBranching constructs (if/else, switch) are identical to Java Looping constructs (for/while/do-while) are also identical

JNI C functionsapplicationId 'com.example.hellojni'

className HelloJNI

//Return type string. Void parameterspublic native String stringFromJNI();

// Corresponding C functionJNIEXPORT jstring JNICALL

Java_com_example_hellojni_HelloJni_stringFromJNI( JNIEnv* env,

jobject thiz);//Return type void. Int parameters

public native void SetWidth(int width);

//Function to add two numbers

public native int AddNums(int a, int b);

Page 44: Android NDKmobile.web.unc.edu/files/2017/04/gradlecture_ndk.pdfBranching constructs (if/else, switch) are identical to Java Looping constructs (for/while/do-while) are also identical

JNI C functionsapplicationId 'com.example.hellojni'

className HelloJNI

//Return type string. Void parameterspublic native String stringFromJNI();

// Corresponding C function

JNIEXPORT jstring JNICALL

Java_com_example_hellojni_HelloJni_stringFromJNI( JNIEnv* env, jobject thiz);

//Return type void. Int parameters

public native void SetWidth(int width);

??????????????????????????????????? ( C/C++ Function?)//Function to add two numbers

public native int AddNums(int a, int b);

??????????????????????????????????? ( C/C++ Function?)

Page 45: Android NDKmobile.web.unc.edu/files/2017/04/gradlecture_ndk.pdfBranching constructs (if/else, switch) are identical to Java Looping constructs (for/while/do-while) are also identical

JNI C functionsapplicationId 'com.example.hellojni'

className HelloJNI

//Return type void. Int parameters

public native void SetWidth(int width);

JNIEXPORT void JNICALL

Java_com_example_hellojni_HelloJni_SetWidth( JNIEnv* env, jobject

thiz, jint width);

//Function to add two numbers

public native int AddNums(int a, int b);

JNIEXPORT int JNICALL

Java_com_example_hellojni_HelloJni_AddNums( JNIEnv* env, jobject

thiz, jint a, jint b);

Page 46: Android NDKmobile.web.unc.edu/files/2017/04/gradlecture_ndk.pdfBranching constructs (if/else, switch) are identical to Java Looping constructs (for/while/do-while) are also identical

JNI C++ functions

#include<jni.h>

……...

…....

extern "C" {

//JNI Native C functions

JNIEXPORT JNIReturnType JNICALL

Java_ApplicationID_ClassName_FuncName( JNIEnv* env, jobject thiz,

arguments... ) { …… };

}

Page 47: Android NDKmobile.web.unc.edu/files/2017/04/gradlecture_ndk.pdfBranching constructs (if/else, switch) are identical to Java Looping constructs (for/while/do-while) are also identical

Calling Java Functions● Java functions can be called from native code ( C/C++)

● #include<jni.h> ( A Header file)

● Defines two variables JNIEnv* , JavaVM*

● Defines several functions to retrieve classes,

methods, and variables

Page 48: Android NDKmobile.web.unc.edu/files/2017/04/gradlecture_ndk.pdfBranching constructs (if/else, switch) are identical to Java Looping constructs (for/while/do-while) are also identical

JNI Functions● Some of the widely used functions

jclass FindClass(JNIEnv *env, const char *name);

jmethodID GetMethodID(JNIEnv *env, jclass clazz,const char *name, const

char *sig);

NativeType Call<type>Method(JNIEnv *env, jobject obj,jmethodID methodID,

...)

jfieldID GetFieldID(JNIEnv *env, jclass clazz,const char *name, const char

*sig);

Page 49: Android NDKmobile.web.unc.edu/files/2017/04/gradlecture_ndk.pdfBranching constructs (if/else, switch) are identical to Java Looping constructs (for/while/do-while) are also identical

JNI Functions

● Using the JNI functions in C/C++ code○ Create objects of Java classes○ Get Methods of the classes○ Call private, public, and static methods of the classes

Page 50: Android NDKmobile.web.unc.edu/files/2017/04/gradlecture_ndk.pdfBranching constructs (if/else, switch) are identical to Java Looping constructs (for/while/do-while) are also identical

Constructor like function● Special native function called when System.loadLibrary call is made

JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM* vm, void* reserved);

● Use this function load and save several environmental variables● Corresponding JNI_OnUnLoad() function exists to free memories

Page 51: Android NDKmobile.web.unc.edu/files/2017/04/gradlecture_ndk.pdfBranching constructs (if/else, switch) are identical to Java Looping constructs (for/while/do-while) are also identical

Example OnLoad CodeJNIEXPORT jint JNICALL JNI_OnLoad(JavaVM* vm, void* reserved) {

JNIEnv* env;

if ((*vm)->GetEnv(vm, (void**)&env, JNI_VERSION_1_6) !=

JNI_OK) {

return JNI_ERR; // JNI version not supported.

}

}

● Let’s look at a detailed example of callbacks

Page 52: Android NDKmobile.web.unc.edu/files/2017/04/gradlecture_ndk.pdfBranching constructs (if/else, switch) are identical to Java Looping constructs (for/while/do-while) are also identical

Questions?

Link to code:

https://github.com/googlesamples/android-ndk

Examples discussed in class

● hello-jni, hello-jniCallback

Advanced examples

● hello-gls , native-activity, native-audio

Page 53: Android NDKmobile.web.unc.edu/files/2017/04/gradlecture_ndk.pdfBranching constructs (if/else, switch) are identical to Java Looping constructs (for/while/do-while) are also identical

Points to cover● Settings side

○ Path of the NDK set○ Changes in gradle ○ Add dependencies and path to CMake

● Java Side○ Declaring native functions○ Setting the load library name on start up○ Calling a C function code○ Talk about @keep ( code optimization)

● C/C++ Side○ What is a Java JNI - one slide recap○ Data types ( jClass, jMethod, jObject, jInt, jString…)○ Declaring a JNI callable function in C ( if in C++ use extern)○ Signature of the function○ Parameters passed! ○ Calling a Java Function


Recommended