- Timestamp:
- 06/20/11 22:06:51 (14 years ago)
- Location:
- ps/trunk/source
- Files:
-
- 3 edited
-
lib/sysdep/os/win/wposix/wdlfcn.cpp (modified) (1 diff)
-
ps/DllLoader.cpp (modified) (8 diffs)
-
ps/DllLoader.h (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
-
ps/trunk/source/lib/sysdep/os/win/wposix/wdlfcn.cpp
r9410 r9642 47 47 char* dlerror() 48 48 { 49 return 0; 49 // the obvious implementation involves sys_StatusDescription, but we 50 // don't want to return a pointer to a static array because that's not 51 // thread-safe. we therefore check GetLastError directly. 52 switch(GetLastError()) 53 { 54 case ERROR_MOD_NOT_FOUND: 55 return "module not found"; 56 case ERROR_PROC_NOT_FOUND: 57 return "symbol not found"; 58 default: 59 return "unknown"; 60 } 50 61 } 51 62 -
ps/trunk/source/ps/DllLoader.cpp
r8929 r9642 1 /* Copyright (C) 201 0Wildfire Games.1 /* Copyright (C) 2011 Wildfire Games. 2 2 * This file is part of 0 A.D. 3 3 * … … 26 26 #include "ps/GameSetup/Config.h" 27 27 28 void* const HANDLE_UNAVAILABLE = (void*)-1;28 static void* const HANDLE_UNAVAILABLE = (void*)-1; 29 29 30 30 // directory to search for libraries (optionally set by --libdir at build-time, … … 40 40 // note: on Linux, lib is prepended to the SO file name 41 41 #if OS_UNIX 42 static const char*prefix = "lib";42 static CStr prefix = "lib"; 43 43 #else 44 static const char*prefix = "";44 static CStr prefix = ""; 45 45 #endif 46 // our SOs export binary-compatible interfaces across debug and release builds, 47 // but for debugging/performance we prefer to use the same version as the app. 48 // note: on Windows, the extension is replaced with .dll by dlopen. 46 47 // we usually want to use the same debug/release build type as the 48 // main executable (the library should also be efficient in release builds and 49 // allow easy symbol access in debug builds). however, that version of the 50 // library might be missing, so we check for both. 51 // this works because the interface is binary-compatible. 49 52 #ifndef NDEBUG 50 static const char* primarySuffix = "_dbg.so"; 51 static const char* secondarySuffix = ".so"; 53 static CStr suffixes[] = { "_dbg", "" }; // (order matters) 52 54 #else 53 static const char* primarySuffix = ".so"; 54 static const char* secondarySuffix = "_dbg.so"; 55 static CStr suffixes[] = { "", "_dbg" }; 55 56 #endif 57 58 // NB: our Windows dlopen() function changes the extension to .dll 59 static CStr extensions[] = { 60 ".so", 61 #if OS_MACOSX 62 ".dylib" // supported by OS X dlopen 63 #endif 64 }; 56 65 57 66 // (This class is currently only used by 'Collada' and 'AtlasUI' which follow … … 59 68 // to support other DLLs.) 60 69 61 static CStr GenerateFilename(const CStr& name, const CStr& suffix )70 static CStr GenerateFilename(const CStr& name, const CStr& suffix, const CStr& extension) 62 71 { 63 72 CStr n; 64 73 if (!g_Libdir.empty()) 65 74 n = g_Libdir + "/"; 66 n += prefix + name + suffix ;75 n += prefix + name + suffix + extension; 67 76 return n; 68 77 } 69 78 79 80 81 // @param name base name of the library (excluding prefix/suffix/extension) 82 // @param errors receives descriptions of any and all errors encountered 83 // @return valid handle or 0 84 static void* LoadAnyVariant(const CStr& name, std::stringstream& errors) 85 { 86 for(size_t idxSuffix = 0; idxSuffix < ARRAY_SIZE(suffixes); idxSuffix++) 87 { 88 for(size_t idxExtension = 0; idxExtension < ARRAY_SIZE(extensions); idxExtension++) 89 { 90 CStr filename = GenerateFilename(name, suffixes[idxSuffix], extensions[idxExtension]); 91 92 // we don't really care when relocations take place, but one of 93 // {RTLD_NOW, RTLD_LAZY} must be specified. go with the former because 94 // it is safer and matches the Windows load behavior. 95 const int flags = RTLD_LOCAL|RTLD_NOW; 96 void* handle = dlopen(filename.c_str(), flags); 97 if(handle) 98 return handle; 99 else 100 errors << "dlopen(" << filename << ") failed: " << dlerror() << "; "; 101 } 102 } 103 104 return 0; // none worked 105 } 106 107 70 108 DllLoader::DllLoader(const char* name) 71 : m_Name(name), m_Handle(0)109 : m_Name(name), m_Handle(0) 72 110 { 73 111 } … … 92 130 TIMER(L"LoadDLL"); 93 131 94 // we don't really care when relocations take place, but one of 95 // {RTLD_NOW, RTLD_LAZY} must be passed. go with the former because 96 // it is safer and matches the Windows load behavior. 97 const int flags = RTLD_LOCAL|RTLD_NOW; 98 99 CStr filename = GenerateFilename(m_Name, primarySuffix); 100 m_Handle = dlopen(filename.c_str(), flags); 101 102 char* primaryError = NULL; 103 104 // open failed (mostly likely SO not found) 105 if (! m_Handle) 132 std::stringstream errors; 133 m_Handle = LoadAnyVariant(m_Name, errors); 134 if(!m_Handle) // (only report errors if nothing worked) 106 135 { 107 primaryError = dlerror(); 108 if (primaryError) 109 primaryError = strdup(primaryError); // don't get overwritten by next dlopen 110 111 // Try to open the other debug/release version 112 filename = GenerateFilename(m_Name, secondarySuffix); 113 m_Handle = dlopen(filename.c_str(), flags); 114 } 115 116 // open still failed; report the first error 117 if (! m_Handle) 118 { 119 if (primaryError) 120 LOGERROR(L"dlopen error: %hs", primaryError); 136 LOGERROR(L"DllLoader: %hs", errors.str().c_str()); 121 137 m_Handle = HANDLE_UNAVAILABLE; 122 138 } 123 124 free(primaryError);125 139 } 126 140 … … 130 144 void DllLoader::Unload() 131 145 { 132 if (!IsLoaded())146 if(!IsLoaded()) 133 147 return; 134 148 … … 139 153 void DllLoader::LoadSymbolInternal(const char* name, void** fptr) const 140 154 { 141 if (!IsLoaded())155 if(!IsLoaded()) 142 156 { 143 157 debug_warn(L"Loading symbol from invalid DLL"); … … 147 161 148 162 *fptr = dlsym(m_Handle, name); 149 150 if (*fptr == NULL) 163 if(*fptr == NULL) 151 164 throw PSERROR_DllLoader_SymbolNotFound(); 152 165 } -
ps/trunk/source/ps/DllLoader.h
r7824 r9642 1 /* Copyright (C) 20 09Wildfire Games.1 /* Copyright (C) 2011 Wildfire Games. 2 2 * This file is part of 0 A.D. 3 3 *
Note:
See TracChangeset
for help on using the changeset viewer.
