[英]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.