轉自:http://hi.baidu.com/mcu99/blog/item/216f1fce17e1c00b92457edd.html
以下程式在Ubuntu作業系統上,gcc編譯通過。但是當我想把它們移到Android下運行時,則出現錯誤,問題出在什麼地方尚不得而知。
(補充:該問題已經解決,詳見http://hi.baidu.com/mcu99/blog/item/59ed168014b130df9023d942.html)
/***********************dl1.c的內容**************************/
#include<stdio.h>
#include<dlfcn.h>
int main()
{
int a,b;
void *p;
int (*func)(int,int);
scanf("%d%d",&a,&b);
p=dlopen("./dl2.so",RTLD_NOW);
func=dlsym(p,"max");
printf("%d與%d相比,%d為大數。\n",a,b,(*func)(a,b));
dlclose(p);
}
/***********************dl1.c的內容**************************/
/***********************dl2.c的內容**************************/
#include<stdio.h>
int max(int x,int y)
{
return x>y?x:y;
}
/***********************dl2.c的內容**************************/
編譯:
gcc dl2.c -shared -fPIC -o dl2.so
gcc -o dl1 -ldl dl1.c
附《產生動態連結程式庫是否必須使用 -fPIC 的問題》文章連結
http://hi.baidu.com/han_zhi_xing/blog/item/08f0ef37a50409360a55a9b4.html
運行:
admin@admin-desktop:/abc/test$ ./dl1
2008 2012
2008與2012相比,2012為大數。
===========================
在Android下,我編寫了一個Android.mk來處理它們
LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
LOCAL_SRC_FILES:= \
dl2.c
LOCAL_PRELINK_MODULE := true
LOCAL_CFLAGS=-fPIC
LOCAL_MODULE:= dl2
include $(BUILD_SHARED_LIBRARY)
include $(CLEAR_VARS)
LOCAL_SRC_FILES:= \
dl1.c
LOCAL_CFLAGS=-ldl
LOCAL_PRELINK_MODULE := true
LOCAL_MODULE:= dl1
include $(BUILD_EXECUTABLE)
然後分別make dl2和make dl1,然後將編譯得到的dl1和dl2.so送到模擬器中的同一目錄下,但運行時出現如下錯誤
# ./dl1
3 5
[1] + Stopped (signal) ./dl1
#
[1] Segmentation fault ./dl1
不知道問題出在什麼地方……
在這篇文章中(http://hi.baidu.com/mcu99/blog/item/216f1fce17e1c00b92457edd.html),我在Android下使用dlopen函數調用.so檔案沒有成功,於是只得改用在編譯過程中指定.so檔案的方式加以調用,這次在Android下倒是通過了。
先在(Android源碼目錄)/development/目錄下建立一個檔案夾,比如起名叫 test123
在test123目錄下建立以下三個檔案:test.c、max.c、Android.mk
/**************** test.c 主程式 ********************/
#include<stdio.h>
extern max(int,int);
int main()
{
int a=5,b=3,c;
c=max(a,b);
printf("%d與%d相比,%d大。\n",a,b,c);
return 0;
}
/**************** max.c 將要被編譯成動態連結程式庫 ********************/
int max(int x,int y)
{
return x>y?x:y;
}
/**************** Android.mk 是Android系統中的Makefile檔案 ********************/
LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
LOCAL_SRC_FILES:= \
max.c
LOCAL_PRELINK_MODULE := false
LOCAL_MODULE:= libmax
include $(BUILD_SHARED_LIBRARY)
include $(CLEAR_VARS)
LOCAL_SRC_FILES:= \
test.c
LOCAL_CFLAGS=-lmax
LOCAL_LDFLAGS:= \
-Lout/target/product/generic/obj/lib
LOCAL_SHARED_LIBRARIES := \
libmax
LOCAL_MODULE:= test
include $(BUILD_EXECUTABLE)
建立好這三個檔案後,用cd命令回到Android源碼目錄下,執行make test。注意不是檔案夾名 test123
再用命令
adb push (Android源碼目錄)/out/target/product/generic/system/bin/test /data
adb push out/target/product/generic/system/lib/libmax.so /system/lib
將test程式和編譯好的libmax.so送進模擬器下相應的位置,其中libmax.so應該放到 /system/lib下,不然test找不到它,test程式就無所謂了,放在什麼地方都行。
用adb shell進入模擬器的控制台,當然事先要先把emulator啟動起來,否則adb shell會失敗。
進入test所在目錄,./test運行
# ./test
5與3相比,5大。