Reputation: 3660
I have generated a .so
file via C++ on Linus and got .so
file generated now I have cross compile this .so
file for Android ARM
so I have to comiple it via Android NDK
so that new genrated .so
can be used in my android project .
So can anyone help me where I have to put Linux generated .so file in my Android project and what to add in Make file(Android.mk) so that it can generate new .so
file with existing methods in my previous Linux generated .so
file.
I hope my question is clear to you all, if not please tell me.
Please help me. Thanks in advance
Upvotes: 2
Views: 3627
Reputation: 102205
Here are the steps to build a native C++ shared object.
Create an Android.mk
, add it to the the JNI folder, and add the architectures you want to support. For example:
APP_ABI := armeabi x86 mips armeabi-v7a
Pick a C++ runtime library. See the CPLUSPLUS.README in the NDK. I picked STL Port for the runtime (the GNU runtime was toxic due to its license).
Create an Appication.mk
, add it to the the JNI folder, and add the 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 "STLport library" ensures my library is compiled against stlport_shared.so
, and the stlport_shared.so
is copied into the APK.
My library also depends upon a cross-compiled version of Crypto++. Crypto++ was also compiled/linked against stlport_shared.so
. The stuff following "Crypto++ library" ensures my library is compiled against libcryptopp.so
, and the libcryptopp.so
is copied into the APK.
Finally, my library is called out. My library is the stuff following "PRNG library" (its a one file test project). It builds libprng.so
, and ensures libprng.so
is copied into the APK.
You'll also need Android classes. Here's 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 Android modified build system really sucks. Its sufficiently different from standard make-based projects and poorly documented. But that's what Android offers, so that's what you have to use. Eclipse's Android 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
Upvotes: 5