Linux动态库的编写与调用

1. 用 c 语言写动态库:
/*
  * libsthc.h
  * Declarations for function add
  */
#include "stdio.h"
#include "stdlib.h"
#include "stdarg.h"
 
#ifdef __cplusplus
extern "C"
{
#endif
int add(int x, int y);
 
#ifdef __cplusplus
}
#endif
 
/*
  * libsthc.c
  * Implementation of function add declared in libsthc.h
  * in c language
  */
#include "libsthc.h"
 
int add(int x, int y)
{
         return x + y;
}
 
#makefile
libsthc.so:libsthc.o
         gcc -shared libsthc.o -lc -o libsthc.so
libsthc.o:libsthc.c libsthc.h
         gcc -fPIC -c libsthc.c -o libsthc.o
all:libsthc.so
clean:
         rm -f *.o *.so
 
make 完成后,会生成一个动态库,即 libsthc.so 。为了使其他程序也可以使用该动态库,需要将库文件 libsthc.so 拷贝到 /usr/lib 目录下 ( 由于权限的问题,一般要以 root 的身分进行拷贝 ) ,为了使其他程序也可以使用该动态库,需要将头文件 libsthc.h 拷贝到 /usr/include 目录下 ( 由于权限的问题 , 一般要以 root 的身分进行拷贝 ) 。
 
1.1 用 c 语言静态方式调用动态库 libsthc.so :
/*
  * ctest.c
  * Testing program for libsthc.so library
  * in c languange
  * by 玄机逸士
*/
#include "libsthc.h"
int main(void)
{
         printf("%d\n", add(1, 2));
         return 0;
}
 
#makefile:
ctest:ctest.o
         gcc ctest.o -lsthc -o ctest
ctest.o:ctest.c
         gcc -c ctest.c -o ctest.o
all:ctest
clean:
         rm -f *.o ctest
 
1.2 用 c 语言动态方式调用动态库 libsthc.so :
/*cdltest.c*/
#include "stdio.h"
#include "stdlib.h"
#include "dlfcn.h"
 
int main(void)
{
         void *handle;
         int (*fcn)(int x, int y);
         const char *errmsg;
        
         /* open the library */
         handle = dlopen("libsthc.so", RTLD_NOW);
         if(handle == NULL)
         {
                   fprintf(stderr, "Failed to load libsthc.so: %s\n", dlerror());
                   return 1;
         }
         dlerror();
 
         //*(void **)(&fcn) = dlsym(handle, "add");            //ok
         fcn = dlsym(handle, "add");                                   //ok
         if((errmsg = dlerror()) != NULL)
         {
                   printf("%s\n", errmsg);
                  return 1;
         }
         printf("%d\n", fcn(1, 5));
        
         dlclose(handle);
         return 0;
}
 
#makefile :
cdltest:cdltest.o
         gcc cdltest.o -ldl -lsthc -o cdltest
cdltest.o:cdltest.c
         gcc -c cdltest.c -o cdltest.o
all:cdltest
clean:
         rm -f *.o cdltest
 
1.3 用 c++ 静态方式调用动态库 libsthc.so :
/*cpptest.cc*/
#include "libsthc.h"
using namespace std;
int main(void)
{
         printf("%d\n", add(1, 2));
         return 0;
}
 
#makefile:
cpptest:cpptest.o
         g++ cpptest.o –o cpptest -lsthc
cpptest.o:cpptest.cc
         g++ -c cpptest.cc -Wno-deprecated -o cpptest.o
all:cpptest
clean:
         rm -f *.o cpptest
 
1.4 用 c++ 动态方式调用动态库 libsthc.so :
/*cppdltest.cpp*/
#include "stdio.h"
#include "stdlib.h"
#include "dlfcn.h"
 
int main(void)
{
         void *handle;
         int (*fcn)(int x, int y);
         const char *errmsg;
        
         /* open the library */
         handle = dlopen("libsthc.so", RTLD_NOW);
         if(handle == NULL)
         {
                   fprintf(stderr, "Failed to load libsthc.so: %s\n", dlerror());
                   return 1;
         }
         dlerror();
 
         *(void **)(&fcn) = dlsym(handle, "add");     //ok
         //fcn = dlsym(handle, "add");                        //not ok in c++
         if((errmsg = dlerror()) != NULL)
         {
                   printf("%s\n", errmsg);
                   return 1;
         }
         printf("%d\n", fcn(1, 5));
        
         dlclose(handle);
         return 0;
}
 
#makefile
cppdltest:cppdltest.o
         g++ cppdltest.o -ldl -lsthc -o cppdltest
cppdltest.o:cppdltest.cpp
         g++ -c cppdltest.cpp -o cppdltest.o
all:cppdltest
clean:
         rm -f *.o cppdltest
 
 
2. 用 c++ 语言写动态库:
/*
  * libsthcpp.h
  * Declarations for function cppadd
  */
#include "stdio.h"
#include "stdlib.h"
#include "stdarg.h"
#ifdef __cplusplus
extern "C"
{
#endif
 
int cppadd(int x, int y);
#ifdef __cplusplus
}
#endif
 
 
/*
  * libsthcpp.cpp
  * Implementation of function cppadd declared in libsthcpp.h
  * in c++ language
  */
#include "libsthcpp.h"
 
int cppadd(int x, int y)
{
         return x + y;
}
 
#makefile
libsthcpp.so:libsthcpp.o
         g++ -g -shared -Wl libsthcpp.o -lc -o libsthcpp.so
libsthcpp.o:libsthcpp.cc libsthcpp.h
         g++ -g -fPIC -c libsthcpp.cc -o libsthcpp.o
all:libsthcpp.so
clean:
         rm -f *.o *.so
 
make 完成后,会生成一个动态库,即 libsthcpp.so 。为了使其他程序也可以使用该动态库,需要将库文件 libsthcpp.so 拷贝到 /usr/lib 目录下 ( 由于权限的问题,一般要以 root 的身分进行拷贝 ) ,为了使其他程序也可以使用该动态库,需要将头文件 libsthcpp.h 拷贝到 /usr/include 目录下 ( 由于权限的问题 , 一般要以 root 的身分进行拷贝 ) 。
 
2.1 用 c 语言静态方式调用动态库 libsthcpp.so :
/*
  * ctest.c
  * Testing program for libsthcpp.so library
  * in c languange
  * by 玄机逸士
*/
#include "libsthcpp.h"
int main(void)
{
         printf("%d\n", cppadd(1, 2));
         return 0;
}
 
#makefile
ctest:ctest.o
         gcc ctest.o -lsthcpp -o ctest
ctest.o:ctest.c
         gcc -c ctest.c -o ctest.o
all:ctest
clean:
         rm -f *.o ctest
 
 
2.2 用 c 语言动态方式调用动态库 libsthcpp.so :
/*cdltest.c*/
#include "stdio.h"
#include "stdlib.h"
#include "dlfcn.h"
 
int main(void)
{
         void *handle;
         int (*fcn)(int x, int y);
         const char *errmsg;
        
         /* open the library */
         handle = dlopen("libsthcpp.so", RTLD_NOW);
         if(handle == NULL)
         {
                   fprintf(stderr, "Failed to load libsthc.so: %s\n", dlerror());
                   return 1;
         }
         dlerror();
 
         //*(void **)(&fcn) = dlsym(handle, "cppadd");       //ok in c and c++
         fcn = dlsym(handle, "cppadd");                               //ok in c, but not in c++
         if((errmsg = dlerror()) != NULL)
         {
                   printf("%s\n", errmsg);
                   return 1;
         }
         printf("%d\n", fcn(1, 5));
        
         dlclose(handle);
         return 0;
}
 
#makefile
cdltest:cdltest.o
         gcc cdltest.o -ldl -lsthcpp -o cdltest
cdltest.o:cdltest.c
         gcc -c cdltest.c -o cdltest.o
all:cdltest
clean:
         rm -f *.o cdltest
 
2.3 用 c++ 语言静态方式调用动态库 libsthcpp.so :
/*
  * cpptest.cpp
  * Testing program for libsthc.so library written in c language
  * in c++ languange
  * by 玄机逸士
*/
#include "libsthcpp.h"
#include "iostream.h"
int main(void)
{
         cout << cppadd(1, 2) << endl;
         return 0;
}
 
#makefile
cpptest:cpptest.o
         g++ cpptest.o -lsthcpp -o cpptest
cpptest.o:cpptest.cpp
         g++ -c cpptest.cpp -Wno-deprecated -o cpptest.o
all:cpptest
clean:
         rm -f *.o cpptest
 
2.4 用 c++ 语言动态方式调用动态库 libsthcpp.so :
/*cppdltest.cpp*/
#include "stdio.h"
#include "stdlib.h"
#include "dlfcn.h"
 
int main(void)
{
         void *handle;
         int (*fcn)(int x, int y);
         const char *errmsg;
        
         /* open the library */
         handle = dlopen("libsthcpp.so", RTLD_NOW);
         if(handle == NULL)
         {
                   fprintf(stderr, "Failed to load libsthc.so: %s\n", dlerror());
                   return 1;
         }
         dlerror();
 
         *(void **)(&fcn) = dlsym(handle, "cppadd");         //ok in c and c++
         //fcn = dlsym(handle, "cppadd");                             //ok in c, but not in c++
         if((errmsg = dlerror()) != NULL)
         {
                   printf("%s\n", errmsg);
                   return 1;
         }
         printf("%d\n", fcn(1, 5));
        
         dlclose(handle);
         return 0;
}
 
#makefile
cppdltest:cppdltest.o
         g++ cppdltest.o -ldl -lsthcpp -o cppdltest
cppdltest.o:cppdltest.cpp
         g++ -c cppdltest.cpp -o cppdltest.o
all:cppdltest
clean:
         rm -f *.o cppdltest
 
本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/pathuang68/archive/2009/06/16/4273904.aspx
 
补充:
 
显式调用动态库的要点:
 
显式调用的含义是代码出现库文件名,用户需要自己去打开和管理库文件。其要点为:

⑴把dlfcn.h系统头文件包含进来

⑵用dlopen函数打开库文件,并指定打开方式

dllope的的第一个参数为共享库的名称,将会在下面位置查找指定的共享库。

①环境变量LD_LIBRARY_PATH列出的用分号间隔的所有目录。

②文件/etc/ld.so.cache中找到的库的列表,由ldconfig命令刷新。

③目录usr/lib。

④目录/lib。

⑤当前目录。

第二个参数为打开共享库的方式。有两个取值

①RTLD_NOW:将共享库中的所有函数加载到内存

②RTLD_LAZY:会推后共享库中的函数的加载操作,直到调用dlsym()时方加载某函数

⑶用dlerror()函数测试是否打开成功,并进行错误处理;

⑷用dlsym获得函数地址,存放在一个函数指针中

⑸用获得的函数指针进行函数调用。

⑹程序结束时用dlclose关闭打开的动态库,防止资源泄露。

⑺用ldconfig工具把动态库的路径加到系统库列表中

你可能感兴趣的:(Linux动态库的编写与调用)