2014-11-12 05:39:20 +08:00
|
|
|
#include "zm_plugin.h"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*!\fn Plugin::Plugin(const std::string &sFilename)
|
|
|
|
* \param sFilename is the name of plugin file to load
|
|
|
|
*/
|
|
|
|
Plugin::Plugin(const std::string &sFilename)
|
|
|
|
: m_sPluginFileName(sFilename),
|
|
|
|
m_hDLL(0),
|
|
|
|
m_pDLLRefCount(0),
|
|
|
|
m_pfnGetEngineVersion(0),
|
|
|
|
m_pfnRegisterPlugin(0)
|
|
|
|
{
|
|
|
|
|
|
|
|
// Try to load the plugin as a dynamic library
|
|
|
|
m_hDLL = dlopen(sFilename.c_str(), RTLD_LAZY|RTLD_GLOBAL);
|
|
|
|
|
|
|
|
if(!m_hDLL) // if library hasn't been loaded successfully
|
|
|
|
{
|
2014-11-17 04:50:39 +08:00
|
|
|
throw runtime_error("Could not load '" + sFilename + "' (" + dlerror() + ")");
|
2014-11-12 05:39:20 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
// Locate the plugin's exported functions
|
|
|
|
try
|
|
|
|
{
|
|
|
|
m_pfnGetEngineVersion = reinterpret_cast<fnGetEngineVersion *>(dlsym(m_hDLL, "getEngineVersion"));
|
|
|
|
m_pfnRegisterPlugin = reinterpret_cast<fnRegisterPlugin *>(dlsym(m_hDLL, "registerPlugin"));
|
|
|
|
|
|
|
|
// If the functions aren't found, we're going to assume this is
|
|
|
|
// a plain simple DLL and not one of our plugins
|
|
|
|
if(!m_pfnGetEngineVersion || ! m_pfnRegisterPlugin)
|
2014-11-17 04:50:39 +08:00
|
|
|
throw runtime_error("'" + sFilename + "' is not a valid plugin");
|
2014-11-12 05:39:20 +08:00
|
|
|
|
|
|
|
// Initialize a new DLL reference counter
|
|
|
|
m_pDLLRefCount = new size_t(1);
|
|
|
|
}
|
|
|
|
catch(runtime_error &ex)
|
|
|
|
{
|
|
|
|
dlclose(m_hDLL);
|
|
|
|
throw ex;
|
|
|
|
}
|
|
|
|
catch(...)
|
|
|
|
{
|
|
|
|
dlclose(m_hDLL);
|
2014-11-17 04:50:39 +08:00
|
|
|
throw runtime_error("Unknown exception while loading plugin '" + sFilename + "'");
|
2014-11-12 05:39:20 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*!\fn Plugin::Plugin(const Plugin &Other)
|
|
|
|
* \param Other is the other plugin instance to copy
|
|
|
|
*/
|
|
|
|
Plugin::Plugin(const Plugin &Other)
|
|
|
|
: m_sPluginFileName(Other.m_sPluginFileName),
|
|
|
|
m_hDLL(Other.m_hDLL),
|
|
|
|
m_pDLLRefCount(Other.m_pDLLRefCount),
|
|
|
|
m_pfnGetEngineVersion(Other.m_pfnGetEngineVersion),
|
|
|
|
m_pfnRegisterPlugin(Other.m_pfnRegisterPlugin)
|
|
|
|
{
|
|
|
|
// Increase DLL reference counter
|
|
|
|
++*m_pDLLRefCount;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*!\fn Plugin::operator=(const Plugin &Other)
|
|
|
|
* \param Other is the other plugin instance to copy
|
|
|
|
* return copy of object
|
|
|
|
*/
|
|
|
|
Plugin& Plugin::operator=(const Plugin &Other)
|
|
|
|
{
|
|
|
|
m_hDLL = Other.m_hDLL;
|
|
|
|
m_pfnGetEngineVersion = Other.m_pfnGetEngineVersion;
|
|
|
|
m_pfnRegisterPlugin = Other.m_pfnRegisterPlugin;
|
|
|
|
m_pDLLRefCount = Other.m_pDLLRefCount;
|
|
|
|
m_sPluginFileName = Other.m_sPluginFileName;
|
|
|
|
// Increase DLL reference counter
|
|
|
|
++*m_pDLLRefCount;
|
|
|
|
return *this;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Plugin::~Plugin()
|
|
|
|
{
|
|
|
|
// Only unload the DLL if there are no more references to it
|
|
|
|
if(!--*m_pDLLRefCount)
|
|
|
|
{
|
|
|
|
delete m_pDLLRefCount;
|
|
|
|
dlclose(m_hDLL);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*!\fn Plugin::registerPlugin(PluginManager &K)
|
|
|
|
* \param K is the pointer to plugin manager
|
|
|
|
*/
|
|
|
|
void Plugin::registerPlugin(PluginManager &K)
|
|
|
|
{
|
|
|
|
m_pfnRegisterPlugin(K, m_sPluginFileName);
|
|
|
|
}
|