Newer
Older
If the OS is Windows then LoadLibrary, GetProcAddress and FreeLibrary are used.
Shared library name is of the form *.dll.
If the OS is Linux then dlopen, dlsym and dlclose are used.
Shared library name is of the form lib*.so.
*/
#if _WIN32
Roman Tolchenov
committed
#define _WIN32_WINNT 0x0510
#include <windows.h>
#else
#include <dlfcn.h>
#endif /* _WIN32 */
Janik Zikovsky
committed
#include "MantidKernel/Strings.h"
#include "MantidKernel/DllOpen.h"
#include "MantidKernel/Logger.h"
namespace Mantid {
namespace Kernel {
namespace {
// Static logger object
Logger g_log("DllOpen");
}
/* Opens the shared library after appending the required formatting,
* i.e. libName.so for Linux and Name.dll for Windows.
* Calls the correct implementation based on the current O/S.
Janik Zikovsky
committed
* @param libName :: Name of the library.
* @return Pointer to library (of type void).
void *DllOpen::OpenDll(const std::string &libName) {
Russell Taylor
committed
std::string str = LIB_PREFIX + libName + LIB_POSTFIX;
return OpenDllImpl(str);
}
/* Opens the shared library after appending the required formatting,
* i.e. libName.so for Linux and Name.dll for Windows.
* Calls the correct implementation based on the current O/S.
Janik Zikovsky
committed
* @param libName :: Name of the library.
* @param filePath :: The location on the library.
* @return Pointer to library (of type void).
void *DllOpen::OpenDll(const std::string &libName,
const std::string &filePath) {
std::string str =
filePath + PATH_SEPERATOR + LIB_PREFIX + libName + LIB_POSTFIX;
Russell Taylor
committed
return OpenDllImpl(str);
}
/* Retrieves a function from the opened library.
* Calls the correct implementation based on the current O/S.
Janik Zikovsky
committed
* @param libName :: Name of the library.
* @param funcName :: The name of the function to retrieve.
* @return Pointer to the function (of type void).
void *DllOpen::GetFunction(void *libName, const std::string &funcName) {
Russell Taylor
committed
return GetFunctionImpl(libName, funcName);
}
/* Closes an open library.
* Calls the correct implementation based on the current O/S.
Janik Zikovsky
committed
* @param libName :: Name of the library.
void DllOpen::CloseDll(void *libName) { CloseDllImpl(libName); }
/** Converts a file name (without directory) to a undecorated library name.
* e.g. MyLibrary.dll or libMyLibary.so would become MyLibrary.
Janik Zikovsky
committed
* @param fileName :: The filename (with extension) to convert
* @return The converted libName, or empty string if the conversion was not
*possible.
const std::string DllOpen::ConvertToLibName(const std::string &fileName) {
// take a copy of the input string
Russell Taylor
committed
std::string retVal = fileName;
if ((retVal.compare(0, LIB_PREFIX.size(), LIB_PREFIX) == 0) &&
(retVal.find(PATH_SEPERATOR) == std::string::npos)) {
// found
retVal =
retVal.substr(LIB_PREFIX.size(), retVal.size() - LIB_PREFIX.size());
} else {
// prefix not found
Russell Taylor
committed
return "";
}
Gigg, Martyn Anthony
committed
std::string::size_type pos = retVal.rfind(LIB_POSTFIX);
if (pos != std::string::npos && pos == (retVal.size() - LIB_POSTFIX.size())) {
// found
retVal = retVal.substr(0, retVal.size() - LIB_POSTFIX.size());
} else {
// postfix not found
Russell Taylor
committed
return "";
}
return retVal;
}
/* Adds a directory to the dll cearch path
**/
void DllOpen::addSearchDirectory(const std::string &dir) {
Russell Taylor
committed
addSearchDirectoryImpl(dir);
}
#if _WIN32
const std::string DllOpen::LIB_PREFIX = "";
const std::string DllOpen::LIB_POSTFIX = ".dll";
const std::string DllOpen::PATH_SEPERATOR = "\\";
/* Opens the Windows .dll file.
Janik Zikovsky
committed
* @param filePath :: Filepath of the library.
* @return Pointer to library (of type void).
void *DllOpen::OpenDllImpl(const std::string &filePath) {
void *handle = LoadLibrary(filePath.c_str());
if (!handle) {
Russell Taylor
committed
LPVOID lpMsgBuf;
LPVOID lpDisplayBuf;
DWORD dw = GetLastError();
FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM |
FORMAT_MESSAGE_IGNORE_INSERTS,
NULL, dw, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
(LPTSTR)&lpMsgBuf, 0, NULL);
Russell Taylor
committed
// Display the error message and exit the process
size_t n = lstrlen((LPCTSTR)lpMsgBuf) + 40;
lpDisplayBuf = (LPVOID)LocalAlloc(LMEM_ZEROINIT, n * sizeof(TCHAR));
_snprintf((char *)lpDisplayBuf, n, "failed with error %lu: %s", dw,
g_log.error() << "Could not open library " << filePath << ": "
<< (LPCTSTR)lpDisplayBuf << std::endl;
Russell Taylor
committed
LocalFree(lpMsgBuf);
LocalFree(lpDisplayBuf);
}
return handle;
}
/* Retrieves a function from the opened .dll file.
* Only works if the function has been declared as extern 'C'.
Janik Zikovsky
committed
* @param libName :: Name of the library.
* @param funcName :: The name of the function to retrieve.
* @return Pointer to the function (of type void).
void *DllOpen::GetFunctionImpl(void *libName, const std::string &funcName) {
return (void *)GetProcAddress((HINSTANCE)libName, funcName.c_str());
}
/* Closes an open .dll file.
Janik Zikovsky
committed
* @param libName :: Name of the library.
void DllOpen::CloseDllImpl(void *libName) { FreeLibrary((HINSTANCE)libName); }
/* Adds a directory to the dll cearch path
**/
void DllOpen::addSearchDirectoryImpl(const std::string &dir) {
Russell Taylor
committed
SetDllDirectory(dir.c_str());
}
#else
const std::string DllOpen::LIB_PREFIX = "lib";
// Shared libraries end in "so" on linux, "dylib" on the Mac
#ifdef __linux__
const std::string DllOpen::LIB_POSTFIX = ".so";
#elif defined __APPLE__
const std::string DllOpen::LIB_POSTFIX = ".dylib";
#endif
const std::string DllOpen::PATH_SEPERATOR = "/";
/* Opens the Linux .so file
Janik Zikovsky
committed
* @param filePath :: Filepath of the library.
* @return Pointer to library (of type void).
void *DllOpen::OpenDllImpl(const std::string &filePath) {
void *handle = dlopen(filePath.c_str(), RTLD_NOW | RTLD_GLOBAL);
if (!handle) {
g_log.error("Could not open library " + filePath + ": " + dlerror());
Russell Taylor
committed
}
return handle;
}
/* Retrieves a function from the opened library.
* Only works if the function has been declared as extern 'C'.
Janik Zikovsky
committed
* @param libName :: Name of the library.
* @param funcName :: The name of the function to retrieve.
* @return Pointer to the function (of type void).
void *DllOpen::GetFunctionImpl(void *libName, const std::string &funcName) {
Russell Taylor
committed
return dlsym(libName, funcName.c_str());
}
/* Closes an open .so file.
Janik Zikovsky
committed
* @param libName :: Name of the library.
void DllOpen::CloseDllImpl(void *libName) {
Gigg, Martyn Anthony
committed
UNUSED_ARG(libName);
// Commented out for now due to a potential bug in glibc
}
/* Adds a directory to the dll cearch path
**/
void DllOpen::addSearchDirectoryImpl(const std::string &dir) {
Gigg, Martyn Anthony
committed
UNUSED_ARG(dir);
}
#endif /* _WIN32 */
} // namespace Kernel
} // namespace Mantid