dlopen

dl1.c 是主函数

//dl1.c

#include<stdio.h>
#include<dlfcn.h>
#include"dl1.h"

int main(){
	scanf("%d%d", &a, &b);
	p = dlopen("./dl2.so", RTLD_NOW);
	func_max = dlsym(p, "max");
	printf("%d 与 %d相比,%d为大数。\n", a, b, (*func_max)(a, b));
	dlclose(p);
}
d1l.h
//dl1.h
int a, b;
void *p;
int (*func_max)(int, int);
dl2.c 是比较函数,用于编译成so文件
//dl2.c
#include<stdio.h>

int max(int x, int y){
	return x>y?x:y;
}

编译

gcc dl2.c -o dl2.so -shared -fPIC
gcc dl1.c -o dl1 -ldl

-ldl选项,表示生成的对象模块需要使用共享库

(1)dlopen()
第一个参数:指定共享库的名称,将会在下面位置查找指定的共享库.
-环境变量LD_LIBRARY_PATH列出的用分号间隔的所有目录.
-文件/etc/ld.so.cache中找到的库的列表,用ldconfig维护.
-目录usr/lib.
-目录/lib.
-当前目录.

第二个参数:指定如何打开共享库。
-RTLD_NOW:将共享库中的所有函数加载到内存
-RTLD_LAZY:会推后共享库中的函数的加载操作,直到调用dlsym()时方加载某函数

(2)dlsym()
调用dlsym时,利用dlopen()返回的共享库的phandle以及函数名称作为参数,返回要加载函数的入口地址。

(3)dlerror()
该函数用于检查调用共享库的相关函数出现的错误。

(4)dlclose() 
该函数用于关闭动态库。

编写Android.mk

LOCAL_PATH:= $(call my-dir)

include $(CLEAR_VARS)
LOCAL_SRC_FILES:= \
dl2.c
LOCAL_MODULE_TAGS := optional
LOCAL_PRELINK_MODULE := true
#LOCAL_CFLAGS=-fPIC
LOCAL_MODULE:= libdl2
include $(BUILD_SHARED_LIBRARY)

include $(CLEAR_VARS)
LOCAL_SRC_FILES:= \
dl1.c
#LOCAL_CFLAGS:=-lmax
#LOCAL_LDFLAGS:= -Lout/target/product/generic/obj/lib
LOCAL_MODULE_TAGS := optional
LOCAL_SHARED_LIBRARIES := \
    libdl

#LOCAL_CFLAGS=-ldl
LOCAL_MODULE:= dl1
include $(BUILD_EXECUTABLE)

libdl.so是系统自动生成

上一次之所以失败,原因似乎是使用了红色字体的那一句,因为我将其更换为蓝色字体的那一句,问题就解决了。看来这样写在链接时才能正确找到libdl.so,而包含该.so文件是使用dlopen函数的保证。

将这三个文件放在Android源码目录下的development目录下的dl文件夹中(dl文件夹是新建的),然后在终端中使用root权限进入到Android源码目录下,执行 make dl1  ,make dl2。编译出dl2.so和dl1

使用以下命令将它们放入Android模拟器,注意要先启动emulator

adb push Android源码目录/out/target/product/generic/system/lib/dl2.so /data
adb push Android源码目录/out/target/product/generic/system/bin/dl1 /data

进入data文件夹执行
adb shell
# cd data
# ./dl1

87 9(这里随便输入两个数)
dlopen ok!

87与9相比,87为大数。

你可能感兴趣的:(dlopen)