2017-12-10 15:31:48 +11:00
|
|
|
#include "ScriptLoader.h"
|
|
|
|
|
|
|
|
#include <Server_Common/Logging/Logger.h>
|
|
|
|
#include <boost/format.hpp>
|
|
|
|
#include <boost/filesystem.hpp>
|
2017-12-12 13:17:43 +11:00
|
|
|
#include <boost/algorithm/string/predicate.hpp>
|
2017-12-10 15:31:48 +11:00
|
|
|
|
|
|
|
extern Core::Logger g_log;
|
|
|
|
|
2017-12-12 01:45:24 +11:00
|
|
|
Core::Scripting::ScriptLoader::ScriptLoader()
|
|
|
|
{}
|
|
|
|
|
2017-12-10 15:31:48 +11:00
|
|
|
const std::string Core::Scripting::ScriptLoader::getModuleExtension()
|
|
|
|
{
|
|
|
|
#ifdef _WIN32
|
|
|
|
return ".dll";
|
|
|
|
#elif __APPLE__
|
|
|
|
return ".dylib";
|
|
|
|
#else
|
|
|
|
return ".so";
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
bool Core::Scripting::ScriptLoader::unloadModule( ModuleHandle handle )
|
|
|
|
{
|
|
|
|
#ifdef _WIN32
|
|
|
|
bool success = FreeLibrary( handle ) != 0;
|
|
|
|
#else
|
|
|
|
bool success = dlclose( handle ) == 0;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
if( !success )
|
|
|
|
{
|
|
|
|
g_log.fatal( "Failed to unload module @ 0x" + boost::str( boost::format( "%|08X|" ) % handle ) );
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
g_log.debug( "Unloaded module @ 0x" + boost::str( boost::format( "%|08X|" ) % handle ) );
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2017-12-12 01:45:24 +11:00
|
|
|
Core::Scripting::ScriptInfo* Core::Scripting::ScriptLoader::loadModule( std::string path )
|
2017-12-10 15:31:48 +11:00
|
|
|
{
|
2017-12-12 13:17:43 +11:00
|
|
|
boost::filesystem::path f( path );
|
|
|
|
|
|
|
|
if ( isModuleLoaded( f.stem().string() ) )
|
|
|
|
{
|
|
|
|
g_log.error( "Unable to load module '" + f.stem().string() + "' as it is already loaded" );
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2017-12-10 15:31:48 +11:00
|
|
|
#ifdef _WIN32
|
|
|
|
ModuleHandle handle = LoadLibrary( path.c_str() );
|
|
|
|
#else
|
|
|
|
ModuleHandle handle = dlopen( path.c_str(), RTLD_LAZY );
|
|
|
|
#endif
|
|
|
|
|
|
|
|
if( !handle )
|
|
|
|
{
|
|
|
|
g_log.error( "Failed to load module from: " + path );
|
|
|
|
|
2017-12-12 01:45:24 +11:00
|
|
|
return nullptr;
|
2017-12-10 15:31:48 +11:00
|
|
|
}
|
|
|
|
|
|
|
|
g_log.info( "Loaded module from '" + path + "' @ 0x" + boost::str( boost::format( "%|08X|" ) % handle ) );
|
|
|
|
|
2017-12-12 01:45:24 +11:00
|
|
|
auto info = new ScriptInfo;
|
|
|
|
info->handle = handle;
|
|
|
|
info->library_name = f.stem().string();
|
|
|
|
|
|
|
|
m_scriptMap.insert( std::make_pair( f.stem().string(), info ) );
|
|
|
|
|
|
|
|
return info;
|
2017-12-10 15:31:48 +11:00
|
|
|
}
|
|
|
|
|
2017-12-11 21:10:54 +11:00
|
|
|
ScriptObject* Core::Scripting::ScriptLoader::getScriptObjectExport( ModuleHandle handle, std::string name )
|
2017-12-10 15:31:48 +11:00
|
|
|
{
|
2017-12-10 16:49:01 +11:00
|
|
|
typedef ScriptObject* (*getScriptObjectType)();
|
|
|
|
auto fn = boost::str( boost::format( "get%1%" ) % name );
|
2017-12-10 15:31:48 +11:00
|
|
|
|
2017-12-11 21:10:54 +11:00
|
|
|
g_log.debug( "getting symbol: " + fn );
|
2017-12-10 15:31:48 +11:00
|
|
|
|
|
|
|
#ifdef _WIN32
|
|
|
|
getScriptObjectType func = reinterpret_cast< getScriptObjectType >( GetProcAddress( handle, fn.c_str() ) );
|
|
|
|
#else
|
|
|
|
getScriptObjectType func = reinterpret_cast< getScriptObjectType >( dlsym( handle, fn.c_str() ) );
|
|
|
|
#endif
|
|
|
|
|
|
|
|
if( func )
|
2017-12-11 21:10:54 +11:00
|
|
|
{
|
|
|
|
auto ptr = func();
|
|
|
|
|
|
|
|
g_log.debug( "got ScriptObject @ 0x" + boost::str( boost::format( "%|08X|" ) % ptr ) );
|
|
|
|
g_log.debug( "script info -> name: " + std::string( ptr->getName() ) + ", id: " + std::to_string( ptr->getId() ) );
|
|
|
|
|
|
|
|
return ptr;
|
|
|
|
}
|
2017-12-10 15:31:48 +11:00
|
|
|
else
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
2017-12-12 13:17:43 +11:00
|
|
|
bool Core::Scripting::ScriptLoader::unloadScript( Core::Scripting::ScriptInfo* info )
|
2017-12-10 15:31:48 +11:00
|
|
|
{
|
2017-12-12 13:17:43 +11:00
|
|
|
return unloadScript( info->handle );
|
2017-12-10 15:31:48 +11:00
|
|
|
}
|
|
|
|
|
|
|
|
bool Core::Scripting::ScriptLoader::unloadScript( ModuleHandle handle )
|
|
|
|
{
|
2017-12-12 01:45:24 +11:00
|
|
|
for( auto it = m_scriptMap.begin(); it != m_scriptMap.end(); ++it )
|
2017-12-10 15:31:48 +11:00
|
|
|
{
|
2017-12-12 01:45:24 +11:00
|
|
|
if( it->second->handle == handle )
|
2017-12-10 15:31:48 +11:00
|
|
|
{
|
2017-12-12 01:45:24 +11:00
|
|
|
delete it->second;
|
|
|
|
m_scriptMap.erase( it );
|
|
|
|
|
2017-12-10 15:31:48 +11:00
|
|
|
return unloadModule( handle );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
2017-12-12 01:45:24 +11:00
|
|
|
}
|
|
|
|
|
2017-12-12 13:17:43 +11:00
|
|
|
bool Core::Scripting::ScriptLoader::isModuleLoaded( std::string name )
|
2017-12-12 01:45:24 +11:00
|
|
|
{
|
|
|
|
for( auto it = m_scriptMap.begin(); it != m_scriptMap.end(); ++it )
|
|
|
|
{
|
2017-12-12 13:17:43 +11:00
|
|
|
if( boost::iequals( it->second->library_name, name ) )
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
Core::Scripting::ScriptInfo* Core::Scripting::ScriptLoader::getScriptInfo( std::string name )
|
|
|
|
{
|
|
|
|
for( auto it = m_scriptMap.begin(); it != m_scriptMap.end(); ++it )
|
|
|
|
{
|
|
|
|
if( it->second->script_name == name )
|
2017-12-12 01:45:24 +11:00
|
|
|
{
|
2017-12-12 13:17:43 +11:00
|
|
|
return it->second;
|
2017-12-12 01:45:24 +11:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-12-12 13:17:43 +11:00
|
|
|
return nullptr;
|
2017-12-10 15:31:48 +11:00
|
|
|
}
|