Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WIP Plugins common code, initial implementation #469

Draft
wants to merge 14 commits into
base: master
Choose a base branch
from
Draft
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
wip
  • Loading branch information
375gnu committed Oct 23, 2019
commit fe275eaca8ac7bfa13b7e1845bcf344552c56114
2 changes: 1 addition & 1 deletion src/celplugin/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -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)
12 changes: 7 additions & 5 deletions src/celplugin/host.cpp
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
#define PUBLIC_GET_INFO
#include <fmt/printf.h>
#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<void(*)()>(pi->IDDPtr);
void (*myfn)() = reinterpret_cast<void(*)()>(pi->ID);
(*myfn)();
}

5 changes: 2 additions & 3 deletions src/celplugin/myplug.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
#include <iostream>
#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<void*>(&myfn) };
static PluginInfo pinf = { 0x0107, 0, Script, 0, "LUA" };
static PluginInfo pinf(Scripting, "LUA");
return &pinf;
}
73 changes: 73 additions & 0 deletions src/celplugin/plugin-common.h
Original file line number Diff line number Diff line change
@@ -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 <cstdint>

#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)

}
}
15 changes: 13 additions & 2 deletions src/celplugin/plugin.cpp
Original file line number Diff line number Diff line change
@@ -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 <fmt/printf.h>
#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<CreateScriptEnvironmentFunc*>(ptr);
51 changes: 18 additions & 33 deletions src/celplugin/plugin.h
Original file line number Diff line number Diff line change
@@ -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 <cstdint>
#include <string>
#include <vector>
#include <celcompat/filesystem.h>
#ifdef _WIN32
#include <windows.h>
#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<const char*>(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 };
46 changes: 40 additions & 6 deletions src/celplugin/pluginmanager.cpp
Original file line number Diff line number Diff line change
@@ -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 <fmt/printf.h>
#include "plugin.h"
#include "pluginmanager.h"
#include <algorithm>
#ifndef _WIN32
#include <dlfcn.h>
#endif
#include <celutil/util.h>
#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;
}

}
}
33 changes: 28 additions & 5 deletions src/celplugin/pluginmanager.h
Original file line number Diff line number Diff line change
@@ -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 <string>
#include <vector>
#include <celcompat/filesystem.h>


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<Plugin*> m_plugins;
std::vector<const Plugin*> m_plugins;
fs::path m_directory;
}; // PluginManager
}