设为首页 加入收藏

TOP

linux动态库编译和使用详细剖析 - 后续(二)
2018-10-21 16:09:50 】 浏览:124
Tags:linux 动态 编译 使用 详细 剖析 后续
// // ds_parse - 解析动态库文件, 返回执行函数 // so : 动态库对象 // name : 待解析的函数名称 // return : 返回解析的函数地址, NULL 是失败 // inline void * ds_parse(void * so, const char * name) { return dlsym(so, name); } // // ds_delete - 释放卸载动态库文件 // so : 动态库对象 // return : void // inline void ds_delete(void * so) { if (so) { dlclose(so); } }

核心思路是在 winds 上面采用最小的代价构建了一个 linux dlopen 操作三部曲.

实现的很一般般. 或者说不痛快, 胜在可用, 代价小.  推荐喜欢但基础一般的朋友可以练习练习多写写.

文章到这里也快尾声了, 算 Over ~

 

正文 - 原地踌躇, 也走到了 中年

  人生的修行, 那么让人不可捉摸. 心无旁贷, 好想有机会再能看看大山中柿子树. 甜甜涩涩的 ~

很幸运你读到这里. 不妨带大家看看 libuv 怎么封装 dll 的. 总的思路都一样, winds 向着 *nix 靠拢. 写的很平稳厚实.

先看基础部分 (dl.c, uv.h, internal.h)

/* Platform-specific definitions for uv_dlopen support. */
#define UV_DYNAMIC FAR WINAPI
typedef struct {
  HMODULE handle;
  char* errmsg;
} uv_lib_t;

static void uv__format_fallback_error(uv_lib_t* lib, int errorno){ DWORD_PTR args[1] = { (DWORD_PTR) errorno }; LPSTR fallback_error = "error: %1!d!"; FormatMessageA(FORMAT_MESSAGE_FROM_STRING | FORMAT_MESSAGE_ARGUMENT_ARRAY | FORMAT_MESSAGE_ALLOCATE_BUFFER, fallback_error, 0, 0, (LPSTR) &lib->errmsg, 0, (va_list*) args); }
static int uv__dlerror(uv_lib_t* lib, const char* filename, DWORD errorno) { DWORD_PTR arg; DWORD res; char* msg; if (lib->errmsg) { LocalFree(lib->errmsg); lib->errmsg = NULL; } if (errorno == 0) return 0; res = FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, errorno, MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), (LPSTR) &lib->errmsg, 0, NULL); if (!res && GetLastError() == ERROR_MUI_FILE_NOT_FOUND) { res = FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, errorno, 0, (LPSTR) &lib->errmsg, 0, NULL); } if (res && errorno == ERROR_BAD_EXE_FORMAT && strstr(lib->errmsg, "%1")) { msg = lib->errmsg; lib->errmsg = NULL; arg = (DWORD_PTR) filename; res = FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_ARGUMENT_ARRAY | FORMAT_MESSAGE_FROM_STRING, msg, 0, 0, (LPSTR) &lib->errmsg, 0, (va_list*) &arg); LocalFree(msg); } if (!res) uv__format_fallback_error(lib, errorno); return -1; }

uv__dlerror 是构造 linux dlerror 前戏.
作者设计的意图是围绕 winds FormatMessageA api 错误处理用法包装.

写的挺漂亮的. 其实还有更好更偷懒的实现方式, 参照基础项目 structc 中的

  stderr https://github.com/wangzhione/structc/blob/master/structc/system/stderr.c

winds 实现 strerror 函数. 用于解决 GetLastError 和 FormatMessage 配合的不爽. 

libuv 写的真好, 不知道 niginx 源码是什么水平, 有机会研究一下.一块分享.

 

随后的代码很轻松和标准

int uv_dlopen(const char* filename, uv_lib_t* lib) {
  WCHAR filename_w[32768];

  lib->handle = NULL;
  lib->errmsg = NULL;

  if (!MultiByteToWideChar(CP_UTF8,
                           0,
                           filename,
                           -1,
                           filename_w,
                           ARRAY_SIZE(filename_w))) {
    return uv__dlerror(lib, filename, GetLastError());
  }

  lib->handle = LoadLibraryExW(filename_w, NULL, LOAD_WITH_ALTERED_SEARCH_PATH);
  if (lib->handle == NULL) {
    return uv__dlerror(lib, filename, GetLastError());
  }

  return 0;
}


void uv_dlclose(uv_lib_t* lib) {
  if (lib->errmsg) {
    LocalFree((void*)lib->errmsg);
    lib->errmsg = NULL;
  }

  if (lib->
首页 上一页 1 2 3 下一页 尾页 2/3/3
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
上一篇第二章、线性表 下一篇二维数组

最新文章

热门文章

Hot 文章

Python

C 语言

C++基础

大数据基础

linux编程基础

C/C++面试题目