WIP
This commit is contained in:
parent
9dd2ec7a59
commit
389872bafe
@ -71,5 +71,5 @@ TARGET_LINK_LIBRARIES(${SERVER_EXE_NAME}
|
||||
c55lib
|
||||
dl
|
||||
)
|
||||
add_definitions(-DRCCPP_ENABLED=1)
|
||||
add_definitions()
|
||||
|
||||
|
@ -1,12 +1,13 @@
|
||||
#pragma once
|
||||
#include "server/rccpp.h"
|
||||
#include "core/types.h"
|
||||
|
||||
class Module : public RuntimeClass<Module> {
|
||||
CLASS_INTERNALS(Module)
|
||||
public:
|
||||
Module();
|
||||
~Module();
|
||||
RUNTIME_VIRTUAL int test_add(int a, int b);
|
||||
#define EXPORT __attribute__ ((visibility ("default")))
|
||||
|
||||
namespace interface
|
||||
{
|
||||
struct Module
|
||||
{
|
||||
virtual ~Module(){};
|
||||
virtual int test_add(int a, int b) = 0;
|
||||
};
|
||||
RUNTIME_EXPORT_MODULE(Module)
|
||||
|
||||
}
|
||||
|
@ -1,9 +1,5 @@
|
||||
#if defined(RCCPP_ENABLED)
|
||||
#include "rccpp.h"
|
||||
|
||||
// Module interface
|
||||
#include "interface/module.h"
|
||||
|
||||
#include <c55_filesys.h>
|
||||
|
||||
#include <vector>
|
||||
@ -14,10 +10,47 @@
|
||||
#include <sys/wait.h>
|
||||
#include <dlfcn.h>
|
||||
|
||||
#define RUNTIME_VIRTUAL virtual
|
||||
#define CLASS_INTERNALS(C) public: constexpr static const char *NAME = #C;
|
||||
#include <cstddef>
|
||||
|
||||
#include <vector>
|
||||
#include <cassert>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
#include <algorithm>
|
||||
|
||||
namespace rccpp {
|
||||
|
||||
typedef void *(*RCCPP_Constructor)();
|
||||
|
||||
struct RCCPP_Info {
|
||||
void *module;
|
||||
RCCPP_Constructor constructor;
|
||||
};
|
||||
|
||||
struct CCompiler: public Compiler
|
||||
{
|
||||
CCompiler();
|
||||
|
||||
void build(const std::string &module_name,
|
||||
const std::string &in_path, const std::string &out_path);
|
||||
|
||||
void *construct(const char *name);
|
||||
|
||||
private:
|
||||
std::unordered_map<std::string, RCCPP_Info> component_info_;
|
||||
std::unordered_map<std::string, std::vector<void*>> constructed_objects;
|
||||
|
||||
std::vector<std::string> changed_classes_;
|
||||
bool compile(const std::string &in_path, const std::string &out_path);
|
||||
};
|
||||
|
||||
// linux
|
||||
#if 1
|
||||
static void *library_load(const char *filename) { return dlopen(filename, RTLD_NOW); }
|
||||
static void library_unload(void *module) { dlclose(module); }
|
||||
//static void library_unload(void *module) { dlclose(module); }
|
||||
static void *library_get_address(void *module, const char *name) { return dlsym(module, name); }
|
||||
#elif 0
|
||||
static void *library_load(const char *filename) { return LoadLibrary(filename); }
|
||||
@ -25,11 +58,11 @@ static void library_unload(void *module) { FreeLibrary(module); }
|
||||
static void *library_get_address(void *module, const char *name) { return GetProcAddress(module, name); }
|
||||
#endif
|
||||
|
||||
RCCPP_Compiler::RCCPP_Compiler()
|
||||
CCompiler::CCompiler()
|
||||
{
|
||||
}
|
||||
|
||||
bool RCCPP_Compiler::compile(const std::string &in_path, const std::string &out_path)
|
||||
bool CCompiler::compile(const std::string &in_path, const std::string &out_path)
|
||||
{
|
||||
//std::string command = "g++ -g -O0 -fPIC -fvisibility=hidden -shared";
|
||||
std::string command = "g++ -DRCCPP -g -fPIC -fvisibility=hidden -shared";
|
||||
@ -57,7 +90,7 @@ bool RCCPP_Compiler::compile(const std::string &in_path, const std::string &out_
|
||||
return exit_status == 0;
|
||||
}
|
||||
|
||||
void RCCPP_Compiler::build(const std::string &module_name,
|
||||
void CCompiler::build(const std::string &module_name,
|
||||
const std::string &in_path, const std::string &out_path)
|
||||
{
|
||||
std::cout << "Building " << module_name << ": "
|
||||
@ -78,24 +111,9 @@ void RCCPP_Compiler::build(const std::string &module_name,
|
||||
return;
|
||||
}
|
||||
|
||||
RCCPP_GetInterface GetInterface = (RCCPP_GetInterface)library_get_address(new_module, "rccpp_GetInterface");
|
||||
if(GetInterface == nullptr) {
|
||||
std::cout << "GetInterface is missing from the library" << std::endl;
|
||||
return;
|
||||
}
|
||||
|
||||
RCCPP_Interface *interface = GetInterface();
|
||||
assert(interface && "Interface is null");
|
||||
RCCPP_Constructor fun_constructor = interface->constructor;
|
||||
RCCPP_Destructor fun_destructor = interface->destructor;
|
||||
RCCPP_PlacementNew fun_placementnew = interface->placementnew;
|
||||
|
||||
if(!(fun_constructor && fun_constructor && fun_placementnew)) {
|
||||
printf("Something failed with the function pointers in the module\n");
|
||||
printf(" constructor: %p (%s)\n", fun_constructor, (fun_constructor != nullptr ? "ok" : "fail"));
|
||||
printf(" destructor: %p (%s)\n", fun_destructor, (fun_destructor != nullptr ? "ok" : "fail"));
|
||||
printf(" placement new: %p (%s)\n", fun_placementnew, (fun_placementnew != nullptr ? "ok" : "fail"));
|
||||
fflush(stdout);
|
||||
RCCPP_Constructor constructor = (RCCPP_Constructor)library_get_address(new_module, "createModule");
|
||||
if(constructor == nullptr) {
|
||||
std::cout << "createModule() is missing from the library" << std::endl;
|
||||
return;
|
||||
}
|
||||
|
||||
@ -105,27 +123,19 @@ void RCCPP_Compiler::build(const std::string &module_name,
|
||||
auto it = component_info_.find(classname);
|
||||
if(it != component_info_.end()) {
|
||||
RCCPP_Info &funcs = it->second;
|
||||
funcs.constructor = fun_constructor;
|
||||
funcs.destructor = fun_destructor;
|
||||
funcs.placement_new = fun_placementnew;
|
||||
if(funcs.module_prev) library_unload(funcs.module_prev);
|
||||
funcs.module_prev = funcs.module;
|
||||
funcs.constructor = constructor;
|
||||
funcs.module = new_module;
|
||||
} else {
|
||||
RCCPP_Info funcs;
|
||||
funcs.constructor = fun_constructor;
|
||||
funcs.destructor = fun_destructor;
|
||||
funcs.placement_new = fun_placementnew;
|
||||
funcs.module_prev = nullptr;
|
||||
funcs.constructor = constructor;
|
||||
funcs.module = new_module;
|
||||
funcs.size = interface->original_size;
|
||||
component_info_.emplace(classname, std::move(funcs));
|
||||
}
|
||||
|
||||
changed_classes_.push_back(classname);
|
||||
}
|
||||
|
||||
void *RCCPP_Compiler::construct(const char *name) {
|
||||
void *CCompiler::construct(const char *name) {
|
||||
auto component_info_it = component_info_.find(name);
|
||||
if(component_info_it == component_info_.end()) {
|
||||
assert(nullptr && "Failed to get class info");
|
||||
@ -145,5 +155,9 @@ void *RCCPP_Compiler::construct(const char *name) {
|
||||
return result;
|
||||
}
|
||||
|
||||
#endif
|
||||
Compiler* createCompiler()
|
||||
{
|
||||
return new CCompiler();
|
||||
}
|
||||
|
||||
} // rccpp
|
||||
|
@ -1,126 +1,19 @@
|
||||
#pragma once
|
||||
#include "core/types.h"
|
||||
|
||||
// This is what you get when the RCCPP is not enabled
|
||||
#if !defined(RCCPP_ENABLED) && !defined(RCCPP)
|
||||
#define RUNTIME_EXPORT_MODULE(C)
|
||||
#define RUNTIME_VIRTUAL
|
||||
#endif
|
||||
namespace rccpp
|
||||
{
|
||||
struct Compiler {
|
||||
virtual ~Compiler(){}
|
||||
|
||||
#if defined(RCCPP) || defined(RCCPP_ENABLED)
|
||||
#define RCCPP_USE_SINGLETON_NEWING
|
||||
#define RUNTIME_VIRTUAL virtual
|
||||
#define CLASS_INTERNALS(C) public: constexpr static const char *NAME = #C;
|
||||
#include <cstddef>
|
||||
virtual void build(const std::string &module_name,
|
||||
const std::string &in_path, const std::string &out_path) = 0;
|
||||
|
||||
struct RCCPP_Interface;
|
||||
virtual void *construct(const char *name) = 0;
|
||||
|
||||
typedef void *(*RCCPP_Constructor)();
|
||||
typedef void (*RCCPP_Destructor)(void *component);
|
||||
typedef void (*RCCPP_PlacementNew)(void *buffer, size_t size);
|
||||
typedef RCCPP_Interface *(*RCCPP_GetInterface)();
|
||||
|
||||
struct RCCPP_Interface {
|
||||
RCCPP_Constructor constructor;
|
||||
RCCPP_Destructor destructor;
|
||||
RCCPP_PlacementNew placementnew;
|
||||
const char *classname;
|
||||
size_t original_size;
|
||||
};
|
||||
#endif
|
||||
|
||||
// This is what the runtime compiler exports for the library.
|
||||
#if defined(RCCPP) && !defined(RCCPP_ENABLED)
|
||||
#include <new>
|
||||
#define EXPORT __attribute__ ((visibility ("default")))
|
||||
#define RUNTIME_EXPORT_MODULE(C) \
|
||||
extern "C" { \
|
||||
static void *rccpp_constructor() { return new C(); } \
|
||||
static void rccpp_destructor(void *c) { delete reinterpret_cast<C*>(c); } \
|
||||
static void rccpp_placementnew(void *buffer, size_t size) { new (buffer) C(*(C*)buffer); } \
|
||||
EXPORT RCCPP_Interface *rccpp_GetInterface() { \
|
||||
static RCCPP_Interface interface; \
|
||||
interface.constructor = &rccpp_constructor; \
|
||||
interface.destructor = &rccpp_destructor; \
|
||||
interface.placementnew = &rccpp_placementnew; \
|
||||
interface.classname = #C; \
|
||||
interface.original_size = sizeof(C); \
|
||||
return &interface; \
|
||||
} \
|
||||
}
|
||||
#endif
|
||||
|
||||
// And this is what your normal compiler sees when you have actually enabled RCCPP.
|
||||
#if !defined(RCCPP) && defined(RCCPP_ENABLED)
|
||||
|
||||
#define RCCPP_CONSTRUCTOR "rccpp_constructor"
|
||||
#define RCCPP_DESTRUCTOR "rccpp_destructor"
|
||||
#define RCCPP_PLACEMENT_NEW "rccpp_placement_new"
|
||||
#define RCCPP_MOVE "rccpp_move"
|
||||
#define RCCPP_CLASSNAME "rccpp_classname"
|
||||
|
||||
#define RUNTIME_EXPORT_MODULE(C)
|
||||
#define RUNTIME_VIRTUAL virtual
|
||||
|
||||
#include <vector>
|
||||
#include <cassert>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
#include <algorithm>
|
||||
|
||||
struct RCCPP_Info {
|
||||
void *module;
|
||||
void *module_prev;
|
||||
RCCPP_Constructor constructor;
|
||||
RCCPP_Destructor destructor;
|
||||
RCCPP_PlacementNew placement_new;
|
||||
size_t size;
|
||||
std::string classname;
|
||||
};
|
||||
|
||||
class RCCPP_Compiler {
|
||||
public:
|
||||
RCCPP_Compiler();
|
||||
|
||||
void build(const std::string &module_name,
|
||||
const std::string &in_path, const std::string &out_path);
|
||||
|
||||
void *construct(const char *name);
|
||||
|
||||
#if defined(RCCPP_USE_SINGLETON_NEWING)
|
||||
static RCCPP_Compiler &instance() {
|
||||
static RCCPP_Compiler i;
|
||||
return i;
|
||||
}
|
||||
#endif
|
||||
std::vector<std::string> include_directories;
|
||||
std::vector<std::string> library_directories;
|
||||
private:
|
||||
|
||||
std::unordered_map<std::string, RCCPP_Info> component_info_;
|
||||
std::unordered_map<std::string, std::vector<void*>> constructed_objects;
|
||||
|
||||
std::vector<std::string> changed_classes_;
|
||||
bool compile(const std::string &in_path, const std::string &out_path);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
#if defined(RCCPP_ENABLED)
|
||||
#include <cstddef>
|
||||
template<typename T>
|
||||
class RuntimeClass {
|
||||
public:
|
||||
#ifdef RCCPP_USE_SINGLETON_NEWING
|
||||
void *operator new(size_t size) { return RCCPP_Compiler::instance().construct(T::NAME); }
|
||||
#endif
|
||||
Compiler* createCompiler();
|
||||
};
|
||||
|
||||
#ifdef RCCPP_USE_SINGLETON_NEWING
|
||||
#define RCCPP_Update() RCCPP_Compiler::instance().update();
|
||||
#endif
|
||||
|
||||
#else
|
||||
template<typename T> class RuntimeClass { };
|
||||
#endif
|
||||
|
@ -12,13 +12,14 @@ namespace server {
|
||||
|
||||
struct CState: public State, public interface::Server
|
||||
{
|
||||
RCCPP_Compiler m_compiler;
|
||||
up_<rccpp::Compiler> m_compiler;
|
||||
|
||||
CState()
|
||||
CState():
|
||||
m_compiler(rccpp::createCompiler())
|
||||
{
|
||||
m_compiler.include_directories.push_back(
|
||||
m_compiler->include_directories.push_back(
|
||||
g_server_config.interface_path);
|
||||
m_compiler.include_directories.push_back(
|
||||
m_compiler->include_directories.push_back(
|
||||
g_server_config.interface_path+"/..");
|
||||
}
|
||||
|
||||
@ -28,9 +29,10 @@ struct CState: public State, public interface::Server
|
||||
{
|
||||
std::cerr<<"Loading module "<<module_name<<" from "<<path<<std::endl;
|
||||
ss_ build_dst = g_server_config.rccpp_build_path + "/module.so";
|
||||
m_compiler.build(module_name, path+"/server/main.cpp", build_dst);
|
||||
m_compiler->build(module_name, path+"/server/main.cpp", build_dst);
|
||||
|
||||
Module *m = static_cast<Module*>(m_compiler.construct(module_name.c_str()));
|
||||
interface::Module *m = static_cast<interface::Module*>(
|
||||
m_compiler->construct(module_name.c_str()));
|
||||
int a = m->test_add(1, 2);
|
||||
std::cout<<"a = "<<a<<std::endl;
|
||||
}
|
||||
|
@ -1,15 +1,25 @@
|
||||
#include "interface/module.h"
|
||||
#include "interface/server.h"
|
||||
|
||||
Module::Module()
|
||||
struct Module: public interface::Module
|
||||
{
|
||||
Module()
|
||||
{
|
||||
}
|
||||
|
||||
Module::~Module()
|
||||
~Module()
|
||||
{
|
||||
}
|
||||
|
||||
int Module::test_add(int a, int b)
|
||||
int test_add(int a, int b)
|
||||
{
|
||||
return a + b;
|
||||
}
|
||||
};
|
||||
|
||||
extern "C" {
|
||||
EXPORT void* createModule(interface::Server *server)
|
||||
{
|
||||
return (void*)(new Module());
|
||||
}
|
||||
}
|
||||
|
@ -1,15 +1,25 @@
|
||||
#include "interface/module.h"
|
||||
#include "interface/server.h"
|
||||
|
||||
Module::Module()
|
||||
struct Module: public interface::Module
|
||||
{
|
||||
Module()
|
||||
{
|
||||
}
|
||||
|
||||
Module::~Module()
|
||||
~Module()
|
||||
{
|
||||
}
|
||||
|
||||
int Module::test_add(int a, int b)
|
||||
int test_add(int a, int b)
|
||||
{
|
||||
return a + b;
|
||||
}
|
||||
};
|
||||
|
||||
extern "C" {
|
||||
EXPORT void* createModule(interface::Server *server)
|
||||
{
|
||||
return (void*)(new Module());
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user