概述
在Android開發(fā)中有時會遇到使用JNI調用C/C++函數庫的場景。一般這個時候都是使用NDK將C/C++源代碼編譯出so文件,然后進行調用。但是有時候會遇到另外的情況:
我們在NDK項目中還要再引入其他第三方的SO庫
這個時候該怎么編譯呢?
通過使用動態(tài)函數庫的調用方法,直接包含其頭文件,便可以直接調用庫中的類和方法。
具體使用過程可以分為兩步:
編寫JNI文件包含第三方庫的頭文件。
編寫MK文件引入預編譯庫(即第三方庫)。
舉個例子
拿現在項目中遇到的一個具體情景:
現在手頭有一個USB設備,要求實現在windows、Android、Linux嵌入式三平臺通用的USB驅動庫,然后各個平臺只用做小量修改即可使用。經過評估決定使用github上的一個開源項目libusb來實現,使用中需要通過JNI對已有的so庫再做一層封裝,所以這里使用上面說的方式來調用,如下。
編寫JNI文件
在要編寫的源文件目錄下新建include文件夾,將要使用的函數所在的頭文件放入其中,如:libusb.h。
在我們的源碼中包含這個頭文件
#include "include/libusb.h"
然后直接在需要使用的位置調用相應的函數即可:
JNIEXPORT void JNICALL Java_com_usbtest_UsbTest_libUsbInit
(JNIEnv *env, jclass jobj) {
if (libusb_init(NULL) < 0)
{
LOGD("VeinSensorBase::Open(): libusb_init() <0\n");
}
}
編譯MK文件
首先將第三方庫作為預編譯引入
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := usb_pre
LOCAL_SRC_FILES := usb/libusb-1.0.so
LOCAL_EXPORT_C_INCLUDES := include
include $(PREBUILT_SHARED_LIBRARY)
include $(CLEAR_VARS)
LOCAL_MODULE := test
LOCAL_SRC_FILES := usb_test.c
LOCAL_SHARED_LIBRARIES := usb_pre
LOCAL_LDLIBS := -llog
include $(BUILD_SHARED_LIBRARY)
其中:
LOCAL_MODULE := usb_pre給這個第三方庫取一個名字,不需要與原來的名字相同。LOCAL_SRC_FILES := usb/libusb-1.0.so表示這個庫的路徑,是在MK文件的目錄下的usb目錄中。LOCAL_EXPORT_C_INCLUDES := include引用的第三方so庫的頭文件位置。PREBUILT_SHARED_LIBRARY表示這是一個共享庫,即so庫。LOCAL_SHARED_LIBRARIES := usb_pre這一步則表示此模塊依賴于上面命名的預編譯庫。
然后執(zhí)行ndk-build編譯即可,此時在libs文件夾中會生成兩個so文件,分別為libtest.so和libusb-1.0.so,都拷貝到項目中就可以了。