Created
December 11, 2012 18:22
-
-
Save jbandela/4260823 to your computer and use it in GitHub Desktop.
Version 1 Cross Compiler interfaces
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <functional> | |
#include <iostream> | |
#include <assert.h> | |
#include <cstddef> | |
typedef void(*ptr_fun_void_t)(); | |
struct vtable{ | |
ptr_fun_void_t* table; | |
}; | |
template<bool bImp> | |
struct interface_base{}; | |
template<> | |
struct interface_base<true>{// Implementation | |
private: | |
int current_; | |
vtable vt; | |
public: | |
interface_base():current_(0){} | |
ptr_fun_void_t* table(){return vt.table;} | |
vtable* get_vtable(){return &vt;} | |
template<class R, class... Parms> | |
R call(int pos,Parms... p){ | |
typedef R(*fun_t)(Parms...); | |
auto f = (fun_t)table()[pos]; | |
return f(p...); | |
} | |
template<class R, class... Parms> | |
int add(R(*pfun)(Parms...)){ | |
table()[current_] = (ptr_fun_void_t)pfun; | |
return current_++; | |
} | |
}; | |
template<> | |
struct interface_base<false>{ // Usage | |
private: | |
vtable* vptr; | |
int current_; | |
public: | |
interface_base():current_(0),vptr(0){} | |
ptr_fun_void_t* table(){return vptr->table;} | |
vtable* get_vtable(){return vptr;} | |
void set_vtable(vtable* v){vptr = v;} | |
int add(){ | |
return current_++; | |
} | |
template<class R, class... Parms> | |
R call(int pos,Parms... p){ | |
typedef R(*fun_t)(Parms...); | |
auto f = (fun_t)table()[pos]; | |
return f(p...); | |
} | |
}; | |
template<bool bImp,template <bool> class Iface, int N> | |
struct vtable_n{}; | |
class vtable_n_getter_setter{ | |
public: | |
template<bool bImp,template <bool> class Iface, int N> | |
static vtable* get_vtable(vtable_n<bImp,Iface,N>* vn){ | |
return vn->ib_.get_vtable(); | |
} | |
template<bool bImp,template <bool> class Iface, int N> | |
static void set_vtable(vtable_n<bImp,Iface,N>* vn, vtable* v){ | |
return vn->ib_.set_vtable(v); | |
} | |
template<bool bImp,template <bool> class Iface, int N> | |
static interface_base<bImp>* get_ib(vtable_n<bImp,Iface,N>* vn){ | |
return &(vn->ib_); | |
} | |
}; | |
template<bool bImp,template <bool> class Iface, int N> | |
vtable* get_vtable(vtable_n<bImp,Iface,N>& vn){ | |
return vtable_n_getter_setter::get_vtable(&vn); | |
} | |
template<template <bool> class Iface,int N> | |
struct vtable_n<true,Iface,N> // Implementation | |
{ | |
friend class Iface<true>; | |
friend class vtable_n_getter_setter; | |
private: | |
interface_base<true> ib_; | |
ptr_fun_void_t table_n[N]; | |
enum {sz = N}; | |
vtable_n(){ | |
ib_.get_vtable()->table = &table_n[0]; | |
} | |
interface_base<true>* base(){return & ib_;} | |
}; | |
template<template <bool> class Iface,int N> | |
struct vtable_n<false,Iface, N> // Usage | |
{ | |
friend struct Iface<false>; | |
friend class vtable_n_getter_setter; | |
enum {sz = N}; | |
private: | |
interface_base<false> ib_; | |
interface_base<false>* base(){return & ib_;} | |
}; | |
template<bool bImp,class Iface, int N,class F> | |
struct jrb_function{}; | |
template<class Iface, int N,class R, class... Parms> | |
struct jrb_function<true, Iface,N,R(Parms...)>{ //Implementation | |
typedef R return_type; | |
typedef std::function<R(Parms...)> fun_t; | |
fun_t func_; | |
int table_pos_; | |
static std::ptrdiff_t offset; | |
static void set_offset(vtable* v,jrb_function& jf){ | |
auto prev_offset = offset; | |
char * cv = reinterpret_cast<char*>(v); | |
char* cf = reinterpret_cast<char*>(&(jf.func_)); | |
offset = cf - cv; | |
if(prev_offset){ | |
assert(offset == prev_offset); | |
} | |
} | |
static fun_t& get_function(vtable* v){ | |
char * cv = reinterpret_cast<char*>(v); | |
char* cf = offset + cv; | |
fun_t* f = reinterpret_cast<fun_t*>(cf); | |
return *f; | |
} | |
static return_type func(vtable* v,Parms... p){ | |
return get_function(v)(p...); | |
} | |
interface_base<true>* ibase_; | |
template<bool bImp,template <bool> class If, int n> | |
jrb_function(vtable_n<bImp,If,n>* vn):table_pos_(-1),ibase_(vtable_n_getter_setter::get_ib(vn)){ | |
set_offset(ibase_->get_vtable(),*this); | |
table_pos_ = ibase_->add(func); | |
} | |
return_type operator()(Parms... p){ | |
return ibase_->call<R,vtable*,Parms...>(table_pos_,ibase_->get_vtable(),p...); | |
} | |
template<class F> | |
void set_func(F f){ | |
func_ = f; | |
} | |
template<class F> | |
void operator=(F f){ | |
set_func(f); | |
} | |
}; | |
template<class Iface, int N,class R, class... Parms> | |
struct jrb_function<false, Iface,N,R(Parms...)>{ //Usage | |
typedef R return_type; | |
typedef std::function<R(Parms...)> fun_t; | |
int table_pos_; | |
interface_base<false>* ibase_; | |
jrb_function(interface_base<false>* i):table_pos_(-1),ibase_(i){ | |
table_pos_ = ibase_->add(); | |
} | |
template<bool bImp,template <bool> class If, int n> | |
jrb_function(vtable_n<bImp,If,n>* vn):table_pos_(-1),ibase_(vtable_n_getter_setter::get_ib(vn)){ | |
table_pos_ = ibase_->add(); | |
} | |
return_type operator()(Parms... p){ | |
return ibase_->call<R,vtable*,Parms...>(table_pos_,ibase_->get_vtable(),p...); | |
} | |
}; | |
template<class Iface, int N,class R, class... Parms> | |
std::ptrdiff_t jrb_function<true,Iface,N,R(Parms...)>::offset = 0; | |
template<template<bool> class Iface> | |
struct imp_interface:public Iface<true>{ // Implementation | |
}; | |
template<template <bool> class Iface> | |
struct use_interface:public Iface<false>{ // Usage | |
use_interface(vtable* v){ | |
use_interface<Iface>* i = this; | |
vtable_n_getter_setter::set_vtable(i,v); | |
} | |
}; | |
template<bool bImp> | |
struct TestInterface1:public vtable_n<bImp,TestInterface1,5>{ | |
jrb_function<bImp,TestInterface1,0,int()> f1; | |
jrb_function<bImp,TestInterface1,1,int(int)> f2; | |
TestInterface1():f1(this),f2(this){ | |
} | |
}; | |
struct Test1:public imp_interface<TestInterface1>{ | |
Test1(){ | |
f1 = []{return 5;}; | |
f2 = [](int i){return i;}; | |
} | |
}; | |
struct Test2:public imp_interface<TestInterface1>{ | |
Test2(){ | |
f1 = []{return 6;}; | |
f2 = [](int i){return i+1;}; | |
} | |
}; | |
void printTest(vtable *v){ | |
use_interface<TestInterface1> t(v); | |
std::cout << t.f1() << std::endl; | |
std::cout << t.f2(6) << std::endl; | |
} | |
void printTest(use_interface<TestInterface1> t){ | |
std::cout << t.f1() << std::endl; | |
std::cout << t.f2(6) << std::endl; | |
} | |
int main(){ | |
Test1 t1; | |
Test2 t2; | |
printTest(get_vtable(t1)); | |
printTest(get_vtable(t2)); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment