C++ linux动态库so导出及使用


第一次尝试导出linux动态库,遇到的问题做个记录。

log4cpp linux下编译安装

在官网上下下来包过后,官网的安装说明不全:

  • ./autogen.sh
  • ./configure
  • make
  • make check
  • sudo make install

使用宏定义进行区分windows & linux

// stdcall & cdecl
#if defined(_MSC_VER) || defined(_WIN32) || defined(_WIN64)
#define TCE_API __stdcall
// TCELOGGER_DLL_EXPORTS
#ifdef TCELOGGER_DLL_EXPORTS
#define DLL_API __declspec(dllexport)
#else
#define DLL_API __declspec(dllimport)
#endif
#else
#define TCE_API
#define DLL_API
#endif

存在不兼容的函数

sprint_s snprintf

发现有的函数是windows平台的。sprint_s是windows平台下线程安全的格式化字符串函数并非标准C函数,因此linux下无法使用,但可以使用snprintf函数代替。

int snprintf(char *dest, size_t n, const char *fmt, ...); 
// 函数原型相同,替换即可
#define sprintf_s snprintf

控制linux动态库的导出函数

windows下通过__declspec(dllexport)来声明DLL动态库导出的接口(函数或类),__declspec(dllimport)来声明为动态库加载的接口。linux下不可用。
linux下,GCC帮助文档 -fvisibility=default|internal|hidden|protected 参数下有这么一段话:

  • a superior solution made possible by this option to marking things hidden when the default is public is to make the default hidden and mark things public. This is the norm with DLL’s on Windows and with -fvisibility=hidden and “attribute ((visibility(“default”)))” instead of “__declspec(dllexport)” you get almost identical semantics with identical syntax. This is a great boon to those working with cross-platform projects.

总结是:

  1. linux下源文件中的所有函数都有一个默认的visibility属性,默认为public,即默认导出。如果要隐藏,则在GCC编译指令中加入 -fvisibility=hidden 参数,会将默认的public属性变为hidden。
  2. 隐藏函数导出后,所有的导出都隐藏,再在源码中,在需要导出的函数前添加 __attribute__ ((visibility(“default”))) ,使其仍按默认的public属性处理。

查看文件属性:

  • readelf -s *.so

查看导出函数:

  • nm -D *.so
  • objdump -tT *.so

使用linux动态库

Linux提供4个库函数、一个头文件dlfcn.h以及两个共享库(静态库libdl.a和动态库libdl.so)支持动态链接。

  • dlopen:打开动态共享目标文件并将其映射到内存中,返回其首地址
  • dlsym:返回锁请求的入口点的指针
  • dlerror:返回NULL或者指向描述最近错误的字符串
  • dlclose:关闭动态共享文件

猜你喜欢

转载自blog.csdn.net/fantasysolo/article/details/88995895