forked from micro-manager/micro-manager
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Factor out loadable module handling from PluginManager.
Behavior is mostly unchanged, with one major exception: when a module is requested, the previously loaded version (if any) is always used, instead of searching the paths anew. This prevents different files from being loaded for the same module name (unless the module is first unloaded) in the case where the search paths or the files within them have changed. (It probably also speeds up device loading.) git-svn-id: https://valelab.ucsf.edu/svn/micromanager2/trunk@12462 d0ab736e-dc22-4aeb-8dc9-08def0aa14fd
- Loading branch information
mark
committed
Dec 24, 2013
1 parent
f68d749
commit 73efc9b
Showing
18 changed files
with
436 additions
and
202 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
#include "LoadedModule.h" | ||
|
||
#include "LoadedModuleImpl.h" | ||
#include "../CoreUtils.h" | ||
#include "../Error.h" | ||
|
||
|
||
LoadedModule::LoadedModule(const std::string& filename) : | ||
filename_(filename) | ||
{ | ||
try | ||
{ | ||
pImpl_ = LoadedModuleImpl::NewPlatformImpl(filename_); | ||
} | ||
catch (const CMMError& e) | ||
{ | ||
throw CMMError("Failed to load module " + ToQuotedString(filename_), e); | ||
} | ||
} | ||
|
||
|
||
LoadedModule::~LoadedModule() | ||
{ | ||
delete pImpl_; | ||
} | ||
|
||
|
||
void | ||
LoadedModule::Unload() | ||
{ | ||
try | ||
{ | ||
pImpl_->Unload(); | ||
} | ||
catch (const CMMError& e) | ||
{ | ||
throw CMMError("Cannot unload module " + ToQuotedString(filename_), e); | ||
} | ||
} | ||
|
||
|
||
void* | ||
LoadedModule::GetFunction(const char* funcName) | ||
{ | ||
try | ||
{ | ||
return pImpl_->GetFunction(funcName); | ||
} | ||
catch (const CMMError& e) | ||
{ | ||
throw CMMError("Cannot find function " + ToString(funcName) + "() in module " + | ||
ToQuotedString(filename_), e); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
#pragma once | ||
|
||
#include <boost/shared_ptr.hpp> | ||
#include <boost/utility.hpp> | ||
|
||
|
||
class LoadedModuleImpl; | ||
|
||
class LoadedModule /* final */ : boost::noncopyable | ||
{ | ||
public: | ||
explicit LoadedModule(const std::string& filename); | ||
~LoadedModule(); | ||
|
||
void Unload(); // For developer use only | ||
void* GetFunction(const char* funcName); | ||
|
||
private: | ||
LoadedModuleImpl* pImpl_; | ||
const std::string filename_; | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
#include "LoadedModuleImpl.h" | ||
|
||
#ifdef WIN32 | ||
# include "LoadedModuleImplWindows.h" | ||
typedef LoadedModuleImplWindows PlatformLoadedModuleImpl; | ||
#else | ||
# include "LoadedModuleImplUnix.h" | ||
typedef LoadedModuleImplUnix PlatformLoadedModuleImpl; | ||
#endif | ||
|
||
|
||
LoadedModuleImpl* | ||
LoadedModuleImpl::NewPlatformImpl(const std::string& filename) | ||
{ | ||
return new PlatformLoadedModuleImpl(filename); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
#pragma once | ||
|
||
#include "LoadedModule.h" | ||
|
||
#include <boost/utility.hpp> | ||
|
||
class LoadedModuleImpl : boost::noncopyable | ||
{ | ||
public: | ||
static LoadedModuleImpl* NewPlatformImpl(const std::string& filename); | ||
|
||
virtual ~LoadedModuleImpl() {} | ||
|
||
virtual void Unload() = 0; | ||
virtual void* GetFunction(const char* funcName) = 0; | ||
|
||
protected: | ||
LoadedModuleImpl() {} | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,57 @@ | ||
#include "LoadedModuleImplUnix.h" | ||
|
||
#include "../Error.h" | ||
|
||
#include <dlfcn.h> | ||
|
||
|
||
static void __attribute__((noreturn)) | ||
ThrowDlError() | ||
{ | ||
const char* errorText = dlerror(); | ||
if (!errorText) | ||
errorText = "Operating system error message not available"; | ||
throw CMMError(errorText); | ||
} | ||
|
||
|
||
LoadedModuleImplUnix::LoadedModuleImplUnix(const std::string& filename) | ||
{ | ||
int mode = RTLD_NOW | RTLD_LOCAL; | ||
|
||
// Hack to make Andor adapter on Linux work | ||
// TODO Check if this is still necessary, and if so, why. If it is | ||
// necessary, add a more generic 'enable-lazy' mechanism. | ||
if (filename.find("libmmgr_dal_Andor.so") != std::string::npos) | ||
mode = RTLD_LAZY | RTLD_LOCAL; | ||
|
||
handle_ = dlopen(filename.c_str(), mode); | ||
if (!handle_) | ||
ThrowDlError(); | ||
} | ||
|
||
|
||
void | ||
LoadedModuleImplUnix::Unload() | ||
{ | ||
if (!handle_) | ||
return; | ||
|
||
int err = dlclose(handle_); | ||
handle_ = 0; | ||
if (err) | ||
ThrowDlError(); | ||
} | ||
|
||
|
||
void* | ||
LoadedModuleImplUnix::GetFunction(const char* funcName) | ||
{ | ||
if (!handle_) | ||
throw CMMError("Cannot get function from unloaded module"); | ||
|
||
void* proc = dlsym(handle_, funcName); | ||
if (!proc) | ||
ThrowDlError(); | ||
return proc; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
#include "LoadedModuleImpl.h" | ||
|
||
|
||
class LoadedModuleImplUnix : public LoadedModuleImpl | ||
{ | ||
public: | ||
explicit LoadedModuleImplUnix(const std::string& filename); | ||
virtual void Unload(); | ||
|
||
virtual void* GetFunction(const char* funcName); | ||
|
||
private: | ||
void* handle_; | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,83 @@ | ||
#include "LoadedModuleImplWindows.h" | ||
|
||
#include "../Error.h" | ||
|
||
#include <boost/algorithm/string.hpp> | ||
|
||
|
||
static void __declspec(noreturn) | ||
ThrowLastError() | ||
{ | ||
std::string errorText; | ||
|
||
DWORD err = GetLastError(); | ||
LPSTR pMsgBuf(0); | ||
if (FormatMessageA( | ||
FORMAT_MESSAGE_ALLOCATE_BUFFER | | ||
FORMAT_MESSAGE_FROM_SYSTEM | | ||
FORMAT_MESSAGE_IGNORE_INSERTS, | ||
NULL, | ||
err, | ||
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), | ||
(LPSTR)&pMsgBuf, | ||
0, | ||
NULL) && pMsgBuf) | ||
{ | ||
errorText = pMsgBuf; | ||
|
||
// Windows error messages sometimes have trailing newlines | ||
boost::algorithm::trim(errorText); | ||
|
||
// This particular message can be rather misleading. | ||
if (errorText == "The specified module could not be found.") { | ||
errorText = "The module, or a module it depends upon, could not be found " | ||
"(Windows error: " + errorText + ")"; | ||
} | ||
} | ||
if (pMsgBuf) | ||
{ | ||
LocalFree(pMsgBuf); | ||
} | ||
|
||
if (errorText.empty()) { | ||
errorText = "Operating system error message not available"; | ||
} | ||
|
||
throw CMMError(errorText); | ||
} | ||
|
||
|
||
LoadedModuleImplWindows::LoadedModuleImplWindows(const std::string& filename) | ||
{ | ||
int saveErrorMode = SetErrorMode(SEM_NOOPENFILEERRORBOX | SEM_FAILCRITICALERRORS); | ||
handle_ = LoadLibrary(filename.c_str()); | ||
SetErrorMode(saveErrorMode); | ||
if (!handle_) | ||
ThrowLastError(); | ||
} | ||
|
||
|
||
void | ||
LoadedModuleImplWindows::Unload() | ||
{ | ||
if (!handle_) | ||
return; | ||
|
||
BOOL ok = FreeLibrary(handle_); | ||
handle_ = 0; | ||
if (!ok) | ||
ThrowLastError(); | ||
} | ||
|
||
|
||
void* | ||
LoadedModuleImplWindows::GetFunction(const char* funcName) | ||
{ | ||
if (!handle_) | ||
throw CMMError("Cannot get function from unloaded module"); | ||
|
||
void* proc = GetProcAddress(handle_, funcName); | ||
if (!proc) | ||
ThrowLastError(); | ||
return proc; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
#pragma once | ||
|
||
#include "LoadedModuleImpl.h" | ||
|
||
#include <windows.h> | ||
|
||
|
||
class LoadedModuleImplWindows: public LoadedModuleImpl | ||
{ | ||
public: | ||
explicit LoadedModuleImplWindows(const std::string& filename); | ||
virtual void Unload(); | ||
|
||
virtual void* GetFunction(const char* funcName); | ||
|
||
private: | ||
HMODULE handle_; | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.