核心思路是在 winds 上面采用最小的代价构建了一个 linux dlopen 操作三部曲.
实现的很一般般. 或者说不痛快, 胜在可用, 代价小. 推荐喜欢但基础一般的朋友可以练习练习多写写.
人生的修行, 那么让人不可捉摸. 心无旁贷, 好想有机会再能看看大山中柿子树. 甜甜涩涩的 ~
很幸运你读到这里. 不妨带大家看看 libuv 怎么封装 dll 的. 总的思路都一样, winds 向着 *nix 靠拢. 写的很平稳厚实.
/* 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 中的
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->