Skip to content

Instantly share code, notes, and snippets.

@jbandela
Created December 11, 2012 18:22
Show Gist options
  • Save jbandela/4260823 to your computer and use it in GitHub Desktop.
Save jbandela/4260823 to your computer and use it in GitHub Desktop.
Version 1 Cross Compiler interfaces
#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