so库调用

1.动态调用

//my.h
void test();

 

//my.c
#include<stdio.h> void test() { printf("This is a test\n"); }

 

//main.c
#include "my.h"
int main(int argc, char* argv[]){ test(); return 0; }

动态库调用

muhe221@muhe:~/work/lib$ gcc -c my.c
muhe221@muhe:~/work/lib$ ls
main.c  my.c  my.h  my.o
muhe221@muhe:~/work/lib$ gcc -fpic -shared -o libmy.so my.c
muhe221@muhe:~/work/lib$ ls
libmy.so  main.c  my.c  my.h  my.o
muhe221@muhe:~/work/lib$ gcc main.c -L. -lmy -o main.o          // -o main.o必须放最后面 否则报错 why?
muhe221@muhe:~/work/lib$ ls
libmy.so  main.c  main.o  my.c  my.h  my.o
muhe221@muhe:~/work/lib$ ./main.o
./main.o: error while loading shared libraries: libmy.so: cannot open shared object file: No such file or directory
muhe221@muhe:~/work/lib$ sudo cp libmy.so /lib
muhe221@muhe:~/work/lib$ ./main.o
This is a test
muhe221@muhe:~/work/lib$

编译生成动态库文件,要加上 -shared 和 -fpic 选项 ,库文件名以lib开头, 以.so 结尾。

 -L 指定函数库查找的位置,注意L后面还有'.',表示在当前目录下查找

-l则指定函数库名,其中的lib和.a(.so)省略。
 
  -fPIC
           If supported for the target machine, emit position-independent code, suitable for dynamic linking and
           avoiding any limit on the size of the global offset table.  This option makes a difference on the m68k,
           PowerPC and SPARC.

           Position-independent code requires special support, and therefore works only on certain machines.

           When this flag is set, the macros "__pic__" and "__PIC__" are defined to 2.

静态库调用

muhe221@muhe:~/work/lib$ ls
main.c  my.c  my.h
muhe221@muhe:~/work/lib$ gcc -c my.c
muhe221@muhe:~/work/lib$ ls
main.c  my.c  my.h  my.o
muhe221@muhe:~/work/lib$ ar -rc libmy.a my.o
muhe221@muhe:~/work/lib$ ls
libmy.a  main.c  my.c  my.h  my.o
muhe221@muhe:~/work/lib$ gcc -l . -o main.o -c main.c
muhe221@muhe:~/work/lib$ ls
libmy.a  main.c  main.o  my.c  my.h  my.o
muhe221@muhe:~/work/lib$ gcc -o main -L. main.o -lmy
muhe221@muhe:~/work/lib$ ls
libmy.a  main  main.c  main.o  my.c  my.h  my.o
muhe221@muhe:~/work/lib$ ./main
This is a test
muhe221@muhe:~/work/lib$

 -------------------------------------------------------------------------------------------------------------------------------

为了使程序方便扩展,具备通用性,可以采用插件形式。采用异步事件驱动模型,保证主程序逻辑不变,将各个业务已动态链接库的形式加载进来,这就是所谓的插件。linux提供了加载和处理动态链接库的系统调用

//calc.c
int add(int a,int b)
{
    return (a + b);
}

int sub(int a, int b)
{
    return (a - b);
}

int mul(int a, int b)
{
    return (a * b);
}

int div(int a, int b)
{
    return (a / b);
}

 

//main.c
#include <stdio.h>
#include <stdlib.h>
#include <dlfcn.h>

//动态链接库路径
#define LIB_CACULATE_PATH "./libcalculate.so"

//函数指针
typedef int (*CAC_FUNC)(int, int);

int main()
{
    void *handle;
    char *error;
    CAC_FUNC cac_func = NULL;

    //打开动态链接库
    handle = dlopen(LIB_CACULATE_PATH, RTLD_LAZY);
    if (!handle) {
      fprintf(stderr, "%s\n", dlerror());
      exit(EXIT_FAILURE);
    }

    //清除之前存在的错误
    dlerror();

    //获取一个函数
    cac_func = dlsym(handle, "add");
    if ((error = dlerror()) != NULL)  {
      fprintf(stderr, "%s\n", error);
      exit(EXIT_FAILURE);
    }
    printf("add: %d\n", (*cac_func)(8, 2));

    cac_func = (CAC_FUNC)dlsym(handle, "sub");
    printf("sub: %d\n", cac_func(8, 2));

    cac_func = (CAC_FUNC)dlsym(handle, "mul");
    printf("mul: %d\n", cac_func(8, 2));

    cac_func = (CAC_FUNC)dlsym(handle, "div");
    printf("div: %d\n", cac_func(8, 2));

    //关闭动态链接库
    dlclose(handle);
    exit(EXIT_SUCCESS);
}

 dlopen以指定模式打开指定的动态连接库文件,并返回一个句柄给调用进程,dlerror返回出现的错误,dlsym通过句柄和连接符名称获取函数名或者变量名,dlclose来卸载打开的库。 dlopen打开模式如下:

  RTLD_LAZY 暂缓决定,等有需要时再解出符号 
  RTLD_NOW 立即决定,返回前解除所有未决定的符号。

 

muhe221@muhe:~/test/test/nel$ ls
calc.c  main.c
muhe221@muhe:~/test/test/nel$ gcc -fpic -shared -o libcalculate.so calc.c
muhe221@muhe:~/test/test/nel$ ls
calc.c  libcalculate.so  main.c
muhe221@muhe:~/test/test/nel$ gcc -rdynamic -o main main.c -ldl
muhe221@muhe:~/test/test/nel$ ls
calc.c  libcalculate.so  main  main.c
muhe221@muhe:~/test/test/nel$ ./main 
add: 10
sub: 6
mul: 16
div: 4

 

posted @ 2015-07-29 11:17  牧 天  阅读(462)  评论(0)    收藏  举报