在Android平臺使用SNPE庫以前都沒什么太大問題,最近因為要使用userBuffer,編譯時報鏈接錯誤:
undefined reference to `zdl::DlSystem::TensorShape::TensorShape(std::vector<unsigned long, std::allocator<unsigned long> >)
因為是鏈接錯誤,而且查看了頭檔案,TensorShape有對應的多載建構式,所以懷疑SNPE的庫檔案libSNPE.so不對,懷疑高通提供的庫檔案不對,好像這也不太可能,一時間陷入了困境,
開始從高通的客服那邊沒有得到太有用的資訊,只能自己想辦法,用objdump從庫檔案dump出符號表看看有沒有對應的函式,但是高通release庫肯定是把符號表去掉了的,只能通過objdump -T出來動態符號,從動態符號中篩選出和TensorShape相關的,然后找一些看著可能像的符號,用c++filt還原出函式名,
先在x86_64平臺的libSNPE.so找到了
c++filt _ZN3zdl8DlSystem11TensorShapeC1ESt6vectorImSaImEE
zdl::DlSystem::TensorShape::TensorShape(std::vector<unsigned long, std::allocator<unsigned long> >)
這和我們需要的函式是一樣的,也就是說x86_64平臺的libSNPE.so肯定是包含這個多載的函式實作的,那android平臺的不應該沒有啊?繼續在android平臺的libSNPE.so里找,終于找到
c++filt _ZN3zdl8DlSystem11TensorShapeC2ENSt6__ndk16vectorImNS2_9allocatorImEEEE
zdl::DlSystem::TensorShape::TensorShape(std::__ndk1::vector<unsigned long, std::__ndk1::allocator<unsigned long> >)
看著像,但是和平常見到的是不太一樣,vector的定義是std::__ndk1::vector,這說明SNPE鏈接的是LLVM的標準libc++庫,這樣原因清楚了,我們編譯使用的是cmake,最開始在build.gradle檔案中并沒有指定ANDROID_STL變數,編譯使用的應該不是libc++庫,導致了鏈接錯誤,(按照NDK檔案的說法,ANDROID_STL默認的是c++_static,這是libc++的靜態庫,按理是能夠鏈接通過的,實際也試過了,ANDROID_STL指定c++_static是能夠編譯通過的,但是不指定,就會出現上面的undefined reference錯誤,我懷疑默認使用的是GNU的庫)
因為還使用了opencv的庫(用的是opencv3的版本),如果改用libc++,會出現鏈接opencv出錯,查找opencv的檔案,opencv4.0.0開始使用c++11庫,因此改用opencv4,在build.gradle檔案中加上ANDROID_STL定義,編譯通過,
android {
defaultConfig {
externalNativeBuild {
cmake {
arguments '-DANDROID_STL=c++_shared'
}
}
}
}
按NDK的檔案,從NDK r18開始,libc++成為NDK中唯一可用的STL,因為我們使用的NDK版本還比較低,所以開始并沒有出錯,隨著NDK升級,不僅r18開始libc++是唯一的STL,而且gcc也不再支持,只能使用clang,還是慢慢轉過去了,以免出現一些莫名其妙的問題,
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/54930.html
標籤:C++
