xamarin繫結原生庫的一些坑
最近一個專案涉及到較多的第三方庫的繫結技術,中間遇到了幾個坑,記錄下來與大家分享
繫結Jar庫
monoandroid對原生庫的呼叫都通過Android.Runtime.JNIEnv進行調入(http://docs.xamarin.com/guides/android/advanced_topics/java_integration_overview/working_with_jni/),例如Android.App.Activity類只是封裝好了大量的JNIEnv對Davlik的呼叫,而對於開發人員自己繫結的庫則由ide自動生成ACW,如果類繼承了JavaObject由於需要Davlik虛擬機器呼叫相應的方法則會生成相應的java程式碼(MCW).在對一個第三方庫進行繫結時遇到的問題是相應的java庫中有一個方法對傳入的list進行了改變而沒有返回值,建立的Jar Binding專案生成的方法是普通的傳值方式而不是ref或者out,查詢mono的文件在metadata.xml中設定成pass_as但是無效(ref),由於專案比較急當時想了一個折中的方法是對第三方庫進行二次封裝,在二次封裝的庫中返回值,折騰了半天Android Studio(吐槽:gradle是又慢建立庫又麻煩)終於搞定,後來翻看官方的文件(http://docs.xamarin.com/guides/android/advanced_topics/api_design/)發現官方提供了copyless marshaling的類,測試使用後正常。
繫結C++開發的ios靜態庫
另一個坑發生在繫結一個ios平臺的靜態庫上面,該靜態庫使用C++開發,根據提供的demo程式碼封裝了一個ios版本的static lib,建立ios的測試程式執行成功。但是繫結後一直提示找不到一些libssh2的方法,剛開始的思路是去github下載相應的庫編譯新增但是還是報錯,與xamarin的支援工程師郵件聯絡說是需要庫開發商提供相應的庫,聯絡廠商工程師反饋沒有對相應的庫的依賴,分析認為是繫結庫的設定有問題但是多次測試不同的monotouch argmument都沒有效果, 為了分析出相應的報錯的方法的出處。根據以往檢視dll的方法的思路找到了一個檢視ios庫的工具:MachOView(後發現使用自帶的nm命令也行).查看出再相應的靜態庫中確實有對應的方法,繼續與庫開發商溝通但是那邊檢查了一遍還是沒有找到相應的依賴。進一步分析build log發現xamarin studio進行編譯的時候對相應的庫進行了force_load,google開了一下force_load和all_load的相關資訊,原來使用這個引數的話會強制libtool載入所有的簽名。將相應的資訊提供給xamarin的工程師,工程師反饋使用SmartLink屬性,測試成功。去查了一下SmartLink相關的資訊發現開啟該標示後後編譯器會分析相應的引用並只加載相關的symbol。來回折騰了10多天終於搞定了,從中得出的經驗就是要使用已有經驗一步步的向下分析才能解決問題。
補充:後面又發現一個坑,繫結另一個視訊相關的庫的時候提示Duplicate symbol,然後用nm工具看了一下確實有兩個一樣名字的方法,google了一下需要設定編譯引數dead_strip,再monouthch中設定為-gcc_flags="-stdlib=libstdc++ -dead_strip"後正常