Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Running native code on Android #OSDCfr 2012

Running native code on Android #OSDCfr 2012

* cross-compiling 3rd party libraries with the Android Standalone Toolchain,
* using prebuilt libraries,
* using NEON code while still targeting all devices,
* illustrating some Java Native Interface (JNI) tips and tricks

Cédric Deltheil

October 13, 2012
Tweet

More Decks by Cédric Deltheil

Other Decks in Programming

Transcript

  1. Running native
    code on Android
    OSDC.fr 2012-10-13
    Cédric @deltheil
    C NDK ARM

    View Slide

  2. - Why using native
    code? -

    View Slide

  3. 1. Reuse some C
    code

    View Slide

  4. 2. Use 3rd party
    libraries

    View Slide

  5. 3. Create portable
    components
    iOS
    Android ...

    View Slide

  6. 4. Use hardware
    acceleration
    CPU
    SIMD algorithm

    View Slide

  7. 5. ... because it’s
    fun :)

    View Slide

  8. ...but How?
    Native Development Kit

    View Slide

  9. - Android NDK
    overview -

    View Slide

  10. Downloads
    http://developer.android.com/tools/sdk/ndk/index.html
    cross-platform

    View Slide

  11. Contents
    1. Tools for Linux,OS X,Win to cross-compile
    native ARM,x86,MIPS binaries.

    View Slide

  12. Contents
    2. System files and headers for Android native
    APIs.
    w/ Java Native Interface (a.k.a JNI)

    View Slide

  13. Contents
    3. Easy-to-use build system: Android.mk &
    ndk-build (make wrapper).

    View Slide

  14. Contents
    4. Documentation and
    code samples.

    View Slide

  15. - Steps to embed C
    code -

    View Slide

  16. 1/3 Wrap C
    Java
    JNI
    C code
    C
    Java
    libmisc.so

    View Slide

  17. 1/3 Wrap C
    /* 1. Wrap your C code with the JNI */
    #include
    jstring
    Java_com_example_Foo_bar(JNIEnv* env, jobject thiz) {
    char buffer[512];
    /* ... */
    return (*env)->NewStringUTF(env, buffer);
    }
    namespace class method instance
    native interface

    View Slide

  18. 2/3 Build native lib
    Java
    JNI
    C code
    C
    Java
    libmisc.so

    View Slide

  19. # 2. Generate a lib with ndk-build
    $ ndk-build
    Compile thumb : misc <= misc.c
    StaticLibrary : libmisc.a
    SharedLibrary : libmisc.so
    Install : libmisc.so => libs/armeabi/libmisc.so
    ...
    2/3 Build native lib

    View Slide

  20. 3/3 Java ext
    Java
    JNI
    C code
    C
    Java
    libmisc.so

    View Slide

  21. /* 3. Expose the logic via a native extension */
    package com.example;
    public class Foo extends /* ... */ {
    static {
    System.loadLibrary("misc");
    }
    public native String bar();
    }
    3/3 Java ext

    View Slide

  22. Basic
    Java
    JNI
    C code
    C
    Java
    libmisc.so

    View Slide

  23. Advanced
    Java
    JNI
    libA.a
    C
    Java
    libmisc.so
    A sources
    C code
    libB.a B sources
    3rd party libs

    View Slide

  24. - Building 3rd
    party libs -

    View Slide

  25. Pro-tip
    Use the Standalone Toolchain.

    View Slide

  26. What?
    A customized install for a given platform,
    arch.
    handy

    View Slide

  27. Why?
    No need to write specific Android.mk
    makefiles: reuse existing build systems.
    0 LOC Makefile autotools

    View Slide

  28. How?

    View Slide

  29. Makefile
    [Ex. 1] jsmn
    JSON
    C parser

    View Slide

  30. [Ex. 1] jsmn 1/3
    override Makefile variables

    View Slide

  31. [Ex. 1] jsmn 2/3

    View Slide

  32. [Ex. 1] jsmn 3/3
    choose the proper arch... and that’s it!
    Full gist @ http://git.io/ndk-jsmn

    View Slide

  33. [Ex. 2] msgpack
    autotools binary
    C/C+ serialization

    View Slide

  34. [Ex. 2] msgpack 1/3

    View Slide

  35. [Ex. 2] msgpack 2/3

    View Slide

  36. [Ex. 2] msgpack 3/3
    Full gist @ http://git.io/ndk-msgpack
    use the cross-toolchains... and that’s it!

    View Slide

  37. - Using a prebuilt
    library -

    View Slide

  38. Overview
    Android.mk
    Application.mk
    ndk-build
    armeabi/
    libfoo.so
    libs/
    single arch

    View Slide

  39. Overview
    Android.mk
    Application.mk
    armeabi-v7a/
    libfoo.so
    ndk-build
    armeabi/
    libfoo.so
    libs/
    fat binary

    View Slide

  40. - Loading a native
    library -

    View Slide

  41. Basic
    Pick the right
    arch vs.
    target device

    View Slide

  42. Medium

    View Slide

  43. Custom
    frontal library
    native method (frontal lib.)
    Pick the right arch
    yourself!

    View Slide

  44. Custom: why?
    [2] Bypass a loadLibrary bug on ICS!
    [1] Properly target ARMv7 without NEON CPUs
    when getCpuFeatures() can’t be used at
    runtime (e.g. 3rd party libs)
    [2] see http://www.moodstocks.com/2012/03/20/ice-cream-sandwich-why-native-code-support-
    sucks
    [1] e.g. «the NVidia Tegra 2 generation SoC has a dual-core ARM Cortex-A9 CPU (lacking ARM's
    advanced SIMD extension—NEON)» - see http://en.wikipedia.org/wiki/Tegra

    View Slide

  45. - Quick JNI hints -

    View Slide

  46. C pointer = int field
    e.g. persist a DB handle
    and use it throughout
    the JNI extensions
    Don’t forget to destruct it (explicitly
    or at finalize() time)

    View Slide

  47. C error codes
    C error code
    & string

    View Slide

  48. Resources
    #AltDevBlogADay NDK Part 1 & Part 2 Linux Mag., 07/11
    VLC for Android
    Tokyo Cabinet Java Pkg

    View Slide

  49. Thanks!
    Questions? Comments? [email protected] | @deltheil

    View Slide