From 5a8e1d9fa03c87e9434140c0f3de327bb761b63b Mon Sep 17 00:00:00 2001 From: Hleb Valoshka <375gnu@gmail.com> Date: Tue, 22 Oct 2019 23:44:15 +0300 Subject: [PATCH 01/14] wip --- src/celplugin/CMakeLists.txt | 8 +++ src/celplugin/config.h | 0 src/celplugin/host.cpp | 36 +++++++++++++ src/celplugin/myplug.cpp | 15 ++++++ src/celplugin/plugin.cpp | 96 +++++++++++++++++++++++++++++++++ src/celplugin/plugin.h | 90 +++++++++++++++++++++++++++++++ src/celplugin/pluginmanager.cpp | 35 ++++++++++++ src/celplugin/pluginmanager.h | 28 ++++++++++ 8 files changed, 308 insertions(+) create mode 100644 src/celplugin/CMakeLists.txt create mode 100644 src/celplugin/config.h create mode 100644 src/celplugin/host.cpp create mode 100644 src/celplugin/myplug.cpp create mode 100644 src/celplugin/plugin.cpp create mode 100644 src/celplugin/plugin.h create mode 100644 src/celplugin/pluginmanager.cpp create mode 100644 src/celplugin/pluginmanager.h diff --git a/src/celplugin/CMakeLists.txt b/src/celplugin/CMakeLists.txt new file mode 100644 index 0000000000..4f974b6183 --- /dev/null +++ b/src/celplugin/CMakeLists.txt @@ -0,0 +1,8 @@ +cmake_minimum_required(VERSION 3.7) +add_compile_options(-fPIC) +add_compile_options(-g) +find_package(fmt 4.0.0 CONFIG REQUIRED) +add_executable(plugintest host.cpp plugin.cpp pluginmanager.cpp ../celcompat/fs.cpp) +include_directories(. ..) +target_link_libraries(plugintest fmt::fmt dl) +add_library(myplug MODULE myplug.cpp) diff --git a/src/celplugin/config.h b/src/celplugin/config.h new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/celplugin/host.cpp b/src/celplugin/host.cpp new file mode 100644 index 0000000000..66845d29c9 --- /dev/null +++ b/src/celplugin/host.cpp @@ -0,0 +1,36 @@ +#include +#include "plugin.h" +#include "pluginmanager.h" +#include +#include // getcwd + +using namespace celestia::plugin; + +int main() +{ + char cwd[256]; + getcwd(cwd, 255); + + PluginManager pm; + pm.searchDirectory() = cwd; + Plugin* p = pm.loadByName("myplug"); + if (p == nullptr) + { + std::cout << "load failed\n"; + return 1; + } + + PluginInfo *pi = p->getPluginInfo(); + if (pi == nullptr) + { + std::cout << "no data provided\n"; + return 2; + } + + fmt::printf("APIVersion = %hx, Type = %hu, Implementation Defined Data = %p\n", pi->APIVersion, pi->Type, fmt::ptr(pi->IDDPtr)); + + void (*myfn)() = reinterpret_cast(pi->IDDPtr); + (*myfn)(); + + return 0; +} diff --git a/src/celplugin/myplug.cpp b/src/celplugin/myplug.cpp new file mode 100644 index 0000000000..0cc97f4690 --- /dev/null +++ b/src/celplugin/myplug.cpp @@ -0,0 +1,15 @@ +#include +#include "plugin.h" + +using namespace celestia::plugin; + +static void myfn() +{ + std::cout << "hi from plugin!\n"; +} + +CELESTIA_PLUGIN_ENTRYPOINT() +{ + static PluginInfo pinf = { 0x0107, 0, Nothing, 0, reinterpret_cast(&myfn) }; + return &pinf; +} diff --git a/src/celplugin/plugin.cpp b/src/celplugin/plugin.cpp new file mode 100644 index 0000000000..5af3de7eb0 --- /dev/null +++ b/src/celplugin/plugin.cpp @@ -0,0 +1,96 @@ +#include +#include "plugin.h" +#ifndef _WIN32 +#include +#endif + +namespace celestia +{ +namespace plugin +{ +Plugin::~Plugin() +{ + if (m_handle != nullptr) + { +#ifdef _WIN32 + FreeLibrary(m_handle); +#else + dlclose(m_handle); +#endif + } +} + +Plugin::Plugin(Plugin &&other) +{ + m_handle = other.m_handle; + other.m_handle = nullptr; + m_regfn = other.m_regfn; + other.m_regfn = nullptr; + + setupScriptEnvironment = other.setupScriptEnvironment; +} + +PluginInfo* Plugin::getPluginInfo() const +{ + return (*m_regfn)(); +} + +Plugin* Plugin::load(const fs::path& path) +{ + Plugin p; + +#ifdef _WIN32 + p.m_handle = ::LoadLibraryW(path.c_str()); + if (p.m_handle == nullptr) + { + fmt::print(std::cerr, "::LoadLibraryW({}) failed: {}\n", path); + return nullptr; + } +#else + p.m_handle = dlopen(path.c_str(), RTLD_NOW/*|RTLD_GLOBAL*/); + if (p.m_handle == nullptr) + { + fmt::print(std::cerr, "dlopen({}) failed: {}\n", path, dlerror()); + return nullptr; + } +#endif + + void *ptr = p.loadSym(CELESTIA_PLUGIN_ENTRY_NAME_STR); + if (ptr == nullptr) + return nullptr; + p.m_regfn = reinterpret_cast(ptr); + + PluginInfo *pi = p.getPluginInfo(); + switch (pi->Type) + { + case Nothing: + break; + case Script: + ptr = p.loadSym("SetupScriptEnvironment"); + if (ptr != nullptr) + p.setupScriptEnvironment = reinterpret_cast(ptr); + break; + default: + fmt::print(std::cerr, "unknown plugin type {} ({})\n", pi->Type, path); + return nullptr; + } + p.m_type = pi->Type; + + return new Plugin(std::move(p)); +} + +void* Plugin::loadSym(const char* fn) const +{ +#ifdef _WIN32 + return ::GetProcAddress(m_handle, fn); +#else + void *ptr = dlsym(m_handle, fn); + char *error = dlerror(); + if (error != nullptr) + fmt::print(std::cerr, "dlsym({}) failed: {}\n", fn, error); + return ptr; +#endif +} + +} +} diff --git a/src/celplugin/plugin.h b/src/celplugin/plugin.h new file mode 100644 index 0000000000..79367b657f --- /dev/null +++ b/src/celplugin/plugin.h @@ -0,0 +1,90 @@ +#pragma once + +#include +#include +#include +#include +#ifdef _WIN32 +#include +#endif + +#define CELESTIA_PLUGIN_ENTRY_NAME get_celestia_plugin_info +#define CELESTIA_PLUGIN_ENTRY_NAME_STR "get_celestia_plugin_info" + +#ifdef _WIN32 +#define CELESTIA_PLUGIN_EXPORTABLE extern "C" __declspec(dllexport) +#else +#define CELESTIA_PLUGIN_EXPORTABLE extern "C" +#endif + +#define CELESTIA_PLUGIN_ENTRYPOINT CELESTIA_PLUGIN_EXPORTABLE PluginInfo* CELESTIA_PLUGIN_ENTRY_NAME + + +namespace celestia +{ +namespace plugin +{ + +class PluginManager; + +enum PluginType : uint32_t +{ + Nothing = 0, + Script = 0x0001, + Audio = 0x0002, + Video = 0x0004, + Render = 0x0010, +}; + +#pragma pack(push,1) +struct PluginInfo +{ + uint16_t APIVersion; + uint16_t Reserved1; + PluginType Type; + uint32_t Reserved2; + void *IDDPtr; // IDD == Implementation Defined Data +}; +#pragma pack(pop) + +class Plugin +{ + public: + Plugin() = default; + ~Plugin(); + Plugin(const Plugin&) = delete; + Plugin(Plugin&&); + Plugin& operator=(const Plugin&) = delete; + Plugin& operator=(Plugin&&) = default; + + PluginInfo* getPluginInfo() const; + + void* loadSym(const char*) const; + + PluginType getType() const { return m_type; } + + static Plugin* load(const fs::path&); + + // pointers to plugin functions + typedef bool(SetupScriptEnvironmentFunc)(); + + SetupScriptEnvironmentFunc *setupScriptEnvironment; + + private: + +#ifdef _WIN32 + HMODULE m_handle { nullptr }; +#else + void *m_handle { nullptr }; +#endif + + PluginType m_type { Nothing }; + + typedef PluginInfo*(RegisterFunc)(); + RegisterFunc *m_regfn; + + friend class PluginManager; +}; // Plugin + +} +} diff --git a/src/celplugin/pluginmanager.cpp b/src/celplugin/pluginmanager.cpp new file mode 100644 index 0000000000..bf4a1e8fde --- /dev/null +++ b/src/celplugin/pluginmanager.cpp @@ -0,0 +1,35 @@ +#include +#include "plugin.h" +#include "pluginmanager.h" +#ifndef _WIN32 +#include +#endif + +namespace celestia +{ +namespace plugin +{ +PluginManager::~PluginManager() +{ + for (auto p : m_plugins) + delete p; +} + +Plugin* PluginManager::loadByPath(const fs::path &path) +{ + return Plugin::load(path); +} + +Plugin* PluginManager::loadByName(const std::string &name) +{ +#if defined(_WIN32) + return Plugin::load(m_directory / fmt::sprintf("%s.dll", name)); +#elif defined(__APPLE__) + return nullptr; +#else + return Plugin::load(m_directory / fmt::sprintf("lib%s.so", name)); +#endif +} + +} +} diff --git a/src/celplugin/pluginmanager.h b/src/celplugin/pluginmanager.h new file mode 100644 index 0000000000..598f6bb72f --- /dev/null +++ b/src/celplugin/pluginmanager.h @@ -0,0 +1,28 @@ +#pragma once + +#include +#include +#include + + +namespace celestia +{ +namespace plugin +{ +class Plugin; + +class PluginManager +{ + public: + ~PluginManager(); + Plugin* loadByPath(const fs::path&); + Plugin* loadByName(const std::string &name); + fs::path& searchDirectory() { return m_directory; } + const fs::path searchDirectory() const { return m_directory; } + + private: + std::vector m_plugins; + fs::path m_directory; +}; // PluginManager +} +} From f42ca1cd7f8952a1a98ec4abf72d0cf02226d6e3 Mon Sep 17 00:00:00 2001 From: Hleb Valoshka <375gnu@gmail.com> Date: Wed, 23 Oct 2019 15:07:21 +0300 Subject: [PATCH 02/14] wip --- src/celplugin/plugin.cpp | 36 +++++++++++++++++++++++++++++++++--- src/celplugin/plugin.h | 40 ++++++++++++++++++++++++++++++++++++---- 2 files changed, 69 insertions(+), 7 deletions(-) diff --git a/src/celplugin/plugin.cpp b/src/celplugin/plugin.cpp index 5af3de7eb0..0976d1dd92 100644 --- a/src/celplugin/plugin.cpp +++ b/src/celplugin/plugin.cpp @@ -27,7 +27,7 @@ Plugin::Plugin(Plugin &&other) m_regfn = other.m_regfn; other.m_regfn = nullptr; - setupScriptEnvironment = other.setupScriptEnvironment; + m_func = other.m_func; } PluginInfo* Plugin::getPluginInfo() const @@ -66,9 +66,9 @@ Plugin* Plugin::load(const fs::path& path) case Nothing: break; case Script: - ptr = p.loadSym("SetupScriptEnvironment"); + ptr = p.loadSym("CreateScriptEnvironment"); if (ptr != nullptr) - p.setupScriptEnvironment = reinterpret_cast(ptr); + p.m_func.createScriptEnvironment = reinterpret_cast(ptr); break; default: fmt::print(std::cerr, "unknown plugin type {} ({})\n", pi->Type, path); @@ -92,5 +92,35 @@ void* Plugin::loadSym(const char* fn) const #endif } +bool Plugin::createScriptEnvironment(CelestiaCore *appCore, const CelestiaConfig *config, ProgressNotifier *progressNotifier) const +{ + auto fn = m_func.createScriptEnvironment; + return fn == nullptr ? false : (*fn)(appCore, config, progressNotifier); +} + +IScript* Plugin::createScript(CelestiaCore *appCore) const +{ + auto fn = m_func.createScript; + return fn == nullptr ? nullptr : (*fn)(appCore); +} + +RotationModel* Plugin::createScritedRotation(const std::string& moduleName, const std::string& funcName, Hash* parameters) const +{ + auto fn = m_func.createScritedRotation; + return fn == nullptr ? nullptr : (*fn)(moduleName, funcName, parameters); +} + +CachingOrbit* Plugin::createScritedOrbit(const std::string& moduleName, const std::string& funcName, Hash* parameters) const +{ + auto fn = m_func.createScritedOrbit; + return fn == nullptr ? nullptr : (*fn)(moduleName, funcName, parameters); +} + +Renderer* Plugin::createRenderer() const +{ + auto fn = m_func.createRenderer; + return fn == nullptr ? nullptr : (*fn)(); +} + } } diff --git a/src/celplugin/plugin.h b/src/celplugin/plugin.h index 79367b657f..af3336d785 100644 --- a/src/celplugin/plugin.h +++ b/src/celplugin/plugin.h @@ -19,6 +19,14 @@ #define CELESTIA_PLUGIN_ENTRYPOINT CELESTIA_PLUGIN_EXPORTABLE PluginInfo* CELESTIA_PLUGIN_ENTRY_NAME +class CelestiaCore; +class CelestiaConfig; +class ProgressNotifier; +class IScript; +class Hash; +class Renderer; +class CachingOrbit; +class RotationModel; namespace celestia { @@ -58,17 +66,26 @@ class Plugin Plugin& operator=(Plugin&&) = default; PluginInfo* getPluginInfo() const; - void* loadSym(const char*) const; - PluginType getType() const { return m_type; } static Plugin* load(const fs::path&); // pointers to plugin functions - typedef bool(SetupScriptEnvironmentFunc)(); + /// scripting support + typedef bool(CreateScriptEnvironmentFunc)(CelestiaCore*, const CelestiaConfig*, ProgressNotifier*); + typedef IScript*(CreateScriptFunc)(CelestiaCore*); + typedef RotationModel*(CreateScritedRotationFunc)(const std::string&, const std::string&, Hash*); + typedef CachingOrbit*(CreateScritedOrbitFunc)(const std::string&, const std::string&, Hash*); - SetupScriptEnvironmentFunc *setupScriptEnvironment; + /// renderer support + typedef Renderer*(CreateRendererFunc)(); + + bool createScriptEnvironment(CelestiaCore *appCore, const CelestiaConfig *config, ProgressNotifier *progressNotifier) const; + IScript* createScript(CelestiaCore *appCore) const; + RotationModel* createScritedRotation(const std::string& moduleName, const std::string& funcName, Hash* parameters) const; + CachingOrbit* createScritedOrbit(const std::string& moduleName, const std::string& funcName, Hash* parameters) const; + Renderer* createRenderer() const; private: @@ -83,6 +100,21 @@ class Plugin typedef PluginInfo*(RegisterFunc)(); RegisterFunc *m_regfn; + union + { + struct + { + CreateScriptEnvironmentFunc *createScriptEnvironment; + CreateScriptFunc *createScript; + CreateScritedRotationFunc *createScritedRotation; + CreateScritedOrbitFunc *createScritedOrbit; + }; + struct + { + CreateRendererFunc *createRenderer; + }; + } m_func; + friend class PluginManager; }; // Plugin From a7bdbe6e41a41d59986469152eeb1c9cb5345dc5 Mon Sep 17 00:00:00 2001 From: Hleb Valoshka <375gnu@gmail.com> Date: Wed, 23 Oct 2019 16:42:56 +0300 Subject: [PATCH 03/14] wip --- src/celplugin/plugin.cpp | 5 +++++ src/celplugin/plugin.h | 1 + 2 files changed, 6 insertions(+) diff --git a/src/celplugin/plugin.cpp b/src/celplugin/plugin.cpp index 0976d1dd92..7fcec39f89 100644 --- a/src/celplugin/plugin.cpp +++ b/src/celplugin/plugin.cpp @@ -92,6 +92,11 @@ void* Plugin::loadSym(const char* fn) const #endif } +bool Plugin::isSupportedVersion() const +{ + return getPluginInfo()->APIVersion == 0x0107; +} + bool Plugin::createScriptEnvironment(CelestiaCore *appCore, const CelestiaConfig *config, ProgressNotifier *progressNotifier) const { auto fn = m_func.createScriptEnvironment; diff --git a/src/celplugin/plugin.h b/src/celplugin/plugin.h index af3336d785..1e5e7d46bc 100644 --- a/src/celplugin/plugin.h +++ b/src/celplugin/plugin.h @@ -70,6 +70,7 @@ class Plugin PluginType getType() const { return m_type; } static Plugin* load(const fs::path&); + bool isSupportedVersion() const; // pointers to plugin functions /// scripting support From 68d26853f8650fce2753f6560430990f79cad44e Mon Sep 17 00:00:00 2001 From: Hleb Valoshka <375gnu@gmail.com> Date: Wed, 23 Oct 2019 17:32:09 +0300 Subject: [PATCH 04/14] wip --- src/celplugin/plugin.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/celplugin/plugin.cpp b/src/celplugin/plugin.cpp index 7fcec39f89..176900c143 100644 --- a/src/celplugin/plugin.cpp +++ b/src/celplugin/plugin.cpp @@ -75,6 +75,11 @@ Plugin* Plugin::load(const fs::path& path) return nullptr; } p.m_type = pi->Type; + if (!p.isSupportedVersion()) + { + fmt::print(std::cerr, "unsupported plugin API version {:#06x}\n", pi->APIVersion); + return nullptr; + } return new Plugin(std::move(p)); } From 2218699e1789f57f0ad78429c02c011eaff1d730 Mon Sep 17 00:00:00 2001 From: Hleb Valoshka <375gnu@gmail.com> Date: Wed, 23 Oct 2019 18:12:27 +0300 Subject: [PATCH 05/14] wip --- src/celplugin/host.cpp | 21 ++++++++--------- src/celplugin/myplug.cpp | 3 ++- src/celplugin/plugin.cpp | 40 ++++++++++++++++++++------------- src/celplugin/plugin.h | 14 +++++++----- src/celplugin/pluginmanager.cpp | 4 ++-- src/celplugin/pluginmanager.h | 4 ++-- 6 files changed, 50 insertions(+), 36 deletions(-) diff --git a/src/celplugin/host.cpp b/src/celplugin/host.cpp index 66845d29c9..363c561f03 100644 --- a/src/celplugin/host.cpp +++ b/src/celplugin/host.cpp @@ -13,24 +13,25 @@ int main() PluginManager pm; pm.searchDirectory() = cwd; - Plugin* p = pm.loadByName("myplug"); + const Plugin* p = pm.loadByName("myplug"); if (p == nullptr) { std::cout << "load failed\n"; return 1; } - PluginInfo *pi = p->getPluginInfo(); - if (pi == nullptr) - { - std::cout << "no data provided\n"; - return 2; - } - + const PluginInfo *pi = p->getPluginInfo(); fmt::printf("APIVersion = %hx, Type = %hu, Implementation Defined Data = %p\n", pi->APIVersion, pi->Type, fmt::ptr(pi->IDDPtr)); - void (*myfn)() = reinterpret_cast(pi->IDDPtr); - (*myfn)(); + if (p->getType() == Script) + { + fmt::printf("%s\n", p->getScriptLanguage()); + } + else + { + void (*myfn)() = reinterpret_cast(pi->IDDPtr); + (*myfn)(); + } return 0; } diff --git a/src/celplugin/myplug.cpp b/src/celplugin/myplug.cpp index 0cc97f4690..32016f899b 100644 --- a/src/celplugin/myplug.cpp +++ b/src/celplugin/myplug.cpp @@ -10,6 +10,7 @@ static void myfn() CELESTIA_PLUGIN_ENTRYPOINT() { - static PluginInfo pinf = { 0x0107, 0, Nothing, 0, reinterpret_cast(&myfn) }; +// static PluginInfo pinf = { 0x0108, 0, Nothing, 0, reinterpret_cast(&myfn) }; + static PluginInfo pinf = { 0x0107, 0, Script, 0, "LUA" }; return &pinf; } diff --git a/src/celplugin/plugin.cpp b/src/celplugin/plugin.cpp index 176900c143..fa70b13b49 100644 --- a/src/celplugin/plugin.cpp +++ b/src/celplugin/plugin.cpp @@ -8,6 +8,7 @@ namespace celestia { namespace plugin { + Plugin::~Plugin() { if (m_handle != nullptr) @@ -27,12 +28,18 @@ Plugin::Plugin(Plugin &&other) m_regfn = other.m_regfn; other.m_regfn = nullptr; + m_pluginInfo = other.m_pluginInfo; m_func = other.m_func; } -PluginInfo* Plugin::getPluginInfo() const +bool Plugin::isSupportedVersion() const +{ + return m_pluginInfo->APIVersion == 0x0107; +} + +void Plugin::loadPluginInfo() { - return (*m_regfn)(); + m_pluginInfo = (*m_regfn)(); } Plugin* Plugin::load(const fs::path& path) @@ -60,8 +67,20 @@ Plugin* Plugin::load(const fs::path& path) return nullptr; p.m_regfn = reinterpret_cast(ptr); - PluginInfo *pi = p.getPluginInfo(); - switch (pi->Type) + p.loadPluginInfo(); + if (p.m_pluginInfo == nullptr) + { + fmt::print(std::cerr, "plugin doesn't have PluginInfo\n"); + return nullptr; + } + + if (!p.isSupportedVersion()) + { + fmt::print(std::cerr, "unsupported plugin API version {:#06x}\n", p.m_pluginInfo->APIVersion); + return nullptr; + } + + switch (p.getType()) { case Nothing: break; @@ -71,13 +90,7 @@ Plugin* Plugin::load(const fs::path& path) p.m_func.createScriptEnvironment = reinterpret_cast(ptr); break; default: - fmt::print(std::cerr, "unknown plugin type {} ({})\n", pi->Type, path); - return nullptr; - } - p.m_type = pi->Type; - if (!p.isSupportedVersion()) - { - fmt::print(std::cerr, "unsupported plugin API version {:#06x}\n", pi->APIVersion); + fmt::print(std::cerr, "unknown plugin type {} ({})\n", p.getType(), path); return nullptr; } @@ -97,11 +110,6 @@ void* Plugin::loadSym(const char* fn) const #endif } -bool Plugin::isSupportedVersion() const -{ - return getPluginInfo()->APIVersion == 0x0107; -} - bool Plugin::createScriptEnvironment(CelestiaCore *appCore, const CelestiaConfig *config, ProgressNotifier *progressNotifier) const { auto fn = m_func.createScriptEnvironment; diff --git a/src/celplugin/plugin.h b/src/celplugin/plugin.h index 1e5e7d46bc..3874185fe2 100644 --- a/src/celplugin/plugin.h +++ b/src/celplugin/plugin.h @@ -51,7 +51,7 @@ struct PluginInfo uint16_t Reserved1; PluginType Type; uint32_t Reserved2; - void *IDDPtr; // IDD == Implementation Defined Data + const void *IDDPtr; // IDD == Implementation Defined Data }; #pragma pack(pop) @@ -65,12 +65,15 @@ class Plugin Plugin& operator=(const Plugin&) = delete; Plugin& operator=(Plugin&&) = default; - PluginInfo* getPluginInfo() const; void* loadSym(const char*) const; - PluginType getType() const { return m_type; } - static Plugin* load(const fs::path&); + const PluginInfo* getPluginInfo() const { return m_pluginInfo; } bool isSupportedVersion() const; + PluginType getType() const { return m_pluginInfo->Type; } + + static Plugin* load(const fs::path&); + + const char* getScriptLanguage() const { return reinterpret_cast(m_pluginInfo->IDDPtr); } // pointers to plugin functions /// scripting support @@ -89,6 +92,7 @@ class Plugin Renderer* createRenderer() const; private: + void loadPluginInfo(); #ifdef _WIN32 HMODULE m_handle { nullptr }; @@ -96,7 +100,7 @@ class Plugin void *m_handle { nullptr }; #endif - PluginType m_type { Nothing }; + PluginInfo *m_pluginInfo; typedef PluginInfo*(RegisterFunc)(); RegisterFunc *m_regfn; diff --git a/src/celplugin/pluginmanager.cpp b/src/celplugin/pluginmanager.cpp index bf4a1e8fde..6e70f61e9d 100644 --- a/src/celplugin/pluginmanager.cpp +++ b/src/celplugin/pluginmanager.cpp @@ -15,12 +15,12 @@ PluginManager::~PluginManager() delete p; } -Plugin* PluginManager::loadByPath(const fs::path &path) +const Plugin* PluginManager::loadByPath(const fs::path &path) { return Plugin::load(path); } -Plugin* PluginManager::loadByName(const std::string &name) +const Plugin* PluginManager::loadByName(const std::string &name) { #if defined(_WIN32) return Plugin::load(m_directory / fmt::sprintf("%s.dll", name)); diff --git a/src/celplugin/pluginmanager.h b/src/celplugin/pluginmanager.h index 598f6bb72f..966f68a4e2 100644 --- a/src/celplugin/pluginmanager.h +++ b/src/celplugin/pluginmanager.h @@ -15,8 +15,8 @@ class PluginManager { public: ~PluginManager(); - Plugin* loadByPath(const fs::path&); - Plugin* loadByName(const std::string &name); + const Plugin* loadByPath(const fs::path&); + const Plugin* loadByName(const std::string &name); fs::path& searchDirectory() { return m_directory; } const fs::path searchDirectory() const { return m_directory; } From fe275eaca8ac7bfa13b7e1845bcf344552c56114 Mon Sep 17 00:00:00 2001 From: Hleb Valoshka <375gnu@gmail.com> Date: Wed, 23 Oct 2019 22:33:28 +0300 Subject: [PATCH 06/14] wip --- src/celplugin/CMakeLists.txt | 2 +- src/celplugin/host.cpp | 12 +++--- src/celplugin/myplug.cpp | 5 +-- src/celplugin/plugin-common.h | 73 +++++++++++++++++++++++++++++++++ src/celplugin/plugin.cpp | 15 ++++++- src/celplugin/plugin.h | 51 ++++++++--------------- src/celplugin/pluginmanager.cpp | 46 ++++++++++++++++++--- src/celplugin/pluginmanager.h | 33 ++++++++++++--- 8 files changed, 182 insertions(+), 55 deletions(-) create mode 100644 src/celplugin/plugin-common.h diff --git a/src/celplugin/CMakeLists.txt b/src/celplugin/CMakeLists.txt index 4f974b6183..50713377d3 100644 --- a/src/celplugin/CMakeLists.txt +++ b/src/celplugin/CMakeLists.txt @@ -2,7 +2,7 @@ cmake_minimum_required(VERSION 3.7) add_compile_options(-fPIC) add_compile_options(-g) find_package(fmt 4.0.0 CONFIG REQUIRED) -add_executable(plugintest host.cpp plugin.cpp pluginmanager.cpp ../celcompat/fs.cpp) +add_executable(plugintest host.cpp plugin.cpp pluginmanager.cpp ../celcompat/fs.cpp ../celutil/util.cpp) include_directories(. ..) target_link_libraries(plugintest fmt::fmt dl) add_library(myplug MODULE myplug.cpp) diff --git a/src/celplugin/host.cpp b/src/celplugin/host.cpp index 363c561f03..58584d1aa9 100644 --- a/src/celplugin/host.cpp +++ b/src/celplugin/host.cpp @@ -1,3 +1,4 @@ +#define PUBLIC_GET_INFO #include #include "plugin.h" #include "pluginmanager.h" @@ -12,7 +13,7 @@ int main() getcwd(cwd, 255); PluginManager pm; - pm.searchDirectory() = cwd; + pm.setSearchDirectory(cwd); const Plugin* p = pm.loadByName("myplug"); if (p == nullptr) { @@ -21,15 +22,16 @@ int main() } const PluginInfo *pi = p->getPluginInfo(); - fmt::printf("APIVersion = %hx, Type = %hu, Implementation Defined Data = %p\n", pi->APIVersion, pi->Type, fmt::ptr(pi->IDDPtr)); + fmt::printf("APIVersion = %hx, Type = %hu, ID = %p\n", pi->APIVersion, pi->Type, fmt::ptr(pi->ID)); - if (p->getType() == Script) + if (p->getType() == Scripting) { - fmt::printf("%s\n", p->getScriptLanguage()); + fmt::printf("%s\n", p->getScriptLanguage()); + fmt::printf("%p %p\n", fmt::ptr(p), fmt::ptr(pm.getScriptPlugin("lUa"))); } else { - void (*myfn)() = reinterpret_cast(pi->IDDPtr); + void (*myfn)() = reinterpret_cast(pi->ID); (*myfn)(); } diff --git a/src/celplugin/myplug.cpp b/src/celplugin/myplug.cpp index 32016f899b..3dccecf964 100644 --- a/src/celplugin/myplug.cpp +++ b/src/celplugin/myplug.cpp @@ -1,5 +1,5 @@ #include -#include "plugin.h" +#include "plugin-common.h" using namespace celestia::plugin; @@ -10,7 +10,6 @@ static void myfn() CELESTIA_PLUGIN_ENTRYPOINT() { -// static PluginInfo pinf = { 0x0108, 0, Nothing, 0, reinterpret_cast(&myfn) }; - static PluginInfo pinf = { 0x0107, 0, Script, 0, "LUA" }; + static PluginInfo pinf(Scripting, "LUA"); return &pinf; } diff --git a/src/celplugin/plugin-common.h b/src/celplugin/plugin-common.h new file mode 100644 index 0000000000..d186608d2c --- /dev/null +++ b/src/celplugin/plugin-common.h @@ -0,0 +1,73 @@ +// plugin-common.h +// +// Copyright (C) 2019, Celestia Development Team +// +// Common definitions for application and module sides +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. + +#pragma once + +#include + +#define CELESTIA_PLUGIN_ENTRY_NAME get_celestia_plugin_info +#define CELESTIA_PLUGIN_ENTRY_NAME_STR "get_celestia_plugin_info" + +#ifdef _WIN32 +#define CELESTIA_PLUGIN_EXPORTABLE extern "C" __declspec(dllexport) +#else +#define CELESTIA_PLUGIN_EXPORTABLE extern "C" +#endif + +#define CELESTIA_PLUGIN_ENTRYPOINT CELESTIA_PLUGIN_EXPORTABLE PluginInfo* CELESTIA_PLUGIN_ENTRY_NAME + +namespace celestia +{ +namespace plugin +{ + +constexpr const uint16_t CurrentAPIVersion = 0x0107; + +enum PluginType : uint32_t +{ + TestPlugin = 0, + Scripting = 0x0001, + Rendering = 0x0002, + AudioInput = 0x0010, + AudioOutput = 0x0020, + VideoInput = 0x0040, + VideoOutput = 0x0080, +}; + +#pragma pack(push,1) +struct PluginInfo +{ + PluginInfo() = delete; + ~PluginInfo() = default; + PluginInfo(const PluginInfo&) = default; + PluginInfo(PluginInfo&&) = default; + PluginInfo& operator=(const PluginInfo&) = default; + PluginInfo& operator=(PluginInfo&&) = default; + + PluginInfo(uint16_t _APIVersion, PluginType _Type, const char *_ID) : + APIVersion(_APIVersion), + Type(_Type), + ID(_ID) + {} + PluginInfo(PluginType _Type, const char *_ID) : + PluginInfo(CurrentAPIVersion, _Type, _ID) + {} + + uint16_t APIVersion; + uint16_t Reserved1; + PluginType Type; + uint32_t Reserved2; + const char *ID; +}; +#pragma pack(pop) + +} +} diff --git a/src/celplugin/plugin.cpp b/src/celplugin/plugin.cpp index fa70b13b49..b1424c2a46 100644 --- a/src/celplugin/plugin.cpp +++ b/src/celplugin/plugin.cpp @@ -1,3 +1,14 @@ +// plugin.cpp +// +// Copyright (C) 2019, Celestia Development Team +// +// Plugin application side implementation +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. + #include #include "plugin.h" #ifndef _WIN32 @@ -82,9 +93,9 @@ Plugin* Plugin::load(const fs::path& path) switch (p.getType()) { - case Nothing: + case TestPlugin: break; - case Script: + case Scripting: ptr = p.loadSym("CreateScriptEnvironment"); if (ptr != nullptr) p.m_func.createScriptEnvironment = reinterpret_cast(ptr); diff --git a/src/celplugin/plugin.h b/src/celplugin/plugin.h index 3874185fe2..920da681ab 100644 --- a/src/celplugin/plugin.h +++ b/src/celplugin/plugin.h @@ -1,23 +1,23 @@ +// plugin.h +// +// Copyright (C) 2019, Celestia Development Team +// +// Plugin class +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. + #pragma once #include #include -#include #include #ifdef _WIN32 #include #endif - -#define CELESTIA_PLUGIN_ENTRY_NAME get_celestia_plugin_info -#define CELESTIA_PLUGIN_ENTRY_NAME_STR "get_celestia_plugin_info" - -#ifdef _WIN32 -#define CELESTIA_PLUGIN_EXPORTABLE extern "C" __declspec(dllexport) -#else -#define CELESTIA_PLUGIN_EXPORTABLE extern "C" -#endif - -#define CELESTIA_PLUGIN_ENTRYPOINT CELESTIA_PLUGIN_EXPORTABLE PluginInfo* CELESTIA_PLUGIN_ENTRY_NAME +#include "plugin-common.h" class CelestiaCore; class CelestiaConfig; @@ -35,26 +35,6 @@ namespace plugin class PluginManager; -enum PluginType : uint32_t -{ - Nothing = 0, - Script = 0x0001, - Audio = 0x0002, - Video = 0x0004, - Render = 0x0010, -}; - -#pragma pack(push,1) -struct PluginInfo -{ - uint16_t APIVersion; - uint16_t Reserved1; - PluginType Type; - uint32_t Reserved2; - const void *IDDPtr; // IDD == Implementation Defined Data -}; -#pragma pack(pop) - class Plugin { public: @@ -67,13 +47,15 @@ class Plugin void* loadSym(const char*) const; +#ifdef PUBLIC_GET_INFO const PluginInfo* getPluginInfo() const { return m_pluginInfo; } +#endif bool isSupportedVersion() const; PluginType getType() const { return m_pluginInfo->Type; } static Plugin* load(const fs::path&); - const char* getScriptLanguage() const { return reinterpret_cast(m_pluginInfo->IDDPtr); } + const char* getScriptLanguage() const { return m_pluginInfo->ID; } // pointers to plugin functions /// scripting support @@ -93,6 +75,9 @@ class Plugin private: void loadPluginInfo(); +#ifndef PUBLIC_GET_INFO + const PluginInfo* getPluginInfo() const { return m_pluginInfo; } +#endif #ifdef _WIN32 HMODULE m_handle { nullptr }; diff --git a/src/celplugin/pluginmanager.cpp b/src/celplugin/pluginmanager.cpp index 6e70f61e9d..876b1fa6db 100644 --- a/src/celplugin/pluginmanager.cpp +++ b/src/celplugin/pluginmanager.cpp @@ -1,35 +1,69 @@ +// pluginmanager.cpp +// +// Copyright (C) 2019, Celestia Development Team +// +// Plugin Manager implementation +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. + #include -#include "plugin.h" -#include "pluginmanager.h" +#include #ifndef _WIN32 #include #endif +#include +#include "plugin.h" +#include "pluginmanager.h" namespace celestia { namespace plugin { + PluginManager::~PluginManager() { for (auto p : m_plugins) delete p; } +void PluginManager::setSearchDirectory(const fs::path &directory) +{ + m_directory = directory; +} + +const fs::path& PluginManager::getSearchDirectory() const +{ + return m_directory; +} + const Plugin* PluginManager::loadByPath(const fs::path &path) { - return Plugin::load(path); + auto p = Plugin::load(path); + if (p != nullptr) + m_plugins.push_back(p); + return p; } const Plugin* PluginManager::loadByName(const std::string &name) { #if defined(_WIN32) - return Plugin::load(m_directory / fmt::sprintf("%s.dll", name)); + return PluginManager::loadByPath(m_directory / fmt::sprintf("%s.dll", name)); #elif defined(__APPLE__) - return nullptr; + return nullptr; // FIXME #else - return Plugin::load(m_directory / fmt::sprintf("lib%s.so", name)); + return PluginManager::loadByPath(m_directory / fmt::sprintf("lib%s.so", name)); #endif } +const Plugin* PluginManager::getScriptPlugin(const std::string &lang) const +{ + auto cmp = [&lang](const Plugin* p){ return compareIgnoringCase(p->getScriptLanguage(), lang) == 0; }; + auto it = std::find_if(m_plugins.begin(), m_plugins.end(), cmp); + return it != m_plugins.end() ? *it : nullptr; +} + } } diff --git a/src/celplugin/pluginmanager.h b/src/celplugin/pluginmanager.h index 966f68a4e2..1cae2397ca 100644 --- a/src/celplugin/pluginmanager.h +++ b/src/celplugin/pluginmanager.h @@ -1,27 +1,50 @@ +// pluginmanager.h +// +// Copyright (C) 2019, Celestia Development Team +// +// Plugin Manager class +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. + #pragma once #include #include #include - namespace celestia { namespace plugin { + class Plugin; +// +// PluginManager is an owner of all plugins +// class PluginManager { public: + PluginManager() = default; ~PluginManager(); + PluginManager(const PluginManager&) = delete; + PluginManager(PluginManager&&) = delete; + PluginManager& operator=(const PluginManager&) = delete; + PluginManager& operator=(PluginManager&&) = delete; + const Plugin* loadByPath(const fs::path&); - const Plugin* loadByName(const std::string &name); - fs::path& searchDirectory() { return m_directory; } - const fs::path searchDirectory() const { return m_directory; } + const Plugin* loadByName(const std::string&); + + void setSearchDirectory(const fs::path&); + const fs::path& getSearchDirectory() const; + + const Plugin* getScriptPlugin(const std::string&) const; private: - std::vector m_plugins; + std::vector m_plugins; fs::path m_directory; }; // PluginManager } From deb7f42b252370772148e28638575739e7a8fe86 Mon Sep 17 00:00:00 2001 From: Hleb Valoshka <375gnu@gmail.com> Date: Wed, 23 Oct 2019 23:28:07 +0300 Subject: [PATCH 07/14] wip --- src/celplugin/CMakeLists.txt | 20 ++++++++++++++++---- src/celplugin/host.cpp | 13 +++++++++++-- 2 files changed, 27 insertions(+), 6 deletions(-) diff --git a/src/celplugin/CMakeLists.txt b/src/celplugin/CMakeLists.txt index 50713377d3..18cad9f07f 100644 --- a/src/celplugin/CMakeLists.txt +++ b/src/celplugin/CMakeLists.txt @@ -1,8 +1,20 @@ cmake_minimum_required(VERSION 3.7) -add_compile_options(-fPIC) -add_compile_options(-g) +if (NOT WIN32) + add_compile_options(-fPIC) + add_compile_options(-g) +else() + add_definitions( + -D_CRT_SECURE_NO_WARNINGS + -D_SCL_SECURE_NO_WARNINGS + -DNOMINMAX + -DWIN32_LEAN_AND_MEAN + ) +endif() find_package(fmt 4.0.0 CONFIG REQUIRED) -add_executable(plugintest host.cpp plugin.cpp pluginmanager.cpp ../celcompat/fs.cpp ../celutil/util.cpp) +if (WIN32) + set(WINUTIL ../celutil/winutil.cpp) +endif() +add_executable(plugintest host.cpp plugin.cpp pluginmanager.cpp ../celcompat/fs.cpp ../celutil/util.cpp ${WINUTIL}) include_directories(. ..) -target_link_libraries(plugintest fmt::fmt dl) +target_link_libraries(plugintest fmt::fmt ${CMAKE_DL_LIBS}) add_library(myplug MODULE myplug.cpp) diff --git a/src/celplugin/host.cpp b/src/celplugin/host.cpp index 58584d1aa9..dbcba13fea 100644 --- a/src/celplugin/host.cpp +++ b/src/celplugin/host.cpp @@ -3,14 +3,23 @@ #include "plugin.h" #include "pluginmanager.h" #include +#ifdef _WIN32 +#include // _getcwd +#else #include // getcwd +#endif using namespace celestia::plugin; int main() { - char cwd[256]; - getcwd(cwd, 255); +#ifdef _WIN32 + wchar_t *cwd = _wgetcwd(nullptr, 0); + if (cwd == nullptr) cwd = L""; +#else + char *cwd = getcwd(nullptr, 0); + if (cwd == nullptr) cwd = ""; +#endif PluginManager pm; pm.setSearchDirectory(cwd); From 57d344da425a4e87c26db920f82db7ab20ad52b1 Mon Sep 17 00:00:00 2001 From: Hleb Valoshka <375gnu@gmail.com> Date: Thu, 24 Oct 2019 15:43:51 +0300 Subject: [PATCH 08/14] [skip ci] apple --- src/celplugin/CMakeLists.txt | 2 +- src/celplugin/pluginmanager.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/celplugin/CMakeLists.txt b/src/celplugin/CMakeLists.txt index 18cad9f07f..292e979e74 100644 --- a/src/celplugin/CMakeLists.txt +++ b/src/celplugin/CMakeLists.txt @@ -17,4 +17,4 @@ endif() add_executable(plugintest host.cpp plugin.cpp pluginmanager.cpp ../celcompat/fs.cpp ../celutil/util.cpp ${WINUTIL}) include_directories(. ..) target_link_libraries(plugintest fmt::fmt ${CMAKE_DL_LIBS}) -add_library(myplug MODULE myplug.cpp) +add_library(myplug SHARED myplug.cpp) diff --git a/src/celplugin/pluginmanager.cpp b/src/celplugin/pluginmanager.cpp index 876b1fa6db..6275e45235 100644 --- a/src/celplugin/pluginmanager.cpp +++ b/src/celplugin/pluginmanager.cpp @@ -52,7 +52,7 @@ const Plugin* PluginManager::loadByName(const std::string &name) #if defined(_WIN32) return PluginManager::loadByPath(m_directory / fmt::sprintf("%s.dll", name)); #elif defined(__APPLE__) - return nullptr; // FIXME + return PluginManager::loadByPath(m_directory / fmt::sprintf("lib%s.dylib", name)); #else return PluginManager::loadByPath(m_directory / fmt::sprintf("lib%s.so", name)); #endif From cd9e49c94938b8264df5f51c0e17c7aa086abd82 Mon Sep 17 00:00:00 2001 From: Hleb Valoshka <375gnu@gmail.com> Date: Thu, 24 Oct 2019 16:39:51 +0300 Subject: [PATCH 09/14] [skip ci] wip --- src/CMakeLists.txt | 1 + src/celengine/parseobject.cpp | 2 -- src/celephem/CMakeLists.txt | 12 ------- src/celestia/CMakeLists.txt | 2 +- src/celestia/celestiacore.cpp | 5 --- src/celplugin/CMakeLists.txt | 30 ++++++---------- src/celplugin/config.h | 0 src/celplugin/plugin.cpp | 9 ++--- src/celplugin/plugin.h | 12 +++---- src/celscript/lua/CMakeLists.txt | 8 ++++- src/celscript/lua/luascript.cpp | 2 +- .../lua}/scriptobject.cpp | 0 .../lua}/scriptobject.h | 0 .../lua}/scriptorbit.cpp | 34 +++++++++++++++++++ src/{celephem => celscript/lua}/scriptorbit.h | 2 +- .../lua}/scriptrotation.cpp | 0 .../lua}/scriptrotation.h | 2 +- 17 files changed, 67 insertions(+), 54 deletions(-) delete mode 100644 src/celplugin/config.h rename src/{celephem => celscript/lua}/scriptobject.cpp (100%) rename src/{celephem => celscript/lua}/scriptobject.h (100%) rename src/{celephem => celscript/lua}/scriptorbit.cpp (89%) rename src/{celephem => celscript/lua}/scriptorbit.h (97%) rename src/{celephem => celscript/lua}/scriptrotation.cpp (100%) rename src/{celephem => celscript/lua}/scriptrotation.h (97%) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 2be6428497..e74607f05c 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -17,6 +17,7 @@ add_subdirectory(celscript) # These compiled objects are merged with the celengine library add_subdirectory(celephem) add_subdirectory(celcompat) +add_subdirectory(celplugin) if (ENABLE_TOOLS) add_subdirectory(tools) diff --git a/src/celengine/parseobject.cpp b/src/celengine/parseobject.cpp index 2ce335047a..99186d34c9 100644 --- a/src/celengine/parseobject.cpp +++ b/src/celengine/parseobject.cpp @@ -22,8 +22,6 @@ #include #include #endif -#include -#include #include #include #include diff --git a/src/celephem/CMakeLists.txt b/src/celephem/CMakeLists.txt index 315867901b..d36927d43b 100644 --- a/src/celephem/CMakeLists.txt +++ b/src/celephem/CMakeLists.txt @@ -32,18 +32,6 @@ if(ENABLE_SPICE) ) endif() - -if(ENABLE_CELX) - list(APPEND CELEPHEM_SOURCES - scriptobject.cpp - scriptobject.h - scriptorbit.cpp - scriptorbit.h - scriptrotation.cpp - scriptrotation.h - ) -endif() - # These object files are merged in the celegine library add_library(celephem OBJECT ${CELEPHEM_SOURCES}) diff --git a/src/celestia/CMakeLists.txt b/src/celestia/CMakeLists.txt index ad0f1e2b81..773d78af2f 100644 --- a/src/celestia/CMakeLists.txt +++ b/src/celestia/CMakeLists.txt @@ -37,7 +37,7 @@ endif() add_library(celestia STATIC ${CELESTIA_SOURCES} $ $ - $) + $) #[[ add_library(celestia SHARED ${CELESTIA_SOURCES}) diff --git a/src/celestia/celestiacore.cpp b/src/celestia/celestiacore.cpp index 6238c0c0d9..c78252a1c1 100644 --- a/src/celestia/celestiacore.cpp +++ b/src/celestia/celestiacore.cpp @@ -54,11 +54,6 @@ #include #include #include - -#ifdef CELX -#include -#endif - #include "imagecapture.h" // TODO: proper gettext diff --git a/src/celplugin/CMakeLists.txt b/src/celplugin/CMakeLists.txt index 292e979e74..a9bafb92ce 100644 --- a/src/celplugin/CMakeLists.txt +++ b/src/celplugin/CMakeLists.txt @@ -1,20 +1,10 @@ -cmake_minimum_required(VERSION 3.7) -if (NOT WIN32) - add_compile_options(-fPIC) - add_compile_options(-g) -else() - add_definitions( - -D_CRT_SECURE_NO_WARNINGS - -D_SCL_SECURE_NO_WARNINGS - -DNOMINMAX - -DWIN32_LEAN_AND_MEAN - ) -endif() -find_package(fmt 4.0.0 CONFIG REQUIRED) -if (WIN32) - set(WINUTIL ../celutil/winutil.cpp) -endif() -add_executable(plugintest host.cpp plugin.cpp pluginmanager.cpp ../celcompat/fs.cpp ../celutil/util.cpp ${WINUTIL}) -include_directories(. ..) -target_link_libraries(plugintest fmt::fmt ${CMAKE_DL_LIBS}) -add_library(myplug SHARED myplug.cpp) +# These object files are merged in the celegine library +set(CELPLUGIN_SOURCES + plugin-common.h + plugin.cpp + plugin.h + pluginmanager.cpp + pluginmanager.h +) +add_library(celplugin OBJECT ${CELPLUGIN_SOURCES}) + diff --git a/src/celplugin/config.h b/src/celplugin/config.h deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/src/celplugin/plugin.cpp b/src/celplugin/plugin.cpp index b1424c2a46..07a9341dbc 100644 --- a/src/celplugin/plugin.cpp +++ b/src/celplugin/plugin.cpp @@ -9,6 +9,7 @@ // as published by the Free Software Foundation; either version 2 // of the License, or (at your option) any later version. +#include #include #include "plugin.h" #ifndef _WIN32 @@ -133,15 +134,15 @@ IScript* Plugin::createScript(CelestiaCore *appCore) const return fn == nullptr ? nullptr : (*fn)(appCore); } -RotationModel* Plugin::createScritedRotation(const std::string& moduleName, const std::string& funcName, Hash* parameters) const +RotationModel* Plugin::createScriptedRotation(const std::string& moduleName, const std::string& funcName, Hash* parameters) const { - auto fn = m_func.createScritedRotation; + auto fn = m_func.createScriptedRotation; return fn == nullptr ? nullptr : (*fn)(moduleName, funcName, parameters); } -CachingOrbit* Plugin::createScritedOrbit(const std::string& moduleName, const std::string& funcName, Hash* parameters) const +CachingOrbit* Plugin::createScriptedOrbit(const std::string& moduleName, const std::string& funcName, Hash* parameters) const { - auto fn = m_func.createScritedOrbit; + auto fn = m_func.createScriptedOrbit; return fn == nullptr ? nullptr : (*fn)(moduleName, funcName, parameters); } diff --git a/src/celplugin/plugin.h b/src/celplugin/plugin.h index 920da681ab..4b76825c8a 100644 --- a/src/celplugin/plugin.h +++ b/src/celplugin/plugin.h @@ -61,16 +61,16 @@ class Plugin /// scripting support typedef bool(CreateScriptEnvironmentFunc)(CelestiaCore*, const CelestiaConfig*, ProgressNotifier*); typedef IScript*(CreateScriptFunc)(CelestiaCore*); - typedef RotationModel*(CreateScritedRotationFunc)(const std::string&, const std::string&, Hash*); - typedef CachingOrbit*(CreateScritedOrbitFunc)(const std::string&, const std::string&, Hash*); + typedef RotationModel*(CreateScriptedRotationFunc)(const std::string&, const std::string&, Hash*); + typedef CachingOrbit*(CreateScriptedOrbitFunc)(const std::string&, const std::string&, Hash*); /// renderer support typedef Renderer*(CreateRendererFunc)(); bool createScriptEnvironment(CelestiaCore *appCore, const CelestiaConfig *config, ProgressNotifier *progressNotifier) const; IScript* createScript(CelestiaCore *appCore) const; - RotationModel* createScritedRotation(const std::string& moduleName, const std::string& funcName, Hash* parameters) const; - CachingOrbit* createScritedOrbit(const std::string& moduleName, const std::string& funcName, Hash* parameters) const; + RotationModel* createScriptedRotation(const std::string& moduleName, const std::string& funcName, Hash* parameters) const; + CachingOrbit* createScriptedOrbit(const std::string& moduleName, const std::string& funcName, Hash* parameters) const; Renderer* createRenderer() const; private: @@ -96,8 +96,8 @@ class Plugin { CreateScriptEnvironmentFunc *createScriptEnvironment; CreateScriptFunc *createScript; - CreateScritedRotationFunc *createScritedRotation; - CreateScritedOrbitFunc *createScritedOrbit; + CreateScriptedRotationFunc *createScriptedRotation; + CreateScriptedOrbitFunc *createScriptedOrbit; }; struct { diff --git a/src/celscript/lua/CMakeLists.txt b/src/celscript/lua/CMakeLists.txt index 919824fd40..c691cac2af 100644 --- a/src/celscript/lua/CMakeLists.txt +++ b/src/celscript/lua/CMakeLists.txt @@ -26,6 +26,12 @@ set(CELX_SOURCES celx_vector.h luascript.cpp luascript.h + scriptobject.cpp + scriptobject.h + scriptorbit.cpp + scriptorbit.h + scriptrotation.cpp + scriptrotation.h ) -add_library(celluascript OBJECT ${CELX_SOURCES}) +add_library(celluascript SHARED ${CELX_SOURCES}) diff --git a/src/celscript/lua/luascript.cpp b/src/celscript/lua/luascript.cpp index ee99dbd445..aee232e67c 100644 --- a/src/celscript/lua/luascript.cpp +++ b/src/celscript/lua/luascript.cpp @@ -13,12 +13,12 @@ #include #include #include -#include #include #include #include #include "celx_internal.h" #include "luascript.h" +#include "scriptobject.h" using namespace std; diff --git a/src/celephem/scriptobject.cpp b/src/celscript/lua/scriptobject.cpp similarity index 100% rename from src/celephem/scriptobject.cpp rename to src/celscript/lua/scriptobject.cpp diff --git a/src/celephem/scriptobject.h b/src/celscript/lua/scriptobject.h similarity index 100% rename from src/celephem/scriptobject.h rename to src/celscript/lua/scriptobject.h diff --git a/src/celephem/scriptorbit.cpp b/src/celscript/lua/scriptorbit.cpp similarity index 89% rename from src/celephem/scriptorbit.cpp rename to src/celscript/lua/scriptorbit.cpp index 398c819a0e..83ea2b80f2 100644 --- a/src/celephem/scriptorbit.cpp +++ b/src/celscript/lua/scriptorbit.cpp @@ -17,6 +17,40 @@ using namespace Eigen; using namespace std; +static ScriptedOrbit* +CreateScriptedOrbit(Hash* orbitData, + const fs::path& path) +{ +#if !defined(CELX) + clog << "ScriptedOrbit not usable without scripting support.\n"; + return nullptr; +#else + + // Function name is required + string funcName; + if (!orbitData->getString("Function", funcName)) + { + clog << "Function name missing from script orbit definition.\n"; + return nullptr; + } + + // Module name is optional + string moduleName; + orbitData->getString("Module", moduleName); + + Value* pathValue = new Value(path.string()); + orbitData->addValue("AddonPath", *pathValue); + + ScriptedOrbit* scriptedOrbit = new ScriptedOrbit(); + if (!scriptedOrbit->initialize(moduleName, funcName, orbitData)) + { + delete scriptedOrbit; + scriptedOrbit = nullptr; + } + + return scriptedOrbit; + + /*! Initialize the script orbit. * moduleName is the name of a module that contains the orbit factory diff --git a/src/celephem/scriptorbit.h b/src/celscript/lua/scriptorbit.h similarity index 97% rename from src/celephem/scriptorbit.h rename to src/celscript/lua/scriptorbit.h index 2e656eb9ab..9bc7824f40 100644 --- a/src/celephem/scriptorbit.h +++ b/src/celscript/lua/scriptorbit.h @@ -13,7 +13,7 @@ #define _CELENGINE_SCRIPTORBIT_H_ #include -#include "orbit.h" +#include struct lua_State; diff --git a/src/celephem/scriptrotation.cpp b/src/celscript/lua/scriptrotation.cpp similarity index 100% rename from src/celephem/scriptrotation.cpp rename to src/celscript/lua/scriptrotation.cpp diff --git a/src/celephem/scriptrotation.h b/src/celscript/lua/scriptrotation.h similarity index 97% rename from src/celephem/scriptrotation.h rename to src/celscript/lua/scriptrotation.h index aea449f07b..0a4c4f138b 100644 --- a/src/celephem/scriptrotation.h +++ b/src/celscript/lua/scriptrotation.h @@ -13,7 +13,7 @@ #define _CELENGINE_SCRIPTROTATION_H_ #include -#include "rotation.h" +#include struct lua_State; From 414d7824da10989985f60688b089d696487b537b Mon Sep 17 00:00:00 2001 From: Hleb Valoshka <375gnu@gmail.com> Date: Thu, 24 Oct 2019 17:57:02 +0300 Subject: [PATCH 10/14] [skip ci] wip --- src/celscript/lua/luaplugin.cpp | 44 +++++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) create mode 100644 src/celscript/lua/luaplugin.cpp diff --git a/src/celscript/lua/luaplugin.cpp b/src/celscript/lua/luaplugin.cpp new file mode 100644 index 0000000000..33a84d5862 --- /dev/null +++ b/src/celscript/lua/luaplugin.cpp @@ -0,0 +1,44 @@ +// luaplugin.cpp +// +// Copyright (C) 2019, the Celestia Development Team +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. + +#include +#include "luascript.h" + +class CelestiaCore; +class CelestiaConfig; +class ProgressNotifier; +class Hash; +class CachingOrbit; +class RotationModel; + +CELESTIA_PLUGIN_ENTRYPOINT() +{ + static celestia::plugin::PluginInfo pinf(celestia::plugin::Scripting, "LUA"); + return &pinf; +} + +CELESTIA_PLUGIN_EXPORTABLE bool CreateScriptEnvironment(CelestiaCore *appCore, const CelestiaConfig *config, ProgressNotifier *progressNotifier) +{ + return celestia::scripts::CreateLuaEnvironment(appCore, config, progressNotifier); +} + +CELESTIA_PLUGIN_EXPORTABLE LuaScript* CreateScript(CelestiaCore *appCore) +{ + return +} + +ScriptedModel* CreateScriptedRotation(const std::string& moduleName, const std::string& funcName, Hash* parameters) +{ + return nullptr; +} + +ScriptedOrbit* CreateScriptedOrbit(const std::string& moduleName, const std::string& funcName, Hash* parameters) +{ + return nullptr; +} From 467119918f7025161e0bb8df2489a351bd7def8f Mon Sep 17 00:00:00 2001 From: Hleb Valoshka <375gnu@gmail.com> Date: Fri, 25 Oct 2019 00:06:42 +0300 Subject: [PATCH 11/14] wip --- CMakeLists.txt | 5 +++ src/celengine/parseobject.cpp | 55 ++++++++++++++++++++++++++++--- src/celestia/celestiacore.cpp | 8 +++-- src/celestia/celestiacore.h | 11 ++++++- src/celplugin/plugin-common.h | 2 +- src/celplugin/plugin.cpp | 26 ++++++++------- src/celplugin/plugin.h | 37 +++++++++++++-------- src/celplugin/pluginmanager.cpp | 8 ++--- src/celplugin/pluginmanager.h | 8 ++++- src/celscript/common/script.h | 4 +++ src/celscript/lua/CMakeLists.txt | 1 + src/celscript/lua/luaplugin.cpp | 10 ++++-- src/celscript/lua/scriptorbit.cpp | 34 ------------------- 13 files changed, 134 insertions(+), 75 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index a554ed02f6..3524638d35 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -32,6 +32,7 @@ option(ENABLE_THEORA "Support video capture to OGG Theora? (Default: on)" ON) option(ENABLE_TOOLS "Build different tools? (Default: off)" OFF) option(NATIVE_OSX_APP "Support native OSX paths read data from (Default: off)" OFF) option(FAST_MATH "Build with unsafe fast-math compiller option (Default: off)" OFF) +option(ENABLE_PLUGINS "Build with experimental plugins support (Default: off)" OFF) if(NOT CMAKE_BUILD_TYPE) set(CMAKE_BUILD_TYPE "Release" CACHE STRING "Build type." FORCE) @@ -285,6 +286,10 @@ if(OCTREE_DEBUG) add_definitions(-DOCTREE_DEBUG) endif() +if(ENABLE_PLUGINS) + add_definitions(-DENABLE_PLUGINS) +endif() + include_directories("${CMAKE_SOURCE_DIR}/src" ${CMAKE_BINARY_DIR}) # configure a header file to pass some of the CMake settings diff --git a/src/celengine/parseobject.cpp b/src/celengine/parseobject.cpp index 99186d34c9..b0d6e582b3 100644 --- a/src/celengine/parseobject.cpp +++ b/src/celengine/parseobject.cpp @@ -22,6 +22,13 @@ #include #include #endif +#if defined(ENABLE_PLUGINS) +#include +#include +#else +#include +#include +#endif #include #include #include @@ -628,12 +635,15 @@ CreateSpiceRotation(Hash* rotationData, } #endif - +#if defined(ENABLE_PLUGINS) +static CachingOrbit* +#else static ScriptedOrbit* +#endif CreateScriptedOrbit(Hash* orbitData, const fs::path& path) { -#if !defined(CELX) +#if !defined(CELX) && !defined(ENABLE_PLUGINS) clog << "ScriptedOrbit not usable without scripting support.\n"; return nullptr; #else @@ -646,6 +656,12 @@ CreateScriptedOrbit(Hash* orbitData, return nullptr; } +#if defined(ENABLE_PLUGINS) + // If language name is missing assume Lua to be backward compatible + string language("LUA"); + orbitData->getString("Language", language); +#endif + // Module name is optional string moduleName; orbitData->getString("Module", moduleName); @@ -653,12 +669,23 @@ CreateScriptedOrbit(Hash* orbitData, Value* pathValue = new Value(path.string()); orbitData->addValue("AddonPath", *pathValue); +#if defined(ENABLE_PLUGINS) + auto plugin = pluginManager.getScriptPlugin(language); + if (plugin == nullptr) + { + fmt::print(cerr, "Support for language {} is missing\n", language); + return nullptr; + } + + auto *scriptedOrbit = plugin->createScriptedOrbit(moduleName, funcName, orbitData); +#else ScriptedOrbit* scriptedOrbit = new ScriptedOrbit(); if (!scriptedOrbit->initialize(moduleName, funcName, orbitData)) { delete scriptedOrbit; scriptedOrbit = nullptr; } +#endif return scriptedOrbit; #endif @@ -999,12 +1026,15 @@ CreatePrecessingRotationModel(Hash* rotationData, } } - +#if defined(ENABLE_PLUGINS) +static RotationModel* +#else static ScriptedRotation* +#endif CreateScriptedRotation(Hash* rotationData, const fs::path& path) { -#if !defined(CELX) +#if !defined(CELX) && !defined(ENABLE_PLUGINS) clog << "ScriptedRotation not usable without scripting support.\n"; return nullptr; #else @@ -1017,6 +1047,12 @@ CreateScriptedRotation(Hash* rotationData, return nullptr; } +#if defined(ENABLE_PLUGINS) + // If language name is missing assume Lua to be backward compatible + string language("LUA"); + rotationData->getString("LUA", language); +#endif + // Module name is optional string moduleName; rotationData->getString("Module", moduleName); @@ -1024,12 +1060,23 @@ CreateScriptedRotation(Hash* rotationData, Value* pathValue = new Value(path.string()); rotationData->addValue("AddonPath", *pathValue); +#if defined(ENABLE_PLUGINS) + auto plugin = pluginManager.getScriptPlugin(language); + if (plugin == nullptr) + { + fmt::print(cerr, "Support for language {} is missing\n", language); + return nullptr; + } + + auto *scriptedRotation = plugin->createScriptedRotation(moduleName, funcName, rotationData); +#else ScriptedRotation* scriptedRotation = new ScriptedRotation(); if (!scriptedRotation->initialize(moduleName, funcName, rotationData)) { delete scriptedRotation; scriptedRotation = nullptr; } +#endif return scriptedRotation; #endif diff --git a/src/celestia/celestiacore.cpp b/src/celestia/celestiacore.cpp index c78252a1c1..9975b245e3 100644 --- a/src/celestia/celestiacore.cpp +++ b/src/celestia/celestiacore.cpp @@ -6,7 +6,7 @@ // keyboard events. CelestiaCore then turns those events into calls // to Renderer and Simulation. // -// Copyright (C) 2001-2009, the Celestia Development Team +// Copyright (C) 2001-2019, the Celestia Development Team // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License @@ -54,6 +54,8 @@ #include #include #include +#include +#include #include "imagecapture.h" // TODO: proper gettext @@ -64,6 +66,7 @@ using namespace Eigen; using namespace std; using namespace celmath; using namespace celestia::scripts; +using namespace celestia::plugin; static const int DragThreshold = 3; @@ -142,7 +145,8 @@ CelestiaCore::CelestiaCore() : timer(new Timer()), m_legacyPlugin(make_unique(this)), m_luaPlugin(make_unique(this)), - m_scriptMaps(make_shared()) + m_scriptMaps(make_shared()), + m_pluginManager(make_unique(this)) { for (int i = 0; i < KeyCount; i++) diff --git a/src/celestia/celestiacore.h b/src/celestia/celestiacore.h index fa1307910c..732cd2fc41 100644 --- a/src/celestia/celestiacore.h +++ b/src/celestia/celestiacore.h @@ -39,7 +39,14 @@ class Url; // class CelestiaWatcher; class CelestiaCore; - +namespace celestia +{ +namespace plugin +{ +class PluginManager; +class Plugin; +} +} // class astro::Date; typedef Watcher CelestiaWatcher; @@ -402,6 +409,8 @@ class CelestiaCore // : public Watchable std::unique_ptr m_luaPlugin; std::shared_ptr m_scriptMaps; + std::unique_ptr m_pluginManager; + enum ScriptState { ScriptCompleted, diff --git a/src/celplugin/plugin-common.h b/src/celplugin/plugin-common.h index d186608d2c..d0e6cb1dd9 100644 --- a/src/celplugin/plugin-common.h +++ b/src/celplugin/plugin-common.h @@ -22,7 +22,7 @@ #define CELESTIA_PLUGIN_EXPORTABLE extern "C" #endif -#define CELESTIA_PLUGIN_ENTRYPOINT CELESTIA_PLUGIN_EXPORTABLE PluginInfo* CELESTIA_PLUGIN_ENTRY_NAME +#define CELESTIA_PLUGIN_ENTRYPOINT CELESTIA_PLUGIN_EXPORTABLE celestia::plugin::PluginInfo* CELESTIA_PLUGIN_ENTRY_NAME namespace celestia { diff --git a/src/celplugin/plugin.cpp b/src/celplugin/plugin.cpp index 07a9341dbc..78fd5b932f 100644 --- a/src/celplugin/plugin.cpp +++ b/src/celplugin/plugin.cpp @@ -11,6 +11,7 @@ #include #include +#include #include "plugin.h" #ifndef _WIN32 #include @@ -33,12 +34,12 @@ Plugin::~Plugin() } } -Plugin::Plugin(Plugin &&other) +Plugin::Plugin(Plugin &&other) : + IScriptPlugin(std::forward(other)) { m_handle = other.m_handle; other.m_handle = nullptr; - m_regfn = other.m_regfn; - other.m_regfn = nullptr; + m_appCore = other.m_appCore; m_pluginInfo = other.m_pluginInfo; m_func = other.m_func; @@ -49,14 +50,9 @@ bool Plugin::isSupportedVersion() const return m_pluginInfo->APIVersion == 0x0107; } -void Plugin::loadPluginInfo() +Plugin* Plugin::load(CelestiaCore *appCore, const fs::path& path) { - m_pluginInfo = (*m_regfn)(); -} - -Plugin* Plugin::load(const fs::path& path) -{ - Plugin p; + Plugin p(appCore); #ifdef _WIN32 p.m_handle = ::LoadLibraryW(path.c_str()); @@ -77,9 +73,9 @@ Plugin* Plugin::load(const fs::path& path) void *ptr = p.loadSym(CELESTIA_PLUGIN_ENTRY_NAME_STR); if (ptr == nullptr) return nullptr; - p.m_regfn = reinterpret_cast(ptr); + auto LoadPluginInfo = reinterpret_cast(ptr); + p.m_pluginInfo = (*LoadPluginInfo)(); - p.loadPluginInfo(); if (p.m_pluginInfo == nullptr) { fmt::print(std::cerr, "plugin doesn't have PluginInfo\n"); @@ -146,6 +142,12 @@ CachingOrbit* Plugin::createScriptedOrbit(const std::string& moduleName, const s return fn == nullptr ? nullptr : (*fn)(moduleName, funcName, parameters); } +bool Plugin::isOurFile(const fs::path &filename) const +{ + auto fn = m_func.isOurFile; + return fn == nullptr ? false : (*fn)(filename); +} + Renderer* Plugin::createRenderer() const { auto fn = m_func.createRenderer; diff --git a/src/celplugin/plugin.h b/src/celplugin/plugin.h index 4b76825c8a..3c59d2bda1 100644 --- a/src/celplugin/plugin.h +++ b/src/celplugin/plugin.h @@ -14,6 +14,8 @@ #include #include #include +#include // IScriptPlugin, IScript +#include // Hash #ifdef _WIN32 #include #endif @@ -22,8 +24,6 @@ class CelestiaCore; class CelestiaConfig; class ProgressNotifier; -class IScript; -class Hash; class Renderer; class CachingOrbit; class RotationModel; @@ -33,12 +33,18 @@ namespace celestia namespace plugin { +using scripts::IScript; +using scripts::IScriptPlugin; + class PluginManager; -class Plugin +class Plugin : public IScriptPlugin { public: - Plugin() = default; + Plugin() = delete; + explicit Plugin(CelestiaCore *appCore) : + IScriptPlugin(appCore) + {} ~Plugin(); Plugin(const Plugin&) = delete; Plugin(Plugin&&); @@ -53,7 +59,7 @@ class Plugin bool isSupportedVersion() const; PluginType getType() const { return m_pluginInfo->Type; } - static Plugin* load(const fs::path&); + static Plugin* load(CelestiaCore*, const fs::path&); const char* getScriptLanguage() const { return m_pluginInfo->ID; } @@ -63,18 +69,25 @@ class Plugin typedef IScript*(CreateScriptFunc)(CelestiaCore*); typedef RotationModel*(CreateScriptedRotationFunc)(const std::string&, const std::string&, Hash*); typedef CachingOrbit*(CreateScriptedOrbitFunc)(const std::string&, const std::string&, Hash*); + typedef bool (IsOurFile)(const fs::path&); /// renderer support typedef Renderer*(CreateRendererFunc)(); + + /// scripting support bool createScriptEnvironment(CelestiaCore *appCore, const CelestiaConfig *config, ProgressNotifier *progressNotifier) const; IScript* createScript(CelestiaCore *appCore) const; RotationModel* createScriptedRotation(const std::string& moduleName, const std::string& funcName, Hash* parameters) const; CachingOrbit* createScriptedOrbit(const std::string& moduleName, const std::string& funcName, Hash* parameters) const; + bool isOurFile(const fs::path&) const; + std::unique_ptr loadScript(const fs::path&); + + /// renderer support Renderer* createRenderer() const; private: - void loadPluginInfo(); + typedef PluginInfo*(RegisterFunc)(); #ifndef PUBLIC_GET_INFO const PluginInfo* getPluginInfo() const { return m_pluginInfo; } #endif @@ -84,24 +97,22 @@ class Plugin #else void *m_handle { nullptr }; #endif - + CelestiaCore *m_appCore; PluginInfo *m_pluginInfo; - typedef PluginInfo*(RegisterFunc)(); - RegisterFunc *m_regfn; - union { struct { CreateScriptEnvironmentFunc *createScriptEnvironment; CreateScriptFunc *createScript; - CreateScriptedRotationFunc *createScriptedRotation; - CreateScriptedOrbitFunc *createScriptedOrbit; + CreateScriptedRotationFunc *createScriptedRotation; + CreateScriptedOrbitFunc *createScriptedOrbit; + IsOurFile *isOurFile; }; struct { - CreateRendererFunc *createRenderer; + CreateRendererFunc *createRenderer; }; } m_func; diff --git a/src/celplugin/pluginmanager.cpp b/src/celplugin/pluginmanager.cpp index 6275e45235..a958f9db08 100644 --- a/src/celplugin/pluginmanager.cpp +++ b/src/celplugin/pluginmanager.cpp @@ -41,7 +41,7 @@ const fs::path& PluginManager::getSearchDirectory() const const Plugin* PluginManager::loadByPath(const fs::path &path) { - auto p = Plugin::load(path); + auto p = Plugin::load(m_appCore, path); if (p != nullptr) m_plugins.push_back(p); return p; @@ -50,11 +50,11 @@ const Plugin* PluginManager::loadByPath(const fs::path &path) const Plugin* PluginManager::loadByName(const std::string &name) { #if defined(_WIN32) - return PluginManager::loadByPath(m_directory / fmt::sprintf("%s.dll", name)); + return loadByPath(m_directory / fmt::sprintf("%s.dll", name)); #elif defined(__APPLE__) - return PluginManager::loadByPath(m_directory / fmt::sprintf("lib%s.dylib", name)); + return loadByPath(m_directory / fmt::sprintf("lib%s.dylib", name)); #else - return PluginManager::loadByPath(m_directory / fmt::sprintf("lib%s.so", name)); + return loadByPath(m_directory / fmt::sprintf("lib%s.so", name)); #endif } diff --git a/src/celplugin/pluginmanager.h b/src/celplugin/pluginmanager.h index 1cae2397ca..737acf36c4 100644 --- a/src/celplugin/pluginmanager.h +++ b/src/celplugin/pluginmanager.h @@ -15,6 +15,8 @@ #include #include +class CelestiaCore; + namespace celestia { namespace plugin @@ -28,7 +30,10 @@ class Plugin; class PluginManager { public: - PluginManager() = default; + PluginManager() = delete; + explicit PluginManager(CelestiaCore *appCore) : + m_appCore(appCore) + {} ~PluginManager(); PluginManager(const PluginManager&) = delete; PluginManager(PluginManager&&) = delete; @@ -46,6 +51,7 @@ class PluginManager private: std::vector m_plugins; fs::path m_directory; + CelestiaCore *m_appCore; }; // PluginManager } } diff --git a/src/celscript/common/script.h b/src/celscript/common/script.h index c05f57ff63..384efd8738 100644 --- a/src/celscript/common/script.h +++ b/src/celscript/common/script.h @@ -37,7 +37,11 @@ class IScriptPlugin IScriptPlugin() = delete; IScriptPlugin(CelestiaCore *appcore) : m_appCore(appcore) {}; IScriptPlugin(const IScriptPlugin&) = delete; +#ifdef ENABLE_PLUGINS + IScriptPlugin(IScriptPlugin&&) = default; +#else IScriptPlugin(IScriptPlugin&&) = delete; +#endif IScriptPlugin& operator=(const IScriptPlugin&) = delete; IScriptPlugin& operator=(IScriptPlugin&&) = delete; virtual ~IScriptPlugin() = default; diff --git a/src/celscript/lua/CMakeLists.txt b/src/celscript/lua/CMakeLists.txt index c691cac2af..fee1ed5b94 100644 --- a/src/celscript/lua/CMakeLists.txt +++ b/src/celscript/lua/CMakeLists.txt @@ -24,6 +24,7 @@ set(CELX_SOURCES celx_rotation.h celx_vector.cpp celx_vector.h + luaplugin.cpp luascript.cpp luascript.h scriptobject.cpp diff --git a/src/celscript/lua/luaplugin.cpp b/src/celscript/lua/luaplugin.cpp index 33a84d5862..4b504d6fa2 100644 --- a/src/celscript/lua/luaplugin.cpp +++ b/src/celscript/lua/luaplugin.cpp @@ -8,6 +8,7 @@ // of the License, or (at your option) any later version. #include +#include #include "luascript.h" class CelestiaCore; @@ -17,6 +18,9 @@ class Hash; class CachingOrbit; class RotationModel; +using namespace celestia::plugin; +using namespace celestia::scripts; + CELESTIA_PLUGIN_ENTRYPOINT() { static celestia::plugin::PluginInfo pinf(celestia::plugin::Scripting, "LUA"); @@ -30,15 +34,15 @@ CELESTIA_PLUGIN_EXPORTABLE bool CreateScriptEnvironment(CelestiaCore *appCore, c CELESTIA_PLUGIN_EXPORTABLE LuaScript* CreateScript(CelestiaCore *appCore) { - return + return nullptr; } -ScriptedModel* CreateScriptedRotation(const std::string& moduleName, const std::string& funcName, Hash* parameters) +RotationModel* CreateScriptedRotation(const std::string& moduleName, const std::string& funcName, Hash* parameters) { return nullptr; } -ScriptedOrbit* CreateScriptedOrbit(const std::string& moduleName, const std::string& funcName, Hash* parameters) +CachingOrbit* CreateScriptedOrbit(const std::string& moduleName, const std::string& funcName, Hash* parameters) { return nullptr; } diff --git a/src/celscript/lua/scriptorbit.cpp b/src/celscript/lua/scriptorbit.cpp index 83ea2b80f2..398c819a0e 100644 --- a/src/celscript/lua/scriptorbit.cpp +++ b/src/celscript/lua/scriptorbit.cpp @@ -17,40 +17,6 @@ using namespace Eigen; using namespace std; -static ScriptedOrbit* -CreateScriptedOrbit(Hash* orbitData, - const fs::path& path) -{ -#if !defined(CELX) - clog << "ScriptedOrbit not usable without scripting support.\n"; - return nullptr; -#else - - // Function name is required - string funcName; - if (!orbitData->getString("Function", funcName)) - { - clog << "Function name missing from script orbit definition.\n"; - return nullptr; - } - - // Module name is optional - string moduleName; - orbitData->getString("Module", moduleName); - - Value* pathValue = new Value(path.string()); - orbitData->addValue("AddonPath", *pathValue); - - ScriptedOrbit* scriptedOrbit = new ScriptedOrbit(); - if (!scriptedOrbit->initialize(moduleName, funcName, orbitData)) - { - delete scriptedOrbit; - scriptedOrbit = nullptr; - } - - return scriptedOrbit; - - /*! Initialize the script orbit. * moduleName is the name of a module that contains the orbit factory From 3fb033f92344236d59fafd58f3e49bd932925cb3 Mon Sep 17 00:00:00 2001 From: Hleb Valoshka <375gnu@gmail.com> Date: Fri, 25 Oct 2019 00:30:44 +0300 Subject: [PATCH 12/14] [skip ci] wip --- src/celscript/lua/luascript.h | 1 + 1 file changed, 1 insertion(+) diff --git a/src/celscript/lua/luascript.h b/src/celscript/lua/luascript.h index 308d477d25..59eb343cc1 100644 --- a/src/celscript/lua/luascript.h +++ b/src/celscript/lua/luascript.h @@ -11,6 +11,7 @@ #include #include +#include "celx.h" class LuaState; class CelestiaConfig; From 69637541aec06dca0ef8276e7412763e10af9326 Mon Sep 17 00:00:00 2001 From: Hleb Valoshka <375gnu@gmail.com> Date: Fri, 25 Oct 2019 22:09:36 +0300 Subject: [PATCH 13/14] wip --- src/celengine/parseobject.cpp | 16 ++++++++++++++-- src/celestia/celestiacore.cpp | 11 ++++++++--- src/celestia/celestiacore.h | 4 +++- src/celplugin/plugin.cpp | 6 ++++++ src/celplugin/plugin.h | 2 ++ src/celplugin/pluginmanager.cpp | 12 ++++++++++++ src/celplugin/pluginmanager.h | 4 ++++ src/celscript/lua/luascript.cpp | 2 ++ src/celscript/lua/luascript.h | 2 ++ 9 files changed, 53 insertions(+), 6 deletions(-) diff --git a/src/celengine/parseobject.cpp b/src/celengine/parseobject.cpp index b0d6e582b3..a341a660a3 100644 --- a/src/celengine/parseobject.cpp +++ b/src/celengine/parseobject.cpp @@ -670,7 +670,13 @@ CreateScriptedOrbit(Hash* orbitData, orbitData->addValue("AddonPath", *pathValue); #if defined(ENABLE_PLUGINS) - auto plugin = pluginManager.getScriptPlugin(language); + auto pluginManager = celestia::plugin::GetPluginManager(); + if (pluginManager == nullptr) + { + fmt::print(cerr, "Error: PluginManager is not initialized!\n"); + return nullptr; + } + auto plugin = pluginManager->getScriptPlugin(language); if (plugin == nullptr) { fmt::print(cerr, "Support for language {} is missing\n", language); @@ -1061,7 +1067,13 @@ CreateScriptedRotation(Hash* rotationData, rotationData->addValue("AddonPath", *pathValue); #if defined(ENABLE_PLUGINS) - auto plugin = pluginManager.getScriptPlugin(language); + auto pluginManager = celestia::plugin::GetPluginManager(); + if (pluginManager == nullptr) + { + fmt::print(cerr, "Error: PluginManager is not initialized!\n"); + return nullptr; + } + auto plugin = pluginManager->getScriptPlugin(language); if (plugin == nullptr) { fmt::print(cerr, "Support for language {} is missing\n", language); diff --git a/src/celestia/celestiacore.cpp b/src/celestia/celestiacore.cpp index 9975b245e3..58d3983106 100644 --- a/src/celestia/celestiacore.cpp +++ b/src/celestia/celestiacore.cpp @@ -144,10 +144,13 @@ CelestiaCore::CelestiaCore() : renderer(new Renderer()), timer(new Timer()), m_legacyPlugin(make_unique(this)), +#if defined(CELX) && !defined(ENABLE_PLUGINS) m_luaPlugin(make_unique(this)), +#endif m_scriptMaps(make_shared()), m_pluginManager(make_unique(this)) { + SetPluginManager(m_pluginManager.get()); for (int i = 0; i < KeyCount; i++) { @@ -164,6 +167,8 @@ CelestiaCore::CelestiaCore() : CelestiaCore::~CelestiaCore() { + SetPluginManager(nullptr); + if (movieCapture != nullptr) recordEnd(); @@ -299,7 +304,7 @@ void CelestiaCore::runScript(const fs::path& filename) if (m_script != nullptr) scriptState = sim->getPauseState() ? ScriptPaused : ScriptRunning; } -#ifdef CELX +#if defined(CELX) && !defined(ENABLE_PLUGINS) else if (m_luaPlugin->isOurFile(localeFilename)) { m_script = m_luaPlugin->loadScript(localeFilename); @@ -3600,7 +3605,7 @@ bool CelestiaCore::initSimulation(const fs::path& configFileName, } } -#ifdef CELX +#if defined(CELX) && !defined(ENABLE_PLUGINS) initLuaHook(progressNotifier); #endif @@ -4396,7 +4401,7 @@ bool CelestiaCore::referenceMarkEnabled(const string& refMark, Selection sel) co } -#ifdef CELX +#if defined(CELX) && !defined(ENABLE_PLUGINS) bool CelestiaCore::initLuaHook(ProgressNotifier* progressNotifier) { return CreateLuaEnvironment(this, config, progressNotifier); diff --git a/src/celestia/celestiacore.h b/src/celestia/celestiacore.h index 732cd2fc41..50909299a1 100644 --- a/src/celestia/celestiacore.h +++ b/src/celestia/celestiacore.h @@ -350,7 +350,7 @@ class CelestiaCore // : public Watchable protected: bool readStars(const CelestiaConfig&, ProgressNotifier*); void renderOverlay(); -#ifdef CELX +#if defined(CELX) && !defined(ENABLE_PLUGINS) bool initLuaHook(ProgressNotifier*); #endif // CELX @@ -406,7 +406,9 @@ class CelestiaCore // : public Watchable std::unique_ptr m_script; std::unique_ptr m_scriptHook; std::unique_ptr m_legacyPlugin; +#if defined(CELX) && !defined(ENABLE_PLUGINS) std::unique_ptr m_luaPlugin; +#endif std::shared_ptr m_scriptMaps; std::unique_ptr m_pluginManager; diff --git a/src/celplugin/plugin.cpp b/src/celplugin/plugin.cpp index 78fd5b932f..16602634de 100644 --- a/src/celplugin/plugin.cpp +++ b/src/celplugin/plugin.cpp @@ -148,6 +148,12 @@ bool Plugin::isOurFile(const fs::path &filename) const return fn == nullptr ? false : (*fn)(filename); } +std::unique_ptr Plugin::loadScript(const fs::path &filename) +{ + auto fn = m_func.loadScript; + return fn == nullptr ? nullptr : (*fn)(filename); +} + Renderer* Plugin::createRenderer() const { auto fn = m_func.createRenderer; diff --git a/src/celplugin/plugin.h b/src/celplugin/plugin.h index 3c59d2bda1..fe09e6af65 100644 --- a/src/celplugin/plugin.h +++ b/src/celplugin/plugin.h @@ -70,6 +70,7 @@ class Plugin : public IScriptPlugin typedef RotationModel*(CreateScriptedRotationFunc)(const std::string&, const std::string&, Hash*); typedef CachingOrbit*(CreateScriptedOrbitFunc)(const std::string&, const std::string&, Hash*); typedef bool (IsOurFile)(const fs::path&); + typedef std::unique_ptr(LoadScript)(const fs::path&); /// renderer support typedef Renderer*(CreateRendererFunc)(); @@ -109,6 +110,7 @@ class Plugin : public IScriptPlugin CreateScriptedRotationFunc *createScriptedRotation; CreateScriptedOrbitFunc *createScriptedOrbit; IsOurFile *isOurFile; + LoadScript *loadScript; }; struct { diff --git a/src/celplugin/pluginmanager.cpp b/src/celplugin/pluginmanager.cpp index a958f9db08..f05c83bf8d 100644 --- a/src/celplugin/pluginmanager.cpp +++ b/src/celplugin/pluginmanager.cpp @@ -65,5 +65,17 @@ const Plugin* PluginManager::getScriptPlugin(const std::string &lang) const return it != m_plugins.end() ? *it : nullptr; } +static PluginManager* pluginManager = nullptr; + +PluginManager* GetPluginManager() +{ + return pluginManager; +} + +void SetPluginManager(PluginManager *pm) +{ + pluginManager = pm; +} + } } diff --git a/src/celplugin/pluginmanager.h b/src/celplugin/pluginmanager.h index 737acf36c4..4a3e960f65 100644 --- a/src/celplugin/pluginmanager.h +++ b/src/celplugin/pluginmanager.h @@ -53,5 +53,9 @@ class PluginManager fs::path m_directory; CelestiaCore *m_appCore; }; // PluginManager + +PluginManager* GetPluginManager(); +void SetPluginManager(PluginManager*); + } } diff --git a/src/celscript/lua/luascript.cpp b/src/celscript/lua/luascript.cpp index aee232e67c..fdbe8806da 100644 --- a/src/celscript/lua/luascript.cpp +++ b/src/celscript/lua/luascript.cpp @@ -74,6 +74,7 @@ bool LuaScript::tick(double dt) return m_celxScript->tick(dt); } +#ifndef ENABLE_PLUGINS bool LuaScriptPlugin::isOurFile(const fs::path &p) const { auto ext = p.extension(); @@ -108,6 +109,7 @@ unique_ptr LuaScriptPlugin::loadScript(const fs::path &path) return script; } +#endif bool LuaHook::call(const char *method) const { diff --git a/src/celscript/lua/luascript.h b/src/celscript/lua/luascript.h index 59eb343cc1..f61d4fbf4a 100644 --- a/src/celscript/lua/luascript.h +++ b/src/celscript/lua/luascript.h @@ -44,6 +44,7 @@ class LuaScript : public IScript friend class LuaScriptPlugin; }; +#ifndef ENABLE_PLUGINS class LuaScriptPlugin : public IScriptPlugin { public: @@ -58,6 +59,7 @@ class LuaScriptPlugin : public IScriptPlugin bool isOurFile(const fs::path&) const override; std::unique_ptr loadScript(const fs::path&) override; }; +#endif class LuaHook : public IScriptHook { From a8956dfc1a27e9d2928409210a691505146d3f2f Mon Sep 17 00:00:00 2001 From: Hleb Valoshka <375gnu@gmail.com> Date: Fri, 25 Oct 2019 22:22:34 +0300 Subject: [PATCH 14/14] wip --- src/celplugin/plugin-common.h | 2 +- src/celplugin/pluginmanager.cpp | 2 -- src/celscript/lua/CMakeLists.txt | 6 +++++- 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/src/celplugin/plugin-common.h b/src/celplugin/plugin-common.h index d0e6cb1dd9..626279e293 100644 --- a/src/celplugin/plugin-common.h +++ b/src/celplugin/plugin-common.h @@ -19,7 +19,7 @@ #ifdef _WIN32 #define CELESTIA_PLUGIN_EXPORTABLE extern "C" __declspec(dllexport) #else -#define CELESTIA_PLUGIN_EXPORTABLE extern "C" +#define CELESTIA_PLUGIN_EXPORTABLE extern "C" __attribute__ ((visibility ("default"))) #endif #define CELESTIA_PLUGIN_ENTRYPOINT CELESTIA_PLUGIN_EXPORTABLE celestia::plugin::PluginInfo* CELESTIA_PLUGIN_ENTRY_NAME diff --git a/src/celplugin/pluginmanager.cpp b/src/celplugin/pluginmanager.cpp index f05c83bf8d..fc609e9b93 100644 --- a/src/celplugin/pluginmanager.cpp +++ b/src/celplugin/pluginmanager.cpp @@ -51,8 +51,6 @@ const Plugin* PluginManager::loadByName(const std::string &name) { #if defined(_WIN32) return loadByPath(m_directory / fmt::sprintf("%s.dll", name)); -#elif defined(__APPLE__) - return loadByPath(m_directory / fmt::sprintf("lib%s.dylib", name)); #else return loadByPath(m_directory / fmt::sprintf("lib%s.so", name)); #endif diff --git a/src/celscript/lua/CMakeLists.txt b/src/celscript/lua/CMakeLists.txt index fee1ed5b94..ab297ee39c 100644 --- a/src/celscript/lua/CMakeLists.txt +++ b/src/celscript/lua/CMakeLists.txt @@ -35,4 +35,8 @@ set(CELX_SOURCES scriptrotation.h ) -add_library(celluascript SHARED ${CELX_SOURCES}) +add_library(celluascript MODULE ${CELX_SOURCES}) + +if(ENABLE_PLUGINS) + target_compile_options(celluascript PUBLIC -fvisibility=hidden PUBLIC -fvisibility-inlines-hidden) +endif()