// NeL - MMORPG Framework // Copyright (C) 2010 Winch Gate Property Limited // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License as // published by the Free Software Foundation, either version 3 of the // License, or (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU Affero General Public License for more details. // // You should have received a copy of the GNU Affero General Public License // along with this program. If not, see . #include "stdmisc.h" #include "nel/misc/dynloadlib.h" #include "nel/misc/path.h" using namespace std; #ifdef DEBUG_NEW #define new DEBUG_NEW #endif namespace NLMISC { NL_LIB_HANDLE nlLoadLibrary(const std::string &libName) { NL_LIB_HANDLE res = 0; #ifdef NL_OS_WINDOWS res = LoadLibrary(libName.c_str()); #elif defined(NL_OS_UNIX) res = dlopen(libName.c_str(), RTLD_NOW); #else # error "You must code nlLoadLibrary() for your platform" #endif if(res == 0) nlwarning("Load library '%s' failed: %s", libName.c_str(), NLMISC::formatErrorMessage(NLMISC::getLastError()).c_str()); return res; } bool nlFreeLibrary(NL_LIB_HANDLE libHandle) { #ifdef NL_OS_WINDOWS return FreeLibrary(libHandle) > 0; #elif defined(NL_OS_UNIX) return dlclose(libHandle) == 0; #else # error "You must code nlFreeLibrary() for your platform" #endif } void *nlGetSymbolAddress(NL_LIB_HANDLE libHandle, const std::string &procName) { void *res = 0; #ifdef NL_OS_WINDOWS res = (void *)GetProcAddress(libHandle, procName.c_str()); #elif defined(NL_OS_UNIX) res = dlsym(libHandle, procName.c_str()); #else # error "You must code nlGetProcAddress() for your platform" #endif if(res == 0) nlwarning("Getting symbol address of '%s' failed: %s", procName.c_str(), NLMISC::formatErrorMessage(NLMISC::getLastError()).c_str()); return res; } // Again some OS specifics stuff #ifdef NL_OS_WINDOWS const string nlLibPrefix; // empty const string nlLibExt(".dll"); #elif defined(NL_OS_MAC) const string nlLibPrefix("lib"); const string nlLibExt(".dylib"); #elif defined(NL_OS_UNIX) const string nlLibPrefix("lib"); const string nlLibExt(".so"); #else # error "You must define the default dynamic lib extention" #endif std::vector CLibrary::_LibPaths; CLibrary::CLibrary (const CLibrary &/* other */) { // Nothing to do has it is forbidden. // Allowing copy require to manage reference count from CLibrary to the module resource. nlassert(false); } CLibrary &CLibrary::operator =(const CLibrary &/* other */) { // Nothing to do has it is forbidden. // Allowing assignment require to manage reference count from CLibrary to the module resource. nlassert(false); return *this; } std::string CLibrary::makeLibName(const std::string &baseName) { return nlLibPrefix+baseName+nlLibSuffix+nlLibExt; } std::string CLibrary::cleanLibName(const std::string &decoratedName) { // remove path and extension string ret = CFile::getFilenameWithoutExtension(decoratedName); if (!nlLibPrefix.empty()) { // remove prefix if (ret.find(nlLibPrefix) == 0) ret = ret.substr(nlLibPrefix.size()); } if (!nlLibSuffix.empty()) { // remove suffix if (ret.substr(ret.size()-nlLibSuffix.size()) == nlLibSuffix) ret = ret.substr(0, ret.size() - nlLibSuffix.size()); } return ret; } void CLibrary::addLibPaths(const std::vector &paths) { for (uint i=0; i(entryPoint)); // call the private initialization method. _PureNelLibrary->_onLibraryLoaded(INelContext::getInstance()); } } return _LibHandle != NULL; } void CLibrary::freeLibrary() { if (_LibHandle) { nlassert(_Ownership); if (_PureNelLibrary) { // call the private finalization method. _PureNelLibrary->_onLibraryUnloaded(); } nldebug("Freeing dynamic library '%s'", _LibFileName.c_str()); nlFreeLibrary(_LibHandle); _PureNelLibrary = NULL; _LibHandle = NULL; _Ownership = false; _LibFileName = ""; } } void *CLibrary::getSymbolAddress(const std::string &symbolName) { nlassert(_LibHandle != NULL); return nlGetSymbolAddress(_LibHandle, symbolName); } bool CLibrary::isLibraryLoaded() { return _LibHandle != NULL; } bool CLibrary::isLibraryPure() { return _LibHandle != NULL && _PureNelLibrary != NULL; } INelLibrary *CLibrary::getNelLibraryInterface() { if (!isLibraryPure()) return NULL; return _PureNelLibrary; } INelLibrary::~INelLibrary() { // cleanup ram if (_LibContext != NULL) delete _LibContext; } void INelLibrary::_onLibraryLoaded(INelContext &nelContext) { ++_LoadingCounter; if (_LoadingCounter == 1) { // Linux relocates all symbols, so this is unnecessary. #ifdef NL_OS_WINDOWS // initialize NeL context nlassert(!NLMISC::INelContext::isContextInitialised()); #endif // NL_OS_WINDOWS _LibContext = new CLibraryContext(nelContext); } else { nlassert(NLMISC::INelContext::isContextInitialised()); } onLibraryLoaded(_LoadingCounter==1); } void INelLibrary::_onLibraryUnloaded() { nlassert(_LoadingCounter > 0); onLibraryUnloaded(_LoadingCounter == 1); --_LoadingCounter; } uint32 INelLibrary::getLoadingCounter() { return _LoadingCounter; } } // namespace NLMISC