简体   繁体   English

在运行时选择并加载备用共享库之一

[英]Choosing and loading one of alternative shared libs at runtime

Was trying to add NEON support to an application, per the CPU-ARM-NEON.html in the docs. 正在尝试根据文档中的CPU-ARM-NEON.html向应用程序添加NEON支持。 The docs mention runtime checks, but it turns out a native library cannot be both plain-v7a and NEON at the same time anyway, the runtime linker simply won't load such a library on some devices. 该文档提到了运行时检查,但事实证明,本机库无论如何不能同时为plain-v7a和NEON,运行时链接程序根本不会在某些设备上加载此类库。

So it looks like I need two versions of the same library, optimized for different capabilities, to load one at runtime manually. 因此,看起来我需要针对不同功能进行优化的同一个库的两个版本,才能在运行时手动加载一个。 Reportedly this can be done, though it is a step away from the ndk-through-eclipse path and I'm at loss on how to set things up. 据报道,这是可以做到的,尽管它离ndk-through-eclipse路径还有一步,而且我对如何进行设置感到困惑。

I figured I list one of the versions under LOCAL_SHARED_LIBRARIES for the core to link properly, but then whatever I list there gets added to core dependencies. 我想我列出了LOCAL_SHARED_LIBRARIES下的一个版本以便内核正确链接,但是随后列出的所有内容都添加到了内核依赖项中。 Runtime linker then checks for it to be present when I load the core, and throws even if another lib was already loaded in its place. 然后,运行时链接程序会在我加载内核时检查它是否存在,并且即使已经在其位置加载了另一个lib也会抛出该异常。

Also, the library that isn't listed remains unstripped and isn't automatically added to the package. 此外,未列出的库仍保持未剥离状态,并且不会自动添加到程序包中。 I have to export unsigned apk from eclipse, add .so, sign, align and reinstall every time, which is bearable but far from practical. 我必须从eclipse中导出未签名的apk,每次添加.so,签名,对齐和重新安装,这是可以忍受的,但远远不切实际。

Any suggestions on how to build the core binary without introducing a hardcoded dependency-by-module-name? 关于如何在不引入按模块名称进行硬编码依赖的情况下如何构建核心二进制文件的任何建议? Is there a civilized way to hook 'non-referenced' libraries up for packaging with the rest of the stuff? 是否有一种文明的方法可以将“未引用”的库与其余内容包装在一起?


Finally found the problem - had a mixed file with both neon and normal code built with .neon suffix. 最终找到了问题-使用.neon后缀构建了一个混合了霓虹灯和普通代码的文件。 Apparently library can contain both NEON and plain-v7a code, a single file however can't - d32 instructions leak outside of neon execution paths and runtime linker does this: 显然,库可以同时包含NEON和Plain-v7a代码,但是不能包含单个文件-d32指令泄漏到neon执行路径之外,并且运行时链接程序会这样做:

D/dalvikvm(5323): Trying to load lib /data/data/com.my.app/lib/libapp.so 0x410b96e8
A/libc(5323): Fatal signal 4 (SIGILL) at 0x5c21ae92 (code=1)
D/dalvikvm(3908): GC_CONCURRENT freed 222K, 9% free 7010K/7687K, paused 38ms+2ms
I/DEBUG(91): *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
I/DEBUG(91): Build fingerprint: 'Lenovo/ThinkPadTablet/Indigo:4.0.3/ThinkPadTablet_A400_03/0070_0132_ROW:user/release-keys'
I/DEBUG(91): pid: 5323, tid: 5336  >>> com.my.app <<<
I/DEBUG(91): signal 4 (SIGILL), code 1 (ILL_ILLOPC), fault addr 5c21ae96
I/DEBUG(91):  r0 5c51d250  r1 00000000  r2 00000000  r3 00000000
I/DEBUG(91):  r4 00000000  r5 00000000  r6 00000000  r7 00000000
I/DEBUG(91):  r8 00000000  r9 3f800000  10 3f800000  fp 00000000
I/DEBUG(91):  ip 00000000  sp 5bc1c9d8  lr 5bf7423d  pc 5c21ae96  cpsr 40000070
I/DEBUG(91):  d0  3ef99342e0ee5069  d1  4012d97c7f3321d2
I/DEBUG(91):  d2  3f985a30f4230d02  d3  3fa55553e1053a42
I/DEBUG(91):  d4  543f7d0ef4230d02  d5  41d50fdf43800000
I/DEBUG(91):  d6  0000000000000000  d7  42c8000041f00000
I/DEBUG(91):  d8  0000000000000000  d9  0000000000000000
I/DEBUG(91):  d10 0000000000000000  d11 0000000000000000
I/DEBUG(91):  d12 0000000000000000  d13 0000000000000000
I/DEBUG(91):  d14 0000000000000000  d15 0000000000000000
I/DEBUG(91):  scr 80000012
I/DEBUG(91):          #00  pc 005fde96  /data/data/com.my.app/lib/libapp.so (_ZN4math7Matrix4C2Effffffffffffffff)

  5fde90:   eddd 0b0c   vldr    d16, [sp, #48]  ; 0x30
  5fde94:   eddd 1b0e   vldr    d17, [sp, #56]  ; 0x38
  5fde98:   f8cd 8028   str.w   r8, [sp, #40]   ; 0x28

If you want to be able to load one library or the other without having a dependency on the module name, it's probably easiest to avoid linking directly to that library, and just loading the right one at runtime and loading symbols from it dynamically using dlsym . 如果您希望能够不依赖模块名称地加载一个库或另一个库,则最简单的方法是避免直接链接到该库,而只是在运行时加载正确的库并使用dlsym从库动态加载符号。 If the library only has got a few functions/entry points, this shouldn't be too complicated. 如果库只有几个函数/入口点,这应该不太复杂。 If, on the other hand, the library has got a very large interface (C++ libraries often tend to use lots of entry points, much harder to load with dlsym ), that's much harder. 另一方面,如果该库具有非常大的接口(C ++库通常倾向于使用许多入口点,而使用dlsym很难加载),那就难得多了。

Technically, if this wasn't limited to android, you could have two different versions of the library with identical names in different directories, and load the right one beforehand. 从技术上讲,如果这不仅限于android,您可以在不同目录中使用两个相同名称的库,并预先加载正确的库。

But in principle you shouldn't necessarily need two different versions of the library. 但是原则上您不一定需要该库的两个不同版本。 You wrote: 你写了:

but it turns out a native library cannot be both plain-v7a and NEON at the same time anyway, the runtime linker simply won't load such a library on some devices. 但事实证明,本机库无论如何不能同时是plain-v7a和NEON,运行时链接程序根本不会在某些设备上加载此类库。

A library most certainly can contain both plain-v7a and NEON code, and should load on all armeabi-v7a devices - there are many such libraries out there. 一个库肯定可以同时包含纯v7a和NEON代码,并且应该在所有armeabi-v7a设备上加载-那里有很多这样的库。 You just need to make sure that the common codepaths aren't built with NEON enabled, and that the internal NEON codepaths only are used after a runtime check. 您只需要确保未在启用NEON的情况下构建通用代码路径,并且仅在运行时检查之后才使用内部NEON代码路径。 This requires that the library is designed with runtime-enabled SIMD-extensions in mind from the start, though - some libraries might be designed to decide on such things at compile time. 但是,这要求库从一开始就考虑到启用了运行时的SIMD扩展名-有些库可能旨在在编译时决定此类事情。 And adding -mfpu=neon (or adding .neon to the filename in Android.mk ) to generic, non-SIMD code doesn't really add much measurable performance boost to normal code; 在普通的非SIMD代码中添加-mfpu=neon (或在Android.mk的文件名中添加.neon )并不能真正提高普通代码的性能。 at worst it will just insert a few instructions occasionally which will stop the code from running on other devices, without actually helping performance much. 在最坏的情况下,它偶尔会插入一些指令,这将阻止代码在其他设备上运行,而实际上并没有太大的帮助。

The hello-neon sample in the NDK is a trivial example on how to handle this. NDK中的hello-neon示例是有关如何处理此问题的简单示例。 Actual real-world libraries that do this are libav and OpenH264, to mention just a few. 举个例子,实际的实际库是libav和OpenH264。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM