Compile native C ++ shared object with Android NDK

I generated the file .so

via C ++ on Linus and got the resulting file now .so

. I have cross-compiled this file .so

for Android ARM

, so I need to link it with Android NDK

so that the new genrated .so

can be used in my android project.

So can anyone help me where should I put the Linux.so file in my Android project and what to add to the Make file (Android.mk) so that it can generate a new file .so

with existing methods in my previous Linux generated file .so

.

I hope my question is clear to all of you, if not please tell me.

Please help me. thanks in advance

+2


source to share


1 answer


Following are the steps to create a native C ++ shared object.

  • Add your own support to your project. See Android Add native support
  • Add your C ++ files to JNI folder
  • Build Android.mk

    , add it to the JNI folder and add the architectures you want to support. For example:

    APP_ABI   := armeabi x86 mips armeabi-v7a
    
          

  1. Select C ++ Runtime Library. See CPLUSPLUS.README in the NDK. I chose the STL port for the runtime (GNU runtime was toxic under license).

  2. Build Appication.mk

    , add it to JNI folder and add magic. For example:

    LOCAL_PATH := $(call my-dir)
    
    # NDK_DEBUG_IMPORTS := 1
    
    #########################################################
    # STLport library
    include $(CLEAR_VARS)
    
    STLPORT_INCL     := /opt/android-ndk-r9/sources/cxx-stl/stlport/stlport
    STLPORT_LIB      := /opt/android-ndk-r9/sources/cxx-stl/stlport/libs/$(TARGET_ARCH_ABI)
    
    LOCAL_MODULE := stlport_shared
    LOCAL_SRC_FILES := $(STLPORT_LIB)/libstlport_shared.so
    
    LOCAL_EXPORT_CPPFLAGS :=
    LOCAL_EXPORT_C_INCLUDES := $(STLPORT_INCL)
    
    include $(PREBUILT_SHARED_LIBRARY)
    
    LOCAL_SHARED_LIBRARIES  := stlport_shared
    
    #########################################################
    # Crypto++ library
    include $(CLEAR_VARS)
    
    CRYPTOPP_INCL   := /usr/local/cryptopp/android-$(TARGET_ARCH_ABI)/include
    CRYPTOPP_LIB    := /usr/local/cryptopp/android-$(TARGET_ARCH_ABI)/lib
    
    LOCAL_MODULE       := cryptopp
    LOCAL_SRC_FILES    := $(CRYPTOPP_LIB)/libcryptopp.so
    
    LOCAL_EXPORT_CPPFLAGS := -Wno-unused-parameter -Wno-unused-variable -Wno-unused-function
    LOCAL_EXPORT_C_INCLUDES := $(CRYPTOPP_INCL) $(CRYPTOPP_INCL)/cryptopp
    
    include $(PREBUILT_SHARED_LIBRARY)
    
    LOCAL_SHARED_LIBRARIES  := cryptopp
    
    #########################################################
    # PRNG library
    include $(CLEAR_VARS)
    
    APP_STL         := stlport_shared
    APP_MODULES     := prng stlport_shared cryptopp
    
    # My ass... LOCAL_EXPORT_C_INCLUDES is useless
    LOCAL_C_INCLUDES   := $(STLPORT_INCL) $(CRYPTOPP_INCL)
    
    LOCAL_CPP_FEATURES := rtti exceptions
    
    LOCAL_CPP_FLAGS    := -Wno-unused-parameter -Wno-unused-variable -Wno-unused-function
    LOCAL_CPP_FLAGS    += -Wl,--exclude-libs,ALL
    
    LOCAL_LDLIBS            := -llog -landroid
    LOCAL_SHARED_LIBRARIES  := cryptopp stlport_shared
    
    LOCAL_MODULE    := prng
    LOCAL_SRC_FILES := libprng.cpp
    
    include $(BUILD_SHARED_LIBRARY)
    
          

My library depends on STLport. The stuff following "The STLport Library" ensures that my library is compiled against stlport_shared.so

and stlport_shared.so

copied into the APK.

My library also depends on the cross compiled version of Crypto ++ . Crypto ++ has also been compiled / linked against stlport_shared.so

. The stuff following "Crypto ++ library" ensures that my library is compiled against libcryptopp.so

and libcryptopp.so

copied into the APK.

Finally, my library gets called. My library is stuff following "PRNG library" (project to test one file). It builds libprng.so

and guarantees to libprng.so

be copied to the APK.



You will also need Android classes. This is what mine looks like.

package com.cryptopp.prng;

public class PRNG {

    static {
        System.loadLibrary("stlport_shared");
        System.loadLibrary("cryptopp");
        System.loadLibrary("prng");
    }

    private static native int CryptoPP_Reseed(byte[] bytes);

    private static native int CryptoPP_GetBytes(byte[] bytes);

    private static Object lock = new Object();

    // Class method. Returns the number of bytes consumed from the seed.
    public static int Reseed(byte[] seed) {         
        synchronized (lock) {
            return CryptoPP_Reseed(seed);
        }
    }

    // Class method. Returns the number of bytes generated.
    public static int GetBytes(byte[] bytes) {
        synchronized (lock) {
            return CryptoPP_GetBytes(bytes);
        }
    }

    // Instance method. Returns the number of bytes consumed from the seed.
    public int reseed(byte[] seed) {
        synchronized (lock) {
            return CryptoPP_Reseed(seed);
        }
    }

    // Instance method. Returns the number of bytes generated.
    public int getBytes(byte[] bytes) {
        synchronized (lock) {
            return CryptoPP_GetBytes(bytes);
        }
    }
}

      

The altered Android build system really sucks. It is quite different from standard layout based projects and is poorly documented. But what Android offers is the way that you should use. Eclipse Android's native support is built around it.


If interested, here's what the wrapper header file looks like. You can use javah

to generate it from your DEX file (compiled Java classes).

/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class com_cryptopp_prng_PRNG */

#ifndef _Included_com_cryptopp_prng_PRNG
#define _Included_com_cryptopp_prng_PRNG
#ifdef __cplusplus
extern "C" {
#endif
/*
 * Class:     com_cryptopp_prng_PRNG
 * Method:    CryptoPP_Reseed
 * Signature: ([B)I
 */
JNIEXPORT jint JNICALL Java_com_cryptopp_prng_PRNG_CryptoPP_1Reseed
  (JNIEnv *, jclass, jbyteArray);

/*
 * Class:     com_cryptopp_prng_PRNG
 * Method:    CryptoPP_GetBytes
 * Signature: ([B)I
 */
JNIEXPORT jint JNICALL Java_com_cryptopp_prng_PRNG_CryptoPP_1GetBytes
  (JNIEnv *, jclass, jbyteArray);

#ifdef __cplusplus
}
#endif
#endif

      

+3


source







All Articles