Skip to content

Commit

Permalink
#5231: Move DynamicLibrary to a static modulelib to be able to use it…
Browse files Browse the repository at this point in the history
… in more than one binary.

Add preliminary code to instantiate the core module from the main binary at startup.
  • Loading branch information
codereader committed Apr 28, 2020
1 parent 04681d3 commit 6e2305a
Show file tree
Hide file tree
Showing 18 changed files with 405 additions and 43 deletions.
16 changes: 16 additions & 0 deletions include/iradiant.h
Expand Up @@ -7,6 +7,22 @@

const char* const MODULE_RADIANT("Radiant");

namespace radiant
{

/**
* Main application host
*/
class IRadiant
{
public:
typedef std::shared_ptr<IRadiant> Ptr;

virtual ~IRadiant() {}
};

}

/**
* \brief
* Interface to the core application.
Expand Down
103 changes: 103 additions & 0 deletions libs/module/CoreModule.h
@@ -0,0 +1,103 @@
#pragma once

#include "imodule.h"
#include "iradiant.h"
#include "os/fs.h"

#include "DynamicLibrary.h"

#define SYMBOL_CREATE_RADIANT CreateRadiant
#define SYMBOL_DESTROY_RADIANT DestroyRadiant
#define Q(x) #x
#define QUOTE(x) Q(x)

namespace module
{

class CoreModule
{
private:
typedef radiant::IRadiant* (*CreateRadiantFunc)(ApplicationContext& context);
typedef void (*DestroyRadiantFunc)(radiant::IRadiant* radiant);

radiant::IRadiant* _instance;

DynamicLibraryPtr _coreModuleLibrary;

public:
class FailureException :
public std::runtime_error
{
public:
FailureException(const std::string& msg) :
std::runtime_error(msg)
{}
};

CoreModule(ApplicationContext& context) :
_instance(nullptr)
{
std::string coreModuleFile = std::string("DarkRadiantCore") + MODULE_FILE_EXTENSION;

fs::path coreModulePath = context.getApplicationPath();
coreModulePath /= coreModuleFile;

if (!fs::exists(coreModulePath))
{
throw FailureException("Cannot find the main module " + coreModuleFile);
}

_coreModuleLibrary = std::make_shared<DynamicLibrary>(coreModulePath.string());

if (_coreModuleLibrary->failed())
{
throw FailureException("Cannot load the main module " + _coreModuleLibrary->getName());
}

auto symbol = _coreModuleLibrary->findSymbol(QUOTE(SYMBOL_CREATE_RADIANT));

if (symbol == nullptr)
{
throw FailureException("Main module " + _coreModuleLibrary->getName() +
" doesn't expose the symbol " + QUOTE(SYMBOL_CREATE_RADIANT));
}

auto createFunc = reinterpret_cast<CreateRadiantFunc>(symbol);

_instance = createFunc(context);
}

~CoreModule()
{
destroy();
}

radiant::IRadiant* get()
{
return _instance;
}

private:
void destroy()
{
if (_instance)
{
assert(_coreModuleLibrary);

auto symbol = _coreModuleLibrary->findSymbol(QUOTE(SYMBOL_DESTROY_RADIANT));

if (symbol == nullptr)
{
throw FailureException("Main module " + _coreModuleLibrary->getName() +
" doesn't expose the symbol " + QUOTE(SYMBOL_DESTROY_RADIANT));
}

auto destroyFunc = reinterpret_cast<DestroyRadiantFunc>(symbol);

destroyFunc(_instance);
_instance = nullptr;
}
}
};

}
Expand Up @@ -3,7 +3,8 @@
#include "string/encoding.h"
#include "itextstream.h"

namespace module {
namespace module
{

/**
* =============================== WIN32 ======================================
Expand Down
@@ -1,10 +1,15 @@
#ifndef DYNAMICLIBRARY_H_
#define DYNAMICLIBRARY_H_
#pragma once

#include <string>
#include <vector>
#include <memory>

#if defined(WIN32)
const char* const MODULE_FILE_EXTENSION = ".dll";
#elif defined(POSIX)
const char* const MODULE_FILE_EXTENSION = ".so";
#endif

/** greebo: This file declares the classes encapsulating a dynamically linked library.
* Each DL class must define a FunctionPointer typedef and a findSymbol() method.
*
Expand All @@ -18,11 +23,13 @@

#include <windows.h>

namespace module {
namespace module
{

/** greebo: WIN32 DynamicLibrary. Loads a DLL given in the constructor.
*/
class DynamicLibrary {
class DynamicLibrary
{
// The full filename of this library
std::wstring _name;

Expand Down Expand Up @@ -59,9 +66,11 @@ class DynamicLibrary {

#include <dlfcn.h>

namespace module {
namespace module
{

class DynamicLibrary {
class DynamicLibrary
{
// The full filename of this library
std::string _name;

Expand Down Expand Up @@ -95,12 +104,13 @@ class DynamicLibrary {
#error "unsupported platform"
#endif

namespace module {
// Shared ptr typedef
typedef std::shared_ptr<DynamicLibrary> DynamicLibraryPtr;
namespace module
{

// A list of allocated libraries
typedef std::vector<DynamicLibraryPtr> DynamicLibraryList;
}
// Shared ptr typedef
typedef std::shared_ptr<DynamicLibrary> DynamicLibraryPtr;

// A list of allocated libraries
typedef std::vector<DynamicLibraryPtr> DynamicLibraryList;

#endif /*DYNAMICLIBRARY_H_*/
}
29 changes: 29 additions & 0 deletions radiant/Radiant.cpp
@@ -0,0 +1,29 @@
#include "iradiant.h"
#include "module/CoreModule.h"

namespace radiant
{

class Radiant :
public IRadiant
{
private:
ApplicationContext& _context;

public:
Radiant(ApplicationContext& context) :
_context(context)
{}
};

}

extern "C" DARKRADIANT_DLLEXPORT radiant::IRadiant* SYMBOL_CREATE_RADIANT(ApplicationContext& context)
{
return new radiant::Radiant(context);
}

extern "C" DARKRADIANT_DLLEXPORT void SYMBOL_DESTROY_RADIANT(radiant::IRadiant* radiant)
{
delete radiant;
}
21 changes: 20 additions & 1 deletion radiant/RadiantApp.cpp
@@ -1,11 +1,13 @@
#include "RadiantApp.h"

#include "i18n.h"
#include "iradiant.h"

#include "log/LogFile.h"
#include "log/LogStream.h"
#include "log/PIDFile.h"
#include "modulesystem/ModuleRegistry.h"
#include "module/CoreModule.h"

#include <wx/wxprec.h>
#include <wx/event.h>
Expand Down Expand Up @@ -53,6 +55,18 @@ bool RadiantApp::OnInit()
_context.initialise(wxApp::argc, wxApp::argv);
module::ModuleRegistry::Instance().setContext(_context);

try
{
_coreModule.reset(new module::CoreModule(_context));

auto* radiant = _coreModule->get();
}
catch (module::CoreModule::FailureException & ex)
{
rError() << "Failed to load core module" << std::endl;
throw ex;
}

// The settings path is set, start logging now
applog::LogFile::create("darkradiant.log");

Expand All @@ -77,7 +91,7 @@ bool RadiantApp::OnInit()
wxInitAllImageHandlers();

// Register to the start up signal
Bind(EV_RadiantStartup, sigc::mem_fun(*this, &RadiantApp::onStartupEvent));
Bind(EV_RadiantStartup, &RadiantApp::onStartupEvent, this);

// Activate the Popup Error Handler
_context.initErrorHandler();
Expand All @@ -89,6 +103,11 @@ bool RadiantApp::OnInit()

int RadiantApp::OnExit()
{
if (_coreModule)
{
_coreModule.reset();
}

// Issue a shutdown() call to all the modules
module::GlobalModuleRegistry().shutdownModules();

Expand Down
3 changes: 3 additions & 0 deletions radiant/RadiantApp.h
Expand Up @@ -2,6 +2,7 @@

#include <wx/app.h>
#include "modulesystem/ApplicationContextImpl.h"
#include "module/CoreModule.h"

/**
* Main application class required by wxWidgets
Expand All @@ -21,6 +22,8 @@ class RadiantApp :
// ModuleRegistry as a refernce.
radiant::ApplicationContextImpl _context;

std::unique_ptr<module::CoreModule> _coreModule;

public:
bool OnInit() override;
int OnExit() override;
Expand Down
6 changes: 0 additions & 6 deletions radiant/modulesystem/ModuleLoader.cpp
Expand Up @@ -19,12 +19,6 @@ namespace
const std::string PLUGINS_DIR = "plugins/"; ///< name of plugins directory
const std::string MODULES_DIR = "modules/"; ///< name of modules directory

#if defined(WIN32)
const std::string MODULE_FILE_EXTENSION = ".dll";
#elif defined(POSIX)
const std::string MODULE_FILE_EXTENSION = ".so";
#endif

// This is the name of the entry point symbol in the module
const char* const SYMBOL_REGISTER_MODULE = "RegisterModule";

Expand Down
2 changes: 1 addition & 1 deletion radiant/modulesystem/ModuleLoader.h
Expand Up @@ -3,7 +3,7 @@
#include <string>
#include <vector>
#include "imodule.h"
#include "DynamicLibrary.h"
#include "module/DynamicLibrary.h"
#include "os/fs.h"

namespace module
Expand Down
14 changes: 14 additions & 0 deletions tools/msvc/DarkRadiant.sln
Expand Up @@ -5,6 +5,9 @@ MinimumVisualStudioVersion = 10.0.40219.1
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "mathlib", "mathlib.vcxproj", "{3C9FB5AA-7118-476E-B33D-D3AC1C8412BB}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "DarkRadiant", "DarkRadiant.vcxproj", "{8E70385C-223A-4DD1-9B99-28FF2331A2B5}"
ProjectSection(ProjectDependencies) = postProject
{83D79C71-4E8F-4F78-9D46-EF02D5D5CD89} = {83D79C71-4E8F-4F78-9D46-EF02D5D5CD89}
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "xmlutillib", "xmlutillib.vcxproj", "{A15EFB56-927F-411D-A57B-0328321456A2}"
EndProject
Expand Down Expand Up @@ -52,6 +55,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Main Binary and Headers", "
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "DarkRadiantCore", "DarkRadiantCore.vcxproj", "{83D79C71-4E8F-4F78-9D46-EF02D5D5CD89}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "modulelib", "modulelib.vcxproj", "{76FF9B0F-B1FF-42BF-9E1D-8FBE2B3F6215}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Win32 = Debug|Win32
Expand Down Expand Up @@ -188,6 +193,14 @@ Global
{83D79C71-4E8F-4F78-9D46-EF02D5D5CD89}.Release|Win32.Build.0 = Release|Win32
{83D79C71-4E8F-4F78-9D46-EF02D5D5CD89}.Release|x64.ActiveCfg = Release|x64
{83D79C71-4E8F-4F78-9D46-EF02D5D5CD89}.Release|x64.Build.0 = Release|x64
{76FF9B0F-B1FF-42BF-9E1D-8FBE2B3F6215}.Debug|Win32.ActiveCfg = Debug|Win32
{76FF9B0F-B1FF-42BF-9E1D-8FBE2B3F6215}.Debug|Win32.Build.0 = Debug|Win32
{76FF9B0F-B1FF-42BF-9E1D-8FBE2B3F6215}.Debug|x64.ActiveCfg = Debug|x64
{76FF9B0F-B1FF-42BF-9E1D-8FBE2B3F6215}.Debug|x64.Build.0 = Debug|x64
{76FF9B0F-B1FF-42BF-9E1D-8FBE2B3F6215}.Release|Win32.ActiveCfg = Release|Win32
{76FF9B0F-B1FF-42BF-9E1D-8FBE2B3F6215}.Release|Win32.Build.0 = Release|Win32
{76FF9B0F-B1FF-42BF-9E1D-8FBE2B3F6215}.Release|x64.ActiveCfg = Release|x64
{76FF9B0F-B1FF-42BF-9E1D-8FBE2B3F6215}.Release|x64.Build.0 = Release|x64
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Expand All @@ -209,6 +222,7 @@ Global
{586DBC32-C9D4-4720-B246-1E3D7D8C02B3} = {3C3C0B81-D1B7-4EE4-9224-99ECA5774F25}
{5EB15BCF-2131-4DE3-B411-FC0D2DEF702F} = {F0E8C46B-4F20-43B1-9A8D-13A9D0A3BA3D}
{83D79C71-4E8F-4F78-9D46-EF02D5D5CD89} = {F0E8C46B-4F20-43B1-9A8D-13A9D0A3BA3D}
{76FF9B0F-B1FF-42BF-9E1D-8FBE2B3F6215} = {026C3BBE-9A3B-4D21-A49D-12DD9DDF3CBA}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {C7F73C9B-AFA1-4AF0-9F99-7C3A7F503A86}
Expand Down
2 changes: 0 additions & 2 deletions tools/msvc/DarkRadiant.vcxproj
Expand Up @@ -868,7 +868,6 @@
<ClCompile Include="..\..\radiant\map\StartupMapLoader.cpp" />
<ClCompile Include="..\..\radiant\map\algorithm\Traverse.cpp" />
<ClCompile Include="..\..\radiant\modulesystem\ApplicationContextImpl.cpp" />
<ClCompile Include="..\..\radiant\modulesystem\DynamicLibrary.cpp" />
<ClCompile Include="..\..\radiant\modulesystem\ModuleLoader.cpp" />
<ClCompile Include="..\..\radiant\modulesystem\ModuleRegistry.cpp" />
<ClCompile Include="..\..\radiant\namespace\Namespace.cpp" />
Expand Down Expand Up @@ -1358,7 +1357,6 @@
<ClInclude Include="..\..\radiant\map\algorithm\Traverse.h" />
<ClInclude Include="..\..\radiant\map\algorithm\WorldspawnArgFinder.h" />
<ClInclude Include="..\..\radiant\modulesystem\ApplicationContextImpl.h" />
<ClInclude Include="..\..\radiant\modulesystem\DynamicLibrary.h" />
<ClInclude Include="..\..\radiant\modulesystem\ModuleLoader.h" />
<ClInclude Include="..\..\radiant\modulesystem\ModuleRegistry.h" />
<ClInclude Include="..\..\radiant\modulesystem\StaticModule.h" />
Expand Down

0 comments on commit 6e2305a

Please sign in to comment.