Friday, June 2, 2017

Interaction of C++ and Python via Boost.Python

  • Download latest boost package from http://www.boost.org/.
  • Unzip and go inside the folder: cd ~/Downloads/boost_1_62_0
  • Run ./bootstrap.sh
  • Then run ./b2 . This will build all the shared libraries in ~/Downloads/boost_1_62_0/stage/lib.(we are interested in boost_python library as of now)
  • Copy headers and libraries to standard path:
    • sudo cp -r ~/Downloads/boost_1_62_0/boost /usr/local/include/
    • sudo cp ~/Downloads/boost_1_62_0/stage/lib/libboost_python.* /usr/local/lib/
  • Append Python wrapper code in C++ so that existing C++ code is not changed at all. [ Caution: Nomenclature of file name and module should be same!!! ]
        char const* greet()
        {
             return "hello, world";
        }
 
        #include <boost/python.hpp>
 
        BOOST_PYTHON_MODULE(<module>)
        {
             using namespace boost::python;
             def("greet", greet);
        }
  • g++ -c <filename>.cpp -o <filename>.o -fPIC && g++ -c <other_filename>.cpp -o <other_filename>.o
  • For following error "/usr/local/include/boost/python/detail/wrap_python.hpp:50:11: fatal error: 'pyconfig.h' file not found", add -I/usr/include/python2.7/ while compiling.
  • g++ -shared <filename>.o <other_filename>.o -lboost_python -lpython2.7 -o <filename>.so ( If <filename>.cpp depends on <other_filename>.cpp, put its compiled object as well. Include -litpp if the c++ code depends on IT++ library)
  • Put the shared library in the standard python module path: cp <filename>.so /Library/Python/2.7/site-packages/
  • Open .py file and call the C++ function: [ module and C++ filename are same ]
        import <module>
        module.greet();
  • For passing an argument from Python to C++, simply do the following:

     In C++:

     char const* greet(string name)
     {
        if(name != null) {
            return "hello " + name;
        } else {
            return "hello, world";
        }
     }
 
     #include <boost/python.hpp>
 
     BOOST_PYTHON_MODULE(<module>)
     {
         using namespace boost::python;
         def("greet", greet);
     }

    In Python:

    import <module>
    module.greet("Rajanya");

IT++ and FFTW integration with Android NDK

IT++ and FFTW libraries need to be compiled specific to Application Binary Interface (ABI) for Android NDK.

These are the following ABIs:
  1. X86
  2. X86_64
  3. armeabi
  4. mips
  5. mips64
etc....
Further details can be found over here-> https://developer.android.com/ndk/guides/abis.html

IMPORTANT: Compile FFTW before IT++ as IT++ incorporates FFTW's archived library inside its own shared library.


FFTW compilation for NDK:
  1. Download the latest package from http://www.fftw.org/
  2. Unzip and go inside the folder: cd ~/Downloads/fftw-3.3.5
  3. Set the compilation parameters specific to an ABI. The example is for 'armeabi'.
    1. export NDK_ROOT="/Users/rajanya/Library/Android/sdk/ndk-bundle"
    2. export PATH="$NDK_ROOT/toolchains/arm-linux-androideabi-4.9/prebuilt/darwin-x86_64/bin/:$PATH"
    3. export SYS_ROOT="$NDK_ROOT/platforms/android-21/arch-arm/"
    4. export CC="arm-linux-androideabi-gcc --sysroot=$SYS_ROOT"
    5. export LD="arm-linux-androideabi-ld"
    6. export AR="arm-linux-androideabi-ar"
    7. export RANLIB="arm-linux-androideabi-ranlib"
    8. export STRIP="arm-linux-androideabi-strip"
    9. export DEST_DIR="$NDK_ROOT/toolchains/arm-linux-androideabi-4.9/prebuilt/darwin-x86_64/user"
  4. Generate Makefile: ./configure --host=arm-eabi --build=i386-apple-darwin10.8.0 --prefix=$DEST_DIR LIBS="-lc -lgcc" --disable-fortran
  5. make && make install

IT++ compilation with FFTW for NDK:
  1. Download the latest package from http://itpp.sourceforge.net/4.3.1/installation.html
  2. Unzip and go inside the folder: cd ~/Downloads/itpp-4.3.1
  3. mkdir build && cd build/
  4. Download https://github.com/taka-no-me/android-cmake to obtain cmake toolchain file.
  5. Open cmake GUI. If cmake not present , visit https://cmake.org/download/
  6. In cmake, add the following entries:
    1. Where is the source code: ~/Downloads/itpp-4.3.1
    2. Where to build the binaries:~/Downloads/itpp-4.3.1/build
  7. Then click '+Add Entry' button to add the following key-value pair:
    1. ANDROID_NDK -> PATH -> ~/Library/Android/sdk/ndk-bundle
    2. ANDROID_NATIVE_API_LEVEL -> STRING -> 17
    3. ANDROID_TOOLCHAIN_NAME -> STRING -> arm-linux-androideabi-4.9
  8. Click Configure -> Specify toolchain file for cross-compiling -> ~/Downloads/android-cmake-master/android.toolchain.cmake
  9. Click Generate.
  10. Return back to terminal. Run make && make install to build & install the shared library at /usr/local/lib/
NOTE: Repeat the above steps for each and every ABI

How to make IT++ functions available to the C++ code in Android?

  1. Copy /usr/local/lib/libitpp.so to <app_path>/app/libs/
  2. Enter the following lines in the CMake file:
    1. set(distribution_DIR ${CMAKE_SOURCE_DIR}/../../../libs)
    2. add_library(lib_itpp SHARED IMPORTED)
    3. set_target_properties(lib_itpp PROPERTIES IMPORTED_LOCATION

          ${distribution_DIR}/lib/${ANDROID_ABI}/libitpp.so)
    4. target_link_libraries(native-lib
                            android
                            lib_itpp)
  3. #include<itpp/itbase.h> in your native-lib.cpp file.