#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"); if(dlerror()) { std::cout << "error finding create function in file: " << lib << 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(); } } }