android - 使用 Android NDK 编译原生 C++ 共享对象

标签 android c++ android-ndk

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

谁能帮我把Linux生成的.so文件放在我的Android项目中,以及在Make文件(Android.mk)中添加什么,以便它可以生成新的.so文件使用我之前的 Linux 生成的 .so 文件中的现有方法。

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

请帮助我。提前致谢

最佳答案

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

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

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

  • 创建一个 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)
    
  • 我的库依赖于 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 类(class)。这是我的样子。

    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 修改后的构建系统真的很糟糕。它与标准的基于 make 的项目有很大不同,并且记录很少。但这就是 Android 提供的功能,因此您必须使用它。 Eclipse 的 Android native 支持是围绕它构建的。


    如果有兴趣,以下是包装器头文件的样子。您可以使用 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
    

    关于android - 使用 Android NDK 编译原生 C++ 共享对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27775704/

    相关文章:

    c++ - scons 如何将 sysroot 传递给 g++

    android - 如何解决 Android 系统库崩溃问题 (libwebcore.so)

    android - 创建新 Ionic 项目时运行子过程电容器时发生错误

    Android BLE 错误 0x06 不支持请求

    c++11数组传递给函数错误

    c++ - 文件已创建,但不可见

    Android:如何将 ndk-gdb 与纯 native 可执行文件一起使用?

    android - 以编程方式在 Android 中为视频添加图像帧或水印

    android - 在 TabHost 中使用 ViewFlipper

    c++ - MFC 工作区栏 : "Failed to create empty document"