使用Android NDK编译本机C ++共享对象

时间:2015-01-05 08:22:47

标签: android c++ android-ndk

我已经在Linus上通过C ++生成了一个.so文件并且现在生成了.so文件我已经交叉编译.so这个Android ARM文件所以我必须将它编辑通过Android NDK以便新生成的.so 可以在我的android项目中使用。

所以任何人都可以帮助我,我必须在我的Android项目中放置Linux生成的.so文件以及在Make文件(Android.mk)中添加什么,以便它可以使用现有方法生成新的.so文件我之前的Linux生成了.so文件。

我希望我的问题清楚,如果不是,请告诉我。

请帮帮我。提前致谢

1 个答案:

答案 0 :(得分:5)

以下是构建本机C ++共享对象的步骤。

  1. 为您的项目添加原生支持。请参阅Android Add native support
  2. 将您的C ++文件添加到JNI文件夹
  3. 创建Android.mk,将其添加到JNI文件夹,然后添加要支持的体系结构。例如:

    APP_ABI   := armeabi x86 mips armeabi-v7a
    
    1. 选择一个C ++运行时库。请参阅NDK中的CPLUSPLUS.README。我为运行时选择了STL端口(GNU运行时由于其许可证而有毒)。

    2. 创建Appication.mk,将其添加到JNI文件夹,然后添加魔法。例如:

      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)
      
    3. 我的图书馆依赖于STLport。 " STLport库" 之后的内容可确保我的库针对stlport_shared.so进行编译,并将stlport_shared.so复制到APK中。

      我的图书馆还取决于cross-compiled version of Crypto++。 Crypto ++也是针对stlport_shared.so编译/链接的。 " Crypto ++库" 之后的内容可确保我的库针对libcryptopp.so进行编译,并将libcryptopp.so复制到APK中。

      最后,我的图书馆被召唤出来。我的库是" PRNG库" (它是一个文件测试项目)之后的东西。它会构建libprng.so,并确保将libprng.so复制到APK中。

      您还需要Android课程。这就是我的样子。

      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);
              }
          }
      }
      

      Android修改后的构建系统真的很糟糕。它与标准的基于制造的项目有很大不同,而且记录不完整。但这就是Android提供的功能,因此您必须使用它。 Eclipse的原生支持是围绕它构建的。


      如果有兴趣,请查看封装头文件的样子。您可以使用javah从DEX文件(已编译的Java类)生成它。

      /* 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