动态链接库是一种通用的软件组件技术,是多种操作系统中提供基本服务的方式。比如Win32内核就是3个DLL文件构成。这种技术在Linux操作系统下也有对应的实现,就是Linux标准对象Standard Ojbect,对应的文件扩展名为.so。
下面通过一个简单的例子开始介绍Linux标准对象。
保存为myso.c文件,按照如下编译: $ gcc -fPIC -shared -o libmyso.so myso.c (备注:-shared 该选项指定生成动态连接库;-fPIC:表示编译为位置独立的代码)。生成一个libmyso.so文件,按照Linux标准对象的命名惯例,应该在库名称之前加上"lib"前缀,尽管不是必须的。编译开关-fPIC代表函数符号可以重定向,-shared代表编译结果是一个标准对象。
下面我们编写调用程序:
保存为invoke.c,按照如下gcc开关编译:$ gcc -o test invoke.c ./libmyso.so 。编译生成test可执行文件。如上编译条件的最后一条是所调用的标准对象文件名,注意必须含有路径。如果只是使用libmyso.so,则必须确保这个文件在可访问的PATH下面。
如下测试结果:
=============可执行bin运行时动态调用so的函数====================================
有的场合,需要在诸如frameworks\base\cmds\bootanimation\中的bin里面,调用so中的函数。一种是静态加载,在Android.mk中指定(没有验证);另一种是用dlopen动态加载so的函数。可参见:https://www.cnblogs.com/fellow1988/p/6185011.html。我自己的调试案例(待验证):
#include <dlfcn.h>
char customerName[256];
property_get("ro.customer.name", customerName, "");
bool encryptedAnimation = atoi(decrypt) != 0 || !strcmp("trigger_restart_min_framework", decrypt);
ALOGD("[BootAnimation ro.customer.name %s ]", customerName);
void* handle = dlopen("/system/lib/libmetazone.so", RTLD_LAZY);
if(handle == NULL)
ALOGD("dlopen libmetazone.so ERROR");
else{
typedef unsigned int (*init)();
typedef unsigned int (*deinit)();
typedef unsigned int (*ZoneRead)(unsigned int u4Idx,unsigned int *pu4Data);
unsigned int direction;
init MetaZoneInit = (init)dlsym(handle,"MetaZone_Init");
deinit MetaZonedeInit = (deinit)dlsym(handle,"MetaZone_Deinit");
ZoneRead MetaZoneRead = (ZoneRead)dlsym(handle,"MetaZone_Read");
MetaZoneInit();
MetaZoneRead(0x10054,&direction);
MetaZonedeInit();
dlclose(handle);
ALOGD("bootanimation direction is %d",direction);
}