#define PLDLOG(message, name, err) PLD_Private_Log(message, name, err)\r
#endif\r
\r
+// Private dlopen function has platform-specific behavior when name == NULL\r
+// * Windows: Return GetModuleHandleA(NULL)\r
+// * POSIX: Return RTLD_NEXT\r
+//\r
+// Private dlsym function has platform-specific behavior when handle == NULL\r
+// * Windows: Use GetModuleHandleA(NULL) instead\r
+// * POSIX: Use RTLD_NEXT instead\r
#ifdef _WIN32\r
\r
#include <windows.h>\r
+typedef FARPROC PLD_ProcAddress;\r
+typedef HMODULE PLD_LibHandle;\r
typedef DWORD PLD_ErrCode;\r
static void PLD_Private_Log(const char *, const char *, PLD_ErrCode);\r
\r
+static PLD_ErrCode PLD_Private_ErrCode(void)\r
+{\r
+ return GetLastError();\r
+}\r
+\r
static void PLD_Private_WriteString(const char *s)\r
{\r
DWORD dummy;\r
(va_list *)&arg);\r
}\r
\r
-static HMODULE PLD_Private_LoadLibrary_wrapper(LPCSTR lpLibFileName)\r
+static PLD_LibHandle PLD_Private_dlopen(const char *name)\r
{\r
- HMODULE hModule = GetModuleHandleA(lpLibFileName);\r
- if (hModule == NULL)\r
- hModule = LoadLibraryA(lpLibFileName);\r
- if (hModule == NULL)\r
- PLDLOG("Failed to load library!", lpLibFileName, GetLastError());\r
- return hModule;\r
+ PLD_LibHandle handle = GetModuleHandleA(name);\r
+ if (handle == NULL)\r
+ handle = LoadLibraryA(name);\r
+ return handle;\r
}\r
\r
-static FARPROC PLD_Private_GetProcAddress_wrapper(HMODULE hModule, LPCSTR lpProcName)\r
+static PLD_ProcAddress PLD_Private_dlsym(PLD_LibHandle handle, const char *name)\r
{\r
- FARPROC lpProc = GetProcAddress(hModule, lpProcName);\r
- if (lpProc == NULL)\r
- PLDLOG("Failed to load procedure!", lpProcName, GetLastError());\r
- return lpProc;\r
+ if (handle == NULL)\r
+ handle = GetModuleHandleA(NULL);\r
+ return GetProcAddress(handle, name);\r
}\r
\r
-#define PLD(name) \\r
- static HMODULE PLDH(void) { \\r
- static HMODULE hModule = NULL; \\r
- if (hModule == NULL) hModule = PLD_Private_LoadLibrary_wrapper(name); \\r
- return hModule; \\r
- } \\r
-\r
-#define PFN(name) ((PLDTYPEOF(&name))PLD_Private_GetProcAddress_wrapper(PLDH(), #name))\r
-\r
#else\r
\r
#define _GNU_SOURCE\r
#include <string.h>\r
#include <dlfcn.h>\r
\r
+typedef void *PLD_ProcAddress;\r
+typedef void *PLD_LibHandle;\r
typedef intptr_t PLD_ErrCode;\r
static void PLD_Private_Log(const char *, const char *, PLD_ErrCode);\r
\r
+static PLD_ErrCode PLD_Private_ErrCode(void)\r
+{\r
+ return (intptr_t)dlerror();\r
+}\r
+\r
static void PLD_Private_WriteString(const char *s)\r
{\r
write(2, s, PLD_Private_strlen(s));\r
strncat(s, (const char *)code, len);\r
}\r
\r
-static void *PLD_Private_dlopen_wrapper(const char *name)\r
+static PLD_LibHandle PLD_Private_dlopen(const char *name)\r
{\r
if (name == NULL)\r
- return (void *)RTLD_NEXT;\r
+ return (PLD_LibHandle)RTLD_NEXT;\r
void *handle = dlopen(name, RTLD_NOLOAD);\r
if (handle == NULL)\r
handle = dlopen(name, RTLD_LAZY);\r
- if (handle == NULL)\r
- PLDLOG("Failed to load library!", name, (intptr_t)dlerror());\r
return handle;\r
}\r
\r
-static void *PLD_Private_dlsym_wrapper(void *handle, const char *name)\r
+static PLD_ProcAddress PLD_Private_dlsym(PLD_LibHandle handle, const char *name)\r
{\r
- void *sym = dlsym(handle, name);\r
+ if (handle == NULL)\r
+ handle = (PLD_LibHandle)RTLD_NEXT;\r
+ return dlsym(handle, name);\r
+}\r
+\r
+\r
+#endif\r
+\r
+static PLD_ProcAddress PLD_Private_dlsym_wrapper(PLD_LibHandle handle, const char *name)\r
+{\r
+ if (name == NULL) {\r
+ PLDLOG("NULL name provided for procedure!", "???", 0);\r
+ return NULL;\r
+ }\r
+ if (handle == NULL)\r
+ handle = PLD_Private_dlopen(NULL);\r
+ PLD_ProcAddress sym = PLD_Private_dlsym(handle, name);\r
if (sym == NULL)\r
- PLDLOG("Failed to load procedure!", name, (intptr_t)dlerror());\r
+ PLDLOG("Failed to load procedure!", name, PLD_Private_ErrCode());\r
return sym;\r
}\r
\r
+static PLD_LibHandle PLD_Private_dlopen_wrapper(const char *name)\r
+{\r
+ // On Linux, RTLD_NEXT is NULL, so check if the\r
+ // name is NULL before concluding it's an error\r
+ PLD_LibHandle handle = PLD_Private_dlopen(name);\r
+ if (handle == NULL && name != NULL)\r
+ PLDLOG("Failed to load library!", name, PLD_Private_ErrCode());\r
+ return handle;\r
+}\r
+\r
+\r
#define PLD(name) \\r
- static void *PLDH(void) { \\r
- static void *handle = NULL; \\r
+ PLD_LibHandle PLDH(void) { \\r
+ static PLD_LibHandle handle = NULL; \\r
if (handle == NULL) handle = PLD_Private_dlopen_wrapper(name); \\r
return handle; \\r
} \\r
\r
-#define PFN(name) ((PLDTYPEOF(&name))PLD_Private_dlsym_wrapper(PLDH(), #name))\r
+// For importing by ordinal on Windows or just using\r
+// another name in a library for whatever reason\r
+#define PFNALT(name, alt) ((PLDTYPEOF(&name))PLD_Private_dlsym_wrapper(PLDH(), alt))\r
+#define PFN(name) PFNALT(name, #name)\r
\r
+// When code is 0, output nothing\r
+static void PLD_Private_FormatError_wrapper(intptr_t code, char *s, int len) {\r
+ // Add an extra newline only on Windows to mimic FormatMessageA\r
+ if (code == 0) {\r
+#ifdef _WIN32\r
+ s[0] = '\r';\r
+ s[1] = '\n';\r
+ s[2] = 0;\r
+#else\r
+ *s = 0;\r
#endif\r
+ return;\r
+ }\r
+ PLD_Private_FormatError(code, s, len);\r
+}\r
+\r
\r
static void PLD_Private_Log(const char *message, const char *name, PLD_ErrCode err)\r
{\r
PLD_Private_WriteString("\n");\r
#endif\r
char errtext[256];\r
- PLD_Private_FormatError(err, errtext, sizeof(errtext));\r
+ PLD_Private_FormatError_wrapper(err, errtext, sizeof(errtext));\r
PLD_Private_WriteString(errtext);\r
\r
// An extra newline because dlerror doesn't append one\r