This commit is contained in:
Perttu Ahola 2014-09-16 23:14:04 +03:00
parent 9dd2ec7a59
commit 389872bafe
7 changed files with 120 additions and 190 deletions

View File

@ -71,5 +71,5 @@ TARGET_LINK_LIBRARIES(${SERVER_EXE_NAME}
c55lib
dl
)
add_definitions(-DRCCPP_ENABLED=1)
add_definitions()

View File

@ -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)
}

View File

@ -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

View File

@ -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

View File

@ -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;
}

View File

@ -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());
}
}

View File

@ -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());
}
}