Newer
Older
#include <string>
#include <iostream>
/*
If the OS is Windows then LoadLibrary, GetProcAddress and FreeLibrary are used.
Some casting to HINSTANCE is required.
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>
//#include <strsafe.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
{
// Get a reference to the logger
Logger& DllOpen::log = Logger::get("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)
{
Russell Taylor
committed
std::string str = filePath + PATH_SEPERATOR + LIB_PREFIX + libName
+ LIB_POSTFIX;
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)
{
Russell Taylor
committed
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)
{
Russell Taylor
committed
//take a copy of the input string
std::string retVal = fileName;
if ((retVal.find(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
return "";
}
if (retVal.rfind(LIB_POSTFIX) == (retVal.size()-LIB_POSTFIX.size()))
{
//found
retVal = retVal.substr(0, retVal.size()-LIB_POSTFIX.size());
}
else
{
//postfix not found
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)
{
Russell Taylor
committed
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
void* handle = LoadLibrary(filePath.c_str());
if (!handle)
{
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 );
// Display the error message and exit the process
size_t n = lstrlen((LPCTSTR)lpMsgBuf) + 40;
lpDisplayBuf = (LPVOID)LocalAlloc(LMEM_ZEROINIT, n*sizeof(TCHAR));
// StringCchPrintf((LPTSTR)lpDisplayBuf,
// LocalSize(lpDisplayBuf) / sizeof(TCHAR),
// TEXT("failed with error %d: %s"),
// dw, lpMsgBuf);
_snprintf((char*)lpDisplayBuf, n, "failed with error %d: %s", dw, lpMsgBuf);
log.error()<<"Could not open library " << filePath << ": " << (LPCTSTR)lpDisplayBuf << std::endl;
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)
{
Russell Taylor
committed
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)
{
Russell Taylor
committed
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)
{
Russell Taylor
committed
void* handle = dlopen(filePath.c_str(), RTLD_NOW | RTLD_GLOBAL);
if (!handle)
{
log.error("Could not open library " + filePath + ": " + dlerror());
}
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)
{
// Commented out for now due to a potential bug in glibc
//dlclose(libName);
}
/* Adds a directory to the dll cearch path
**/
void DllOpen::addSearchDirectoryImpl(const std::string& dir)
{
(void) dir; //Avoid compiler warning
}
#endif /* _WIN32 */
} // namespace Kernel
} // namespace Mantid