在android上使用libevent

來源:互聯網
上載者:User

1. 安裝NDK和ADT

其中NDK用於編譯C++代碼,而ADT用於編譯Java代碼及產生apk包。

NDK雖然可以也可以在Windows下通過Cywin來運行,但是會遇到命令列參數過長的問題(檔案比較多的時候)。因此,建議把NDK安裝在Linux系統上。

ADT則運行在Windows下,並不需要NDK,而只要把Linux下編譯好的.so檔案拷貝過來即可。

2. 編譯libevent

擷取libevent源碼,在linux系統下進行交叉編譯。 關鍵是./configure時,通過參數傳入NDK提供的交叉編譯工具,include和lib的路徑

會遇到一些小問題,細節請參照這篇文章Cross Compiling libevent for Android
就可以搞定。

最後make,就可以在.libs下看到編譯好的.so和.a檔案。

更多NDK交叉編譯的問題,可以看這篇文章Building Open Source libraries with Android NDK。

3. 編譯工程代碼

在NDK的samples目錄下建立工程目錄,比如myprj,然後再建立一個子目錄jni,把C++代碼拷入其中。

在jni目錄下建立Android.mk檔案,其內容如下

LOCAL_PATH := $(call my-dir)include $(CLEAR_VARS)#引入已經編譯好的檔案libevent.aLOCAL_MODULE := eventLOCAL_SRC_FILES := libevent/src/.libs/libevent.ainclude $(PREBUILT_STATIC_LIBRARY)include $(CLEAR_VARS)#引入已經編譯好的檔案libevent_pthreads.aLOCAL_MODULE := event_pthreadsLOCAL_SRC_FILES := libevent/src/.libs/libevent_pthreads.ainclude $(PREBUILT_STATIC_LIBRARY)include $(CLEAR_VARS)#編譯CPP源碼LOCAL_MODULE    := libxyzLOCAL_C_INCLUDES := libevent/src/includeLOCAL_C_INCLUDES += libxyz/#引用多級目錄下的所有的CPP檔案MY_FILES := $(wildcard libxyz/*.cpp)MY_FILES += $(wildcard libxyz/*/*.cpp)LOCAL_SRC_FILES += $(MY_FILES)#引用zlib庫,以及android的log庫LOCAL_LDLIBS += -lz -llog#引用前面定義的libevent靜態庫LOCAL_STATIC_LIBRARIES := eventLOCAL_STATIC_LIBRARIES += event_pthreads#編譯產生動態庫include $(BUILD_SHARED_LIBRARY)

需要說明的是,我們這裡使用的是libevent靜態庫,而不是動態庫。這是由於Android平台不支援versioned soname,即形如libevent.so.5.0這樣的檔案名稱。即便按照這篇文章介紹的,修改soname之後,libevent_pthreads.so載入時還是會遇到reloc失敗的問題。為何如此,通過objdump
-x查看,好像是libevent_pthreads.so匯入表裡沒有對libevent.so的引用,結果有些符號死活就是找不到。規避辦法,就是引用靜態庫。

日誌輸出,不使用printf,而可以使用__android_log_print()函數,這樣就可以在ADT的LogCat控制台看到輸出的日誌。

C++與Java之間綁定,使用JNI。參照hello_jni的例子,建立libxyz_jni.cpp檔案,為每個匯出函數產生綁定函數。比如

extern "C"{void Java_com_company_myprj_libxyz_foo(JNIEnv* env, jobject thiz){   libxyz_foo();}}

需要注意的是,最後的函數名稱foo不要帶"_",否則跟java端綁定就不能成功。

在jni目錄下運行ndk-build,就可以在上級的libs/armeabi下看到產生的libxyz.so檔案。

通過objdump -T libxyz.so就可以看到所有的匯出函數。

4.Java工程

建立普通的android工程,並把前面編譯得到libxyz.so放入libs/armeabi目錄下。

建立libxyz.java檔案,用於對libxyz.so引用,如下。

package com.company.myprj;public class libxyz {public native void foo();static{System.loadLibrary("xyz");}}

注意看清楚,package,class和method的名稱與.so的匯出函數名稱是如何一一對應的。

最後,在android工程裡合適的位置,就可以調用以上代碼了。

import com.company.myprj.libxyz;new libxyz().foo();

另外,需要在manifest檔案裡,給應用加上INTERNET存取權限。

<uses-permission android:name="android.permission.INTERNET"/>

如果是在模擬器裡運行,需要通過

adb forward tcp:1234 tcp:8080

把模擬器裡的8080連接埠轉成外部的1234連接埠,這樣就可以在PC機上訪問了。

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.