动态库和静态库在C/C++开发中很常见,相比静态库直接被编译到可执行程序,动态库运行时加载使得可执行程序的体积更小,更新动态库可以不用重新编译可执行程序等诸多好处。作者是一个Linux后台开发,这些知识经常用到,所以整理了一下这方面的知识。静态库相对简单,本文只关心Linux平台下的动态库。
  创建动态库
  这里我把一个短小却很有用的哈希函数编译成动态库做为示例,ELFhash用于对字符串做哈希,返回一个无符号整数。
//elfhash.h
#include
unsigned long  ELFhash(const char* key);
//elfhash.c
#include "elfhash.h"
unsigned long ELFhash(const char* key)
{
unsigned long h = 0, g;
while( *key ) {
h = ( h > 24;
h &= ~g;
}
return h;
}
  接下来使用gcc编译以上代码,并用ld将编译的目标文件链接成动态库
  gcc -fPIC -c -Wall elfhash.c
  ld  -shared elfhash.o -o libelfhash.so
  其中-fPIC意思是生成位置无关的代码(Position Independent Code),适用于动态库,在多个进程中共享动态库的同一份代码。ld的-shared选项告诉链接器创建的是动态库。gcc也可以间接调用ld生成动态库
  gcc -fPIC -shared -Wall -o libelfhash.so elfhash.c
  使用动态库
  动态库的使用方法有两种一种是隐式使用,第二种是显式使用。隐式使用的方法很简单。
  #include "elfhash.h"
  int main()
  {
  printf("%ldn", ElfHash("key-for-test"));
  return 0;
  }
  显式使用动态库需要借助以下几个函数
#include
void *dlopen(const char *filename, int flag);
//flag可以是RTLD_LAZY,执行共享库中的代码时解决未定义符号,RTLD_NOW则是dlopen返回前解决未定义符号。
char *dlerror(void);
//当发生错误时,返回错误信息
void *dlsym(void *handle, const char *symbol);
//获取符号
int dlclose(void *handle);
//关闭
  应用上面几个函数,调用ELFhash实现跟隐式调用一样的功能
#include "elfhash.h"
#include
#include
int main() {
void *handle;
unsigned long (*hash)(const char*);
char *error;
handle = dlopen ("./libelfhash.so", RTLD_LAZY);
if (!handle) {
fputs (dlerror(), stderr);
exit(1);
}
hash = dlsym(handle, "ElfHash");
if ((error = dlerror()) != NULL)  {
fputs(error, stderr);
exit(1);
}
printf ("%ldn", (*hash)("key-for-test"));
dlclose(handle);
}
  至此了解以上的知识可以创建和使用动态库了。 实际应用中我们可能还是会遇到一些问题。