Android – 動態庫雙向依賴解決方法

問題:
昨天調試一個CA庫link失敗的問題:ca廠商一般提供的都是靜態ca庫,這樣子你直接將其與
你的庫link在一起即可使用,但由於apk在ndk中編譯器:android-ndk-r6b\arm-linux-androideabi-4.4.3
而ca庫使用hisi編譯器:arm-eabi-4.4.0_hisi 兩者使用的編譯不同,所以需要在linux android環境
下將ca靜態庫打包成動態庫,而且用戶實現的ca函數將會link失敗,生成的動態庫將在ndk中使用。

下面是一個簡單的測試例子,用於說明一下如何做到相互依賴而編譯生成動態庫的方法

1、首先編譯生成動態庫
首先定義頭文件:test.h
 1. <span style="font-size:16px;">#ifndef XXX_TEST_H___ 
2. #define XXX_TEST_H___  
3.  
4. /* 由link的庫實現 */ 
5. extern void testA(); 
6. extern void testB(); 
7.  
8. /* 由本身庫實現而由外部調用 */ 
9. extern void testC(); 
10. extern void testD(); 
11.  
12. struct AAInterface{ 
13.     void (*testA)(); 
14.     void (*testB)(); 
15. }; 
16.  
17. extern void setInterface(struct AAInterface *cb); 
18.  
19. #endif /* XXX_TEST_H___ */  
20. </span> 
 
然後實現文件:testA.c
 1. <span style="font-size:16px;">#include <assert.h> 
2. #include <stdlib.h>  
3. #include <string.h>  
4. #include <cutils/log.h>  
5. #include "test.h"  
6.  
7. static struct AAInterface g_aa_interface ; 
8.  
9. /* 由link的庫實現 */ 
10. extern void testA(){ 
11.     g_aa_interface.testA(); 
12. } 
13.  
14. extern void testB(){ 
15.     g_aa_interface.testB(); 
16. } 
17.  
18. extern void testCall(){ 
19.     LOGI("testCall 111"); 
20.     testA(); 
21.     LOGI("testCall 222"); 
22.     testB(); 
23.     LOGI("testCall 333"); 
24. } 
25.  
26. /* 由本身庫實現而由外部調用 */ 
27. extern void testC(){ 
28.     LOGI("testC call in—>"); 
29.     testCall(); 
30.     LOGI("testC call out<—"); 
31. } 
32.  
33. extern void testD(){ 
34.     LOGI("testD call in—>"); 
35.     testCall(); 
36.     LOGI("testD call out<—"); 
37. } 
38.  
39. extern void setInterface(struct AAInterface *cb){ 
40.     LOGI("setInterface call in –>"); 
41.     memset((void*)&g_aa_interface,0x00,sizeof(g_aa_interface)); 
42.     g_aa_interface.testA = cb->testA; 
43.     g_aa_interface.testB = cb->testB; 
44.     LOGI("setInterface call out <–"); 
45. } 
46. </span> 
 
這裡最重要的是利用setInterface接口解決相互link的問題,這就是本質所在。大傢一看就明白瞭,這也是動態
庫導出函數的最好方法,一般使用QueryInterface及enumInterface即可,使用結構將

編譯方法:
LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)
LOCAL_MODULE_TAGS := eng
LOCAL_MODULE:= libtestASO
LOCAL_SRC_FILES:= \
testA.c \
LOCAL_SHARED_LIBRARIES := liblog\
LOCAL_C_INCLUDES += \
    $(TOP)/frameworks/base/test/testA \
LOCAL_CFLAGS += -D_cplusplus
LOCAL_PRELINK_MODULE := false
include $(BUILD_SHARED_LIBRARY)

2、使用生成的動態庫
 1. <span style="font-size:16px;">#include <assert.h> 
2. #include <stdlib.h>  
3. #include <string.h>  
4. #include <cutils/log.h>  
5. #include <test.h>  
6.  
7. /* 由link的庫實現 */ 
8. extern void testA(){ 
9.     LOGI("testA call …"); 
10. } 
11.  
12. extern void testB(){ 
13.     LOGI("testB call …"); 
14. } 
15.  
16. int main(void){ 
17.     struct AAInterface *itf = (struct AAInterface*)calloc(1,sizeof(struct AAInterface)); 
18.     itf->testA = testA; 
19.     itf->testB = testB; 
20.     setInterface(itf); 
21.      www.aiwalls.com
22.     testC(); 
23.     testD(); 
24.     return 0; 
25. } 
26. </span> 
 
ok,知道瞭如何解決這種相互依賴的方法,解決方法相當解決。。對於這種A需要link B,而B又需要link A的相互關系,這種方法就會起到很好的作用瞭。

 

作者:andyhuabing

發佈留言