[英]Choosing and loading one of alternative shared libs at runtime
正在尝试根据文档中的CPU-ARM-NEON.html向应用程序添加NEON支持。 该文档提到了运行时检查,但事实证明,本机库无论如何不能同时为plain-v7a和NEON,运行时链接程序根本不会在某些设备上加载此类库。
因此,看起来我需要针对不同功能进行优化的同一个库的两个版本,才能在运行时手动加载一个。 据报道,这是可以做到的,尽管它离ndk-through-eclipse路径还有一步,而且我对如何进行设置感到困惑。
我想我列出了LOCAL_SHARED_LIBRARIES下的一个版本以便内核正确链接,但是随后列出的所有内容都添加到了内核依赖项中。 然后,运行时链接程序会在我加载内核时检查它是否存在,并且即使已经在其位置加载了另一个lib也会抛出该异常。
此外,未列出的库仍保持未剥离状态,并且不会自动添加到程序包中。 我必须从eclipse中导出未签名的apk,每次添加.so,签名,对齐和重新安装,这是可以忍受的,但远远不切实际。
关于如何在不引入按模块名称进行硬编码依赖的情况下如何构建核心二进制文件的任何建议? 是否有一种文明的方法可以将“未引用”的库与其余内容包装在一起?
最终找到了问题-使用.neon后缀构建了一个混合了霓虹灯和普通代码的文件。 显然,库可以同时包含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
如果您希望能够不依赖模块名称地加载一个库或另一个库,则最简单的方法是避免直接链接到该库,而只是在运行时加载正确的库并使用dlsym
从库动态加载符号。 如果库只有几个函数/入口点,这应该不太复杂。 另一方面,如果该库具有非常大的接口(C ++库通常倾向于使用许多入口点,而使用dlsym
很难加载),那就难得多了。
从技术上讲,如果这不仅限于android,您可以在不同目录中使用两个相同名称的库,并预先加载正确的库。
但是原则上您不一定需要该库的两个不同版本。 你写了:
但事实证明,本机库无论如何不能同时是plain-v7a和NEON,运行时链接程序根本不会在某些设备上加载此类库。
一个库肯定可以同时包含纯v7a和NEON代码,并且应该在所有armeabi-v7a设备上加载-那里有很多这样的库。 您只需要确保未在启用NEON的情况下构建通用代码路径,并且仅在运行时检查之后才使用内部NEON代码路径。 但是,这要求库从一开始就考虑到启用了运行时的SIMD扩展名-有些库可能旨在在编译时决定此类事情。 在普通的非SIMD代码中添加-mfpu=neon
(或在Android.mk
的文件名中添加.neon
)并不能真正提高普通代码的性能。 在最坏的情况下,它偶尔会插入一些指令,这将阻止代码在其他设备上运行,而实际上并没有太大的帮助。
NDK中的hello-neon
示例是有关如何处理此问题的简单示例。 举个例子,实际的实际库是libav和OpenH264。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.