diff --git a/src/App.cpp b/example_apps/MinimalApp/MinimalApp.cpp similarity index 100% rename from src/App.cpp rename to example_apps/MinimalApp/MinimalApp.cpp diff --git a/src/App.h b/example_apps/MinimalApp/MinimalApp.h similarity index 100% rename from src/App.h rename to example_apps/MinimalApp/MinimalApp.h diff --git a/include/utils/App/App.cpp b/include/utils/App/App.cpp new file mode 100644 index 0000000..d2173fb --- /dev/null +++ b/include/utils/App/App.cpp @@ -0,0 +1,165 @@ +#include "App.h" + +Archimedes::App* Archimedes::App::instance = nullptr; + +namespace Archimedes { + + + App::App(const int& argc, char* argv[]) { + + if(instance != nullptr) { + std::cout << "App already exists\nThere can only be one!\n"; + std::abort(); + } + + std::cout << "Initializing...\n"; + + instance = this; + + handleArgs(argc, argv); + + } + + App::~App() { + + std::cout << "\nExiting...\n"; + for(auto it = modules.begin(); it != modules.end(); it++) { + void* handle = (*it)->getHandle(); + delete *it; + dlclose(handle); + it = modules.erase(it); + } + } + + + bool App::load(std::string lib, std::list blacklist = {}) { + + + std::cout << "print twice!\n"; + void* h = dlopen(lib.c_str(), RTLD_NOW); + + if(!h) { + std::cout << "could not open lib at: \"" << lib.c_str() << "\"\nError: " << dlerror() << std::endl; + return false; + } + + Module::create_t* create = (Module::create_t*) dlsym(h, "create"); + char* err = dlerror(); + if(err) { + std::cout << "error finding create function in file: " << lib << std::endl; + std::cout << "dlerror(): " << err << std::endl; + } + + Module* m = create(h, App::Get()); + + for(auto it = blacklist.begin(); it != blacklist.end(); it++) { + if(*it == m->getName()) { + std::cout << "Module \"" << *it << "\" is already loaded!\n"; + delete m; + dlclose(h); + return false; + } + } + + blacklist.push_back(m->getName()); + + bool skip = false; + for(auto it = m->deps.begin(); it != m->deps.end(); it++) { + for(std::string s : blacklist) { + if(it->first == s) + skip = true; + } + if(skip) { + skip = false; + continue; + } else { + load(it->second, blacklist); + } + } + + + modules.push_back(m); + m->setSelf(--modules.end()); + modules.end()++; + + return true; + } + + void App::unload(std::list::iterator it) { + + Module* m = *it; + void* h = m->getHandle(); + + modules.erase(m->self); + delete m; + + dlclose(h); + + } + + void App::stopModule(std::list::iterator it) { + toClose.push_back(*it); + } + + void App::startModule(std::string lib) { + toOpen.push_back(lib); + } + + void App::handleArgs(const int& argc, char* argv[]) { + + int i = 1; + + if(argc == 1) { + printHelp(); + end(); + } + + while(i < argc) { + if(strcmp(argv[i], "-h") == 0 || strcmp(argv[i], "--help") == 0) { + printHelp(); + end(); + } else { + break; + } + i++; + } + + while(i < argc) { + std::cout << "Attempting to load: " << argv[i] << std::endl; + load(argv[i]); + + i++; + } + } + + void App::printHelp() { + std::cout << "archimedes [ -h | --help ] /path/to/some/library.so\n"; + } + + + void App::run() { + std::cout << "\nTesting...\n"; + + for(auto* m : modules) + m->onLoad(); + + // Main loop + while (!done && !modules.empty()) { + + for(auto* m : modules) { + m->run(); + } + + for(auto it = toClose.begin(); it != toClose.end(); it++) { + unload(it); + } + toClose.clear(); + + for(std::string s : toOpen) { + load(s, getBlacklist()); + } + toOpen.clear(); + } + + } +} diff --git a/include/utils/App/App.h b/include/utils/App/App.h new file mode 100644 index 0000000..ec75117 --- /dev/null +++ b/include/utils/App/App.h @@ -0,0 +1,51 @@ +#ifndef APP_H +#define APP_H + +#include "pch.hpp" +#include "utils/Module/Module.h" + +namespace Archimedes { + + class App { + + protected: + static App* instance; + + bool done = false; + + std::list modules; + std::list toClose; + std::list toOpen; + + virtual bool load(std::string, std::list); + virtual void unload(std::list::iterator); + + virtual void handleArgs(const int&, char*[]); + + virtual void printHelp(); + + std::list getBlacklist() { + std::list l; + for(Module* m : modules) + l.push_back(m->getName()); + return l; + } + + public: + App(const int&, char*[]); + ~App(); + + static App& Get() { return *instance; } + + void run(); + + void stopModule(std::list::iterator); + + void startModule(std::string); + + void end() { done = true; } + }; + +} + +#endif