动态链接库是一种通用的软件组件技术,是多种操作系统中提供基本服务的方式。比如Win32内核就是3个DLL文件构成。这种技术在Linux操作系统下也有对应的实现,就是Linux标准对象Standard Ojbect,对应的文件扩展名为.so。

      下面通过一个简单的例子开始介绍Linux标准对象。

Linux 静态链接库与动态链接库之二:动态链接库生成及使用 && 可执行bin运行时动态调用so的函数_path

保存为myso.c文件,按照如下编译: $ gcc -fPIC -shared -o myso.c (备注:-shared 该选项指定生成动态连接库;-fPIC:表示编译为位置独立的代码)。生成一个文件,按照Linux标准对象的命名惯例,应该在库名称之前加上"lib"前缀,尽管不是必须的。编译开关-fPIC代表函数符号可以重定向,-shared代表编译结果是一个标准对象。

      下面我们编写调用程序:

Linux 静态链接库与动态链接库之二:动态链接库生成及使用 && 可执行bin运行时动态调用so的函数_object_02

保存为invoke.c,按照如下gcc开关编译:$ gcc -o test invoke.c ./ 。编译生成test可执行文件。如上编译条件的最后一条是所调用的标准对象文件名,注意必须含有路径。如果只是使用,则必须确保这个文件在可访问的PATH下面。

      如下测试结果:

Linux 静态链接库与动态链接库之二:动态链接库生成及使用 && 可执行bin运行时动态调用so的函数_path_03

=============可执行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/", RTLD_LAZY);
	if(handle == NULL)
		ALOGD("dlopen  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);
	}