Android ndk Android NDK:为同一abi提供库变体

Android ndk Android NDK:为同一abi提供库变体,android-ndk,shared-libraries,Android Ndk,Shared Libraries,我正在寻找一种最好的方法,用不同的编译设置为同一ABI开发和打包库的不同变体,然后在运行时选择最合适的。更具体地说,我想要一个霓虹灯和非霓虹灯armeabi-v7a版本 本机库有一个第三方链接到的公共C接口。他们似乎需要链接到其中一个变体以防止链接错误,但如果更适合设备,我希望在运行时加载替代变体,并让运行时加载程序执行正确的重新定位 从我目前看到的情况来看,似乎我需要为这两个变体提供相同的文件名,因此需要将它们放在不同的文件夹中。abi文件夹下的子文件夹似乎不会被包安装过程复制,因此这种方法不

我正在寻找一种最好的方法,用不同的编译设置为同一ABI开发和打包库的不同变体,然后在运行时选择最合适的。更具体地说,我想要一个霓虹灯和非霓虹灯armeabi-v7a版本

本机库有一个第三方链接到的公共C接口。他们似乎需要链接到其中一个变体以防止链接错误,但如果更适合设备,我希望在运行时加载替代变体,并让运行时加载程序执行正确的重新定位

从我目前看到的情况来看,似乎我需要为这两个变体提供相同的文件名,因此需要将它们放在不同的文件夹中。abi文件夹下的子文件夹似乎不会被包安装过程复制,因此这种方法不起作用。到目前为止,我看到的最好的建议是手动将res文件夹中的一个变量复制到已知的设备路径,并使用完整路径调用System.loadLibrary()。参考:

  • 这仍然是最佳/推荐的方法吗
  • 这将如何与在非arm设备上完成的二进制翻译交互?(虽然我可以提供x86版本,但一些第三方可能会将其从apk中删除)

  • 我假设使用二进制翻译的设备上的CPuffeatures不会将cpu系列报告为ARM,因此我建议的解决方案是以正常的方式构建一个标准的armeabi-v7a库(我猜这将得到二进制翻译),并以res/raw提供一个支持NEON的库。然后在运行时,如果cpufeatures报告一个支持NEON的ARM CPU,则复制该库并使用完整路径调用loadLibrary。有人能看出这种方法有什么问题吗?

    如果你明确地想要一个库有两个不同的版本,那么是的,这可能是最好的折衷方案

    首先,请注意,许多可以使用NEON的库可以在启用运行时部分的情况下构建,这样您就可以拥有一个正常的ARMv7构建,该构建不严格要求NEON,但可以在运行时启用这些代码路径(如果检测到),例如libav/FFmpeg可以做到这一点,许多其他类似库也是如此。这允许您拥有一个ARMv7二进制文件,在适用的情况下充分利用NEON,同时仍能在少数没有NEON的ARMv7设备上工作

    如果您试图使用编译器自动矢量化,或者如果这是一个库,其中NEON例程不容易被限制在运行时启用的受限部分(或者希望通过使用NEON启用构建整个库来获得额外性能),那么您的方法听起来是明智的

    请记住,您希望至少有一个“正常”打包的本机库(您似乎有,但这在例如中是一个问题)。安装时,安装程序从捆绑的体系结构中选择最佳匹配的体系结构,并仅从该体系结构中提取lib,然后在该模式下运行进程。在具有多个ABI(32位和64位)的设备上,这是至关重要的,因为如果进程以不同的模式启动,那么一旦尝试以不同的形式加载库,切换模式就太晚了

    在模拟ARM二进制文件的x86设备上,如果进程在ARM模式下运行,则至少
    cpufeatures
    库将返回ARM。如果您使用系统属性来查找主ABI和辅助ABI,您将不知道当前进程正在使用哪一个


    编辑:具有二进制转换的x86设备实际上似乎能够加载armeabi库,即使同一进程已经加载了一些捆绑的x86库。显然,这种转换是在每个库的基础上进行的,不像32对64位那样,在启动时为进程选择了某种模式,这就排除了加载其他变体的任何库。

    谢谢。您确定cpufeatures在x86设备上返回ARM吗?我以为他们在安装时将二进制文件转换成x86,而不是实际的ARM仿真?我真的需要让x86设备在我的终端进行测试。虽然我会尝试在一般情况下进行运行时检查,但我假设每次调用都需要在常规(非neon编译)代码中检查neon,然后从启用neon编译的单独文件调用函数。这非常混乱,并且阻止了NEON代码内联。好吧,cpufeatures库只返回它编译时使用的架构(请查看
    /sources/android/cpufeatures/cpu features.c
    中的
    android\u cpuInitFamily
    ),因此如果它最初是ARM二进制文件,它总是报告ARM。我很确定二进制转换是在运行时进行的,而不是在安装时进行的——但它似乎比我想象的更强大。我试着做一个包含arm和x86库的APK,但是在res/raw中有一个只包含arm的库。因为有一个x86版本,它将使用这个版本,但是res/raw中的arm库也可以很好地加载到同一个过程中,所以显然翻译是按库进行的。这与例如armeabi与arm64-v8a相反,在armeabi与arm64-v8a中,如果进程以64位模式启动,则无法加载32位库。我将编辑这篇文章并澄清这一点。是的,如果你有运行时检查,你不能有内联的NEON代码。许多库(例如编解码器和类似代码)大多在DSP例程中使用霓虹灯代码(例如“在此阵列上进行卷积”),并具有确定要使用的此类函数的正确版本的设置代码,然后您只能通过函数指针使用它们。您可能在某些地方错过了一些潜在的内联使用,但您仍然可以从SIMD中获得主要的批量好处。我最近看到的大多数编解码器库至少都是这样做的。