cib - meeting c++

76
CIB Component Interface Binder: ABI stable architecture for a C++ SDK Satya Das

Upload: others

Post on 07-Dec-2021

6 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: CIB - Meeting C++

CIBComponent Interface Binder:

ABI stable architecture for a C++ SDK

Satya Das

Page 2: CIB - Meeting C++

2

About me

● A developer at TomTom● Previously I was at Adobe

Page 3: CIB - Meeting C++

3

ABI Stability

Binary compatibility of older client with new library

Page 4: CIB - Meeting C++

4

Agenda

● ABI stable architecture for

– Simple Class with demo– Class Hierarchy– Interface Class with demo

● About CIB tool● Case Study● What all we left

Page 5: CIB - Meeting C++

5

Simple class Demo

SIMPLE CLASS class Circle {public: Circle(float r); Circle(const Circle&) = default; virtual ~Circle() = default;

float Radius() const; void SetRadius(float r);

virtual float Area() const;

private: float mRadius;};

Page 6: CIB - Meeting C++

6

Hourglass Interface

Page 7: CIB - Meeting C++

7

Hourglass Interface

● It was a great talk but few things it did not cover

– Virtual function– Interface classes– Inheritance

● As per Stefanus it was more for ABI isolation

Page 8: CIB - Meeting C++

8

Export free functions ?

Circle* CreateCircle(float r) { return new Circle(r);}

Circle* CopyCircle(const Circle* pCircle) { return new Circle(*pCircle);}

void DeleteCircle(Circle* pCircle) { delete pCircle;}

float Radius(const Circle* pCircle) { return pCircle->Radius();}

void SetRadius(Circle* pCircle, float r) { pCircle->SetRadius(r);}

float Area(const Circle* pCircle) { return pCircle->Area();}

Except the constructor all functions have first parameter as pointer of the class.

Page 9: CIB - Meeting C++

9

Export MethodTable instead

class Circle;using CircleImpl = Circle;

extern "C" struct MethodTableCircle { const size_t numMethods;

CircleImpl* (*Create) (float); CircleImpl* (*Copy) (const CircleImpl*); void (*Delete) (CircleImpl*); float (*Radius) (const CircleImpl*); void (*SetRadius) (CircleImpl*, float); float (*Area) (const CircleImpl*);};

extern "C" { MethodTableCircle DLLEXPORT

gMethodTableCircle = { 6, &CreateCircle, &CopyCircle, &DeleteCircle, &Radius, &SetRadius, &Area };}

Page 10: CIB - Meeting C++

10

Export MethodTable instead

class Circle;using CircleImpl = Circle;

extern "C" struct MethodTableCircle { const size_t numMethods;

CircleImpl* (*Create) (float); CircleImpl* (*Copy) (const CircleImpl*); void (*Delete) (CircleImpl*); float (*Radius) (const CircleImpl*); void (*SetRadius) (CircleImpl*, float); float (*Area) (const CircleImpl*);};

extern "C" { MethodTableCircle DLLEXPORT

gMethodTableCircle = { 6, &CreateCircle, &CopyCircle, &DeleteCircle, &Radius, &SetRadius, &Area };}

Page 11: CIB - Meeting C++

11

Export MethodTable instead

class Circle;using CircleImpl = Circle;

extern "C" struct MethodTableCircle { const size_t numMethods;

CircleImpl* (*Create) (float); CircleImpl* (*Copy) (const CircleImpl*); void (*Delete) (CircleImpl*); float (*Radius) (const CircleImpl*); void (*SetRadius) (CircleImpl*, float); float (*Area) (const CircleImpl*);};

extern "C" { MethodTableCircle DLLEXPORT

gMethodTableCircle = { 6, &CreateCircle, &CopyCircle, &DeleteCircle, &Radius, &SetRadius, &Area };}

Page 12: CIB - Meeting C++

12

Client Uses Proxy Class

class CircleImpl;

class Circle {public: Circle(float r); Circle(const Circle&); virtual ~Circle();

float Radius() const; void SetRadius(float r);

virtual float Area() const;

private: Circle(CircleImpl* pCircleImpl) : pImpl(pCircleImpl) {} CircleImpl* pImpl;};

class Circle {public: Circle(float r); Circle(const Circle&) = default; virtual ~Circle() = default;

float Radius() const; void SetRadius(float r);

virtual float Area() const;

private: float mRadius;};

Library side class definition Client side class definition

Page 13: CIB - Meeting C++

13

Client Imports MethodTable

class CircleImpl;

extern "C" struct MethodTableCircle { const size_t numMethods;

CircleImpl* (*Create) (float); CircleImpl* (*Copy) (const CircleImpl*); void (*Delete) (CircleImpl*); float (*Radius) (const CircleImpl*); void (*SetRadius) (CircleImpl*, float); float (*Area) (const CircleImpl*);};

extern "C" MethodTableCircle DLLIMPORT gMethodTableCircle;

Page 14: CIB - Meeting C++

14

Proxy Class Implementation

Circle::Circle(float r) : pImpl(gMethodTableCircle.Create(r)){}

Circle::Circle(const Circle& a) : pImpl(gMethodTableCircle.Copy(a.pImpl)){}

Circle::~Circle() { gMethodTableCircle.Delete(pImpl);}

Page 15: CIB - Meeting C++

15

Proxy Class Implementation

float Circle::Radius() const { return gMethodTableCircle.Radius(pImpl);}

void Circle::SetRadius(float r) { return gMethodTableCircle.SetRadius(pImpl, r);}

float Circle::Area() const { return gMethodTableCircle.Area(pImpl);}

Page 16: CIB - Meeting C++

16

Proxy Class Sequence Diagram

Circle c(10); c.Area();

Page 17: CIB - Meeting C++

17

Class use sequence diagram

Circle c(10); c.Area();

Page 18: CIB - Meeting C++

18

Class use sequence diagram

Circle c(10); c.Area();

Page 19: CIB - Meeting C++

19

Class use sequence diagram

Circle c(10); c.Area();

Page 20: CIB - Meeting C++

20

Class use sequence diagram

Circle c(10); c.Area();

Page 21: CIB - Meeting C++

21

Class use sequence diagram

Circle c(10); c.Area();

Page 22: CIB - Meeting C++

22

Ensuring ABI stability

class Circle {public: Circle(float r); Circle(const Circle&) = default; virtual ~Circle() = default;

float Radius() const; void SetRadius(float r);

virtual float Perimeter() const; virtual float Area() const;

private: float mOx {0}; float mOy {0}; float mRadius;};

Page 23: CIB - Meeting C++

23

Ensuring ABI stability

extern "C" { MethodTableCircle DLLEXPORT

gMethodTableCircle = { 7, &CreateCircle, &CopyCircle, &DeleteCircle, &Radius, &SetRadius, &Area, &Perimeter };}

extern "C" { MethodTableCircle DLLEXPORT

gMethodTableCircle = { 6, &CreateCircle, &CopyCircle, &DeleteCircle, &Radius, &SetRadius, &Area };}

Method Table: Version 1 Method Table: Version 2

MethodTable is only appended

Page 24: CIB - Meeting C++

24

MethodTable Vs Virtual Table

● MethodTable is NOT replacement of virtual table.

Page 25: CIB - Meeting C++

25

MethodTable Vs Virtual Table

● MethodTable is NOT replacement of virtual table.

● MethodTable is just a mechanism for cross component function call.

Page 26: CIB - Meeting C++

26

MethodTable Vs Virtual Table

● MethodTable is NOT replacement of virtual table.

● MethodTable is just a mechanism for cross component function call.

● MethodTable is shared between components.

Page 27: CIB - Meeting C++

27

MethodTable Vs Virtual Table

● MethodTable is NOT replacement of virtual table.

● MethodTable is just a mechanism for cross component function call.

● MethodTable is shared between components.● Virtual table remains local.

Page 28: CIB - Meeting C++

28

MethodTable Vs Virtual Table

● MethodTable is NOT replacement of virtual table.

● MethodTable is just a mechanism for cross component function call.

● MethodTable is shared between components.● Virtual table remains local.● MethodTable is handy in supporting backward

compatibility.

Page 29: CIB - Meeting C++

29

Client’s Backward Compatiblity

class CircleImpl;

class Circle {public: Circle(float r); Circle(const Circle&); virtual ~Circle();

float Radius() const; void SetRadius(float r);

virtual float Perimeter() const; virtual float Area() const;

private: Circle(CircleImpl* pImplA); CircleImpl* pImpl;};

Page 30: CIB - Meeting C++

30

Client’s Backward Compatiblity

float Circle::Perimeter() const { if (gMethodTableCircle.numMethods < 7) throw std::bad_function_call(); return gMethodTableCircle.Perimeter(pImpl);}

Page 31: CIB - Meeting C++

31

Client’s Backward Compatiblity

try {

Circle c; const auto p = c.Perimeter();

} catch(std::bad_function_call) {

std::clog << "New client with old library" << std::endl;

} }

Page 32: CIB - Meeting C++

32

MethodTable Vs Virtual Table

● MethodTable is NOT replacement of virtual table.

● MethodTable is just a mechanism for cross component function call.

● MethodTable is shared between components.● Virtual table remains local.● MethodTable is handy in supporting backward

compatibility.● MethodTable does NOT inherit.

Page 33: CIB - Meeting C++

33

EXAMPLE 2

INHERITANCE

Page 34: CIB - Meeting C++

34

Inheritance

Library Version 1 Library Version 2

struct Base { Base() {} virtual ~Base() {}

virtual int F() { return 1; } virtual int G() { return 2; } virtual int E() { return 9; }};

struct Derived : Base { Derived() {} virtual ~Derived() {};

int G() override { return 3; } virtual int H() { return 4; }};

struct Base { Base() {} virtual ~Base() {}

virtual int F() { return 1; } virtual int G() { return 2; }};

struct Derived : Base { Derived() {} virtual ~Derived() {};

int G() override { return 3; } virtual int H() { return 4; }};

Page 35: CIB - Meeting C++

35

Inheritance

Library Version 1 Library Version 2

struct Base { Base() {} virtual ~Base() {}

virtual int F() { return 1; } virtual int G() { return 2; } virtual int E() { return 9; }};

struct Derived : Base { Derived() {} virtual ~Derived() {};

int G() override { return 3; } virtual int H() { return 4; }};

struct Base { Base() {} virtual ~Base() {}

virtual int F() { return 1; } virtual int G() { return 2; }};

struct Derived : Base { Derived() {} virtual ~Derived() {};

int G() override { return 3; } virtual int H() { return 4; }};

Page 36: CIB - Meeting C++

36

Inheritance

Library Version 1 Library Version 2

struct Base { Base() {} virtual ~Base() {}

virtual int F() { return 1; } virtual int G() { return 2; }};

struct Base2 {...};

struct Derived : Base, Base2 { Derived() {} virtual ~Derived() {};

int G() override { return 3; } virtual int H() { return 4; }};

struct Base { Base() {} virtual ~Base() {}

virtual int F() { return 1; } virtual int G() { return 2; }};

struct Derived : Base { Derived() {} virtual ~Derived() {};

int G() override { return 3; } virtual int H() { return 4; }};

Page 37: CIB - Meeting C++

37

Inheritance

MethodTable of Base Class

static Base* CreateBase() { return new Base;}

static void DeleteBase(Base* pBase) { delete pBase;}

static int F(Base* pBase) { return pBase->F();}

static int G(Base* pBase) { return pBase->Base::G();}

extern "C" { MethodTableBase DLLEXPORT

gMethodTableBase = { 4, &CreateBase, &DeleteBase, &F, &G };}

Page 38: CIB - Meeting C++

38

Inheritance

MethodTable of Derived Class does NOT contain entries for Base class

static Derived* CreateDerived() { return new Derived;}

static void DeleteDerived(Derived* pDerived) { delete pDerived;}

static int G(Derived* pDerived) { return pDerived->G();}

static int H(Derived* pDerived) { return pDerived->H();}

static Base* CastToBase(Derived* pDerived) { return pDerived;}

extern "C" { MethodTableDerived DLLEXPORT

gMethodTableDerived = { 5, &CreateDerived, &DeleteDerived, &CastToBase, &G, &H };}

Page 39: CIB - Meeting C++

39

Inheritance

MethodTable of Derived Class does NOT contain entries for Base class

static Derived* CreateDerived() { return new Derived;}

static void DeleteDerived(Derived* pDerived) { delete pDerived;}

static int G(Derived* pDerived) { return pDerived->G();}

static int H(Derived* pDerived) { return pDerived->H();}

static Base* CastToBase(Derived* pDerived) { return pDerived;}

extern "C" { MethodTableDerived DLLEXPORT

gMethodTableDerived = { 5, &CreateDerived, &DeleteDerived, &CastToBase, &G, &H };}

● No function pointer corresponding to base class methods

Page 40: CIB - Meeting C++

40

Inheritance

Base Class definition on client side

struct BaseImpl;

struct Base { Base(); virtual ~Base();

virtual int F(); virtual int G();

protected: Base(BaseImpl* pBaseImpl); BaseImpl* pImpl;};

extern "C" MethodTableBase DLLIMPORT gMethodTableBase;

Base::Base(BaseImpl* pBaseImpl) : pImpl(pBaseImpl){}

Base::Base() : Base(gMethodTableBase.Create()){}

Base::~Base() { gMethodTableBase.Delete(pImpl);}

int Base::F() { return gMethodTableBase.F(pImpl);}

int Base::G() { return gMethodTableBase.G(pImpl);}

Page 41: CIB - Meeting C++

41

Inheritance

Derived Class definition on client side

struct DerivedImpl;

struct Derived : Base { Derived(); virtual ~Derived();

int G() override; virtual int H();

private: Derived(DerivedImpl* pDerivedImpl); DerivedImpl* pImpl;};

extern "C" MethodTableDerived DLLIMPORT gMethodTableDerived;

Derived::Derived(DerivedImpl* pImplDerived) : Base(gMethodTableDerived.CastToBase(pImplDerived)) , pImpl(pImplDerived){}

Derived::Derived() : Derived(gMethodTableDerived.Create()){}

Derived::~Derived() { gMethodTableDerived.Delete(pImpl); Base::pImpl = nullptr;}

int Derived::G() { return gMethodTableDerived.G(pImpl);}

int Derived::H() { return gMethodTableDerived.H(pImpl);}

Page 42: CIB - Meeting C++

42

Inheritance

CLIENT LIBRARY V1

Base

pImpl

Base

pImpl

Derived::Derived(DerivedImpl* pImplDerived) : Base(gMethodTableDerived.CastToBase(pImplDerived)) , pImpl(pImplDerived){}

Page 43: CIB - Meeting C++

43

Inheritance

CLIENT LIBRARY V2

Base

pImpl

Base2

pImpl

Derived::Derived(DerivedImpl* pImplDerived) : Base(gMethodTableDerived.CastToBase(pImplDerived)) , pImpl(pImplDerived){}

Base

Page 44: CIB - Meeting C++

44

EXAMPLE 3

INTERFACE CLASS

Page 45: CIB - Meeting C++

45

Interface Class Demo

Page 46: CIB - Meeting C++

46

Interface Classes

class Context {public: virtual ~Context() {}

virtual void DrawCircle(float r) = 0;};

class Circle {public: Circle(float r) : mRadius(r) {}

void Draw(Context* pCtx) const { pCtx->DrawCircle(mRadius); }

private: float mRadius;};

Library Client

class DrawLogger : public Context { void DrawCircle(float r) override { std::cout << "DrawCircle(" << r << ")"; }};

int main() { DrawLogger logger; Circle c(5.0); c.Draw(&logger);}

Page 47: CIB - Meeting C++

47

Client “exports” method table

class Context;using ClientCtxImpl = Context;

struct MethodTableClientCtx { const size_t numMethods;

void (*DrawCircle) (ClientCtxImpl*, float);};

static void DrawCircle(Context* pCtx, float r) { return pCtx->DrawCircle(r);}

static MethodTableClientCtx gMethodTableCtx = { 1, &DrawCircle };

Page 48: CIB - Meeting C++

48

Client “exports” method table

class Context;using ClientCtxImpl = Context;

struct MethodTableClientCtx { const size_t numMethods;

void (*DrawCircle) (ClientCtxImpl*, float);};

static void DrawCircle(Context* pCtx, float r) { return pCtx->DrawCircle(r);}

static MethodTableClientCtx gMethodTableCtx = { 1, &DrawCircle };

Page 49: CIB - Meeting C++

49

Client “exports” method table

class Context;using ClientCtxImpl = Context;

struct MethodTableClientCtx { const size_t numMethods;

void (*DrawCircle) (ClientCtxImpl*, float);};

static void DrawCircle(Context* pCtx, float r) { return pCtx->DrawCircle(r);}

static MethodTableClientCtx gMethodTableCtx = { 1, &DrawCircle };

Page 50: CIB - Meeting C++

50

Library uses implementaion through proxy

Library glue code

static Context* CreateGenericCtx(ClientCtxImpl* p,MethodTableClientCtx* m) {

return new GenericCtx(p, m);}

static void DeleteGenericCtx(Context* pGenericCtx) {

delete pGenericCtx;}

extern "C" { MethodTableGenericCtx DLLEXPORT

gMethodTableGenericCtx = { 2, &CreateGenericCtx, &DeleteGenericCtx };}

class ClientCtxImpl;

class GenericCtx : public Context {public: GenericCtx(ClientCtxImpl* p, MethodTableClientCtx* m) : pImpl(p) , pMethodTable(m) {}

void DrawCircle(float r) override { pMethodTable->DrawCircle(pImpl, r); }

private: ClientCtxImpl* pImpl; MethodTableClientCtx* pMethodTable;};

Page 51: CIB - Meeting C++

51

Library uses implementaion through proxy

Library glue code

static Context* CreateGenericCtx(ClientCtxImpl* p,MethodTableClientCtx* m) {

return new GenericCtx(p, m);}

static void DeleteGenericCtx(Context* pGenericCtx) {

delete pGenericCtx;}

extern "C" { MethodTableGenericCtx DLLEXPORT

gMethodTableGenericCtx = { 2, &CreateGenericCtx, &DeleteGenericCtx };}

class ClientCtxImpl;

class GenericCtx : public Context {public: GenericCtx(ClientCtxImpl* p, MethodTableClientCtx* m) : pImpl(p) , pMethodTable(m) {}

void DrawCircle(float r) override { pMethodTable->DrawCircle(pImpl, r); }

private: ClientCtxImpl* pImpl; MethodTableClientCtx* pMethodTable;};

Page 52: CIB - Meeting C++

52

Library uses implementaion through proxy

Library glue code

static Context* CreateGenericCtx(ClientCtxImpl* p,MethodTableClientCtx* m) {

return new GenericCtx(p, m);}

static void DeleteGenericCtx(Context* pGenericCtx) {

delete pGenericCtx;}

extern "C" { MethodTableGenericCtx DLLEXPORT

gMethodTableGenericCtx = { 2, &CreateGenericCtx, &DeleteGenericCtx };}

class ClientCtxImpl;

class GenericCtx : public Context {public: GenericCtx(ClientCtxImpl* p, MethodTableClientCtx* m) : pImpl(p) , pMethodTable(m) {}

void DrawCircle(float r) override { pMethodTable->DrawCircle(pImpl, r); }

private: ClientCtxImpl* pImpl; MethodTableClientCtx* pMethodTable;};

Page 53: CIB - Meeting C++

53

Library uses implementaion through proxy

Library glue code

static Context* CreateGenericCtx(ClientCtxImpl* p,MethodTableClientCtx* m) {

return new GenericCtx(p, m);}

static void DeleteGenericCtx(Context* pGenericCtx) {

delete pGenericCtx;}

extern "C" { MethodTableGenericCtx DLLEXPORT

gMethodTableGenericCtx = { 2, &CreateGenericCtx, &DeleteGenericCtx };}

class ClientCtxImpl;

class GenericCtx : public Context {public: GenericCtx(ClientCtxImpl* p, MethodTableClientCtx* m) : pImpl(p) , pMethodTable(m) {}

void DrawCircle(float r) override { pMethodTable->DrawCircle(pImpl, r); }

private: ClientCtxImpl* pImpl; MethodTableClientCtx* pMethodTable;};

Page 54: CIB - Meeting C++

54

Library uses implementaion through proxy

Library glue code

static Context* CreateGenericCtx(ClientCtxImpl* p,MethodTableClientCtx* m) {

return new GenericCtx(p, m);}

static void DeleteGenericCtx(Context* pGenericCtx) {

delete pGenericCtx;}

extern "C" { MethodTableGenericCtx DLLEXPORT

gMethodTableGenericCtx = { 2, &CreateGenericCtx, &DeleteGenericCtx };}

class ClientCtxImpl;

class GenericCtx : public Context {public: GenericCtx(ClientCtxImpl* p, MethodTableClientCtx* m) : pImpl(p) , pMethodTable(m) {}

void DrawCircle(float r) override { pMethodTable->DrawCircle(pImpl, r); }

private: ClientCtxImpl* pImpl; MethodTableClientCtx* pMethodTable;};

Page 55: CIB - Meeting C++

55

Library uses implementaion through proxy

Library glue code

static Context* CreateGenericCtx(ClientCtxImpl* p,MethodTableClientCtx* m) {

return new GenericCtx(p, m);}

static void DeleteGenericCtx(Context* pGenericCtx) {

delete pGenericCtx;}

extern "C" { MethodTableGenericCtx DLLEXPORT

gMethodTableGenericCtx = { 2, &CreateGenericCtx, &DeleteGenericCtx };}

class ClientCtxImpl;

class GenericCtx : public Context {public: GenericCtx(ClientCtxImpl* p, MethodTableClientCtx* m) : pImpl(p) , pMethodTable(m) {}

void DrawCircle(float r) override { pMethodTable->DrawCircle(pImpl, r); }

private: ClientCtxImpl* pImpl; MethodTableClientCtx* pMethodTable;};

Page 56: CIB - Meeting C++

56

Library uses implementaion through proxy

Library glue code

static Context* CreateGenericCtx(ClientCtxImpl* p,MethodTableClientCtx* m) {

return new GenericCtx(p, m);}

static void DeleteGenericCtx(Context* pGenericCtx) {

delete pGenericCtx;}

extern "C" { MethodTableGenericCtx DLLEXPORT

gMethodTableGenericCtx = { 2, &CreateGenericCtx, &DeleteGenericCtx };}

class ClientCtxImpl;

class GenericCtx : public Context {public: GenericCtx(ClientCtxImpl* p, MethodTableClientCtx* m) : pImpl(p) , pMethodTable(m) {}

void DrawCircle(float r) override { pMethodTable->DrawCircle(pImpl, r); }

private: ClientCtxImpl* pImpl; MethodTableClientCtx* pMethodTable;};

Page 57: CIB - Meeting C++

57

Library exports MethodTable of the circle class too

Library glue code

extern "C" { MethodTableCircle DLLEXPORT

gMethodTableCircle = { 3, &CreateCircle, &DeleteCircle, &Draw };}

static Circle* CreateCircle(float r) { return new Circle(r);}

static void DeleteCircle(Circle* pCircle) { delete pCircle;}

static void Draw(const Circle* pCircle, Context* pCtx) {

pCircle->Draw(pCtx);}

Page 58: CIB - Meeting C++

58

Client side interface definition

class ContextImpl;

class Context {public: virtual ~Context();

virtual void DrawCircle(float r) = 0;

ContextImpl* const pImpl;

protected: Context();};

Page 59: CIB - Meeting C++

59

Client side interface definition

class ContextImpl;

class Context {public: virtual ~Context();

virtual void DrawCircle(float r) = 0;

ContextImpl* const pImpl;

protected: Context();};

Page 60: CIB - Meeting C++

60

Client side interface definition

class ContextImpl;

class Context {public: virtual ~Context();

virtual void DrawCircle(float r) = 0;

ContextImpl* const pImpl;

protected: Context();};

Page 61: CIB - Meeting C++

61

Client side interface definition

extern "C" MethodTableGenericCtx DLLIMPORT gMethodTableGenericCtx;

Context::Context() : pImpl(gMethodTableGenericCtx.Create(this, &gMethodTableCtx)){}

Context::~Context() { gMethodTableGenericCtx.Delete(pImpl);}

Page 62: CIB - Meeting C++

62

Client side interface definition

extern "C" MethodTableGenericCtx DLLIMPORT gMethodTableGenericCtx;

Context::Context() : pImpl(gMethodTableGenericCtx.Create(this, &gMethodTableCtx)){}

Context::~Context() { gMethodTableGenericCtx.Delete(pImpl);}

Page 63: CIB - Meeting C++

63

Implementation of proxy class

class CircleImpl;

class Circle {public: Circle(float r); ~Circle();

void Draw(Context* pCtx) const;

private: Circle(CircleImpl* pCircleImpl); CircleImpl* pImpl;};

extern "C" MethodTableCircle DLLIMPORT gMethodTableCircle;

Circle::Circle(CircleImpl* pCircleImpl) : pImpl (pCircleImpl){}

Circle::Circle(float r) : Circle(gMethodTableCircle.Create(r)){}

Circle::~Circle() { gMethodTableCircle.Delete(pImpl);}

void Circle::Draw(Context* pCtx) const { return gMethodTableCircle.Draw(

pImpl, pCtx->pImpl);}

Page 64: CIB - Meeting C++

64

Interface Classes

class Context {public: virtual ~Context() {}

virtual void DrawCircle(float r) = 0;};

class Circle {public: Circle(float r) : mRadius(r) {}

void Draw(Context* pCtx) const { pCtx->DrawCircle(mRadius); }

private: float mRadius;};

Library Client

class DrawLogger : public Context { void DrawCircle(float r) override { std::cout << "DrawCircle(" << r << ")"; }};

int main() { DrawLogger logger; Circle c(5.0); c.Draw(&logger);}

Page 65: CIB - Meeting C++

65

Interface Classes

class Context {public: virtual ~Context() {}

virtual void DrawCircle(float r) = 0;};

class Circle {public: Circle(float r) : mRadius(r) {}

void Draw(Context* pCtx) const { pCtx->DrawCircle(mRadius); }

private: float mRadius;};

Library Client

class DrawLogger : public Context { void DrawCircle(float r) override { std::cout << "DrawCircle(" << r << ")"; }};

int main() { DrawLogger logger; Circle c(5.0); c.Draw(&logger);}

Page 66: CIB - Meeting C++

66

Interface Classes

class Context {public: virtual ~Context() {}

virtual void DrawCircle(float r) = 0;};

class Circle {public: Circle(float r) : mRadius(r) {}

void Draw(Context* pCtx) const { pCtx->DrawCircle(mRadius); }

private: float mRadius;};

Library Client

class DrawLogger : public Context { void DrawCircle(float r) override { std::cout << "DrawCircle(" << r << ")"; }};

int main() { DrawLogger logger; Circle c(5.0); c.Draw(&logger);}

Page 67: CIB - Meeting C++

67

Interface Classes

class Context {public: virtual ~Context() {}

virtual void DrawCircle(float r) = 0;};

class Circle {public: Circle(float r) : mRadius(r) {}

void Draw(Context* pCtx) const { pCtx->DrawCircle(mRadius); }

private: float mRadius;};

Library Client

class DrawLogger : public Context { void DrawCircle(float r) override { std::cout << "DrawCircle(" << r << ")"; }};

int main() { DrawLogger logger; Circle c(5.0); c.Draw(&logger);}

Page 68: CIB - Meeting C++

68

Auto generating glue code

● We can have a tool that can generate all this glue code automatically.

Page 69: CIB - Meeting C++

69

Glue code for next version

● Glue code generation for next version can use MethodTable of previous version.

● We saw this tool in action in the demo

Page 70: CIB - Meeting C++

70

Case Study (with PoDoFo library)

● PoDoFo is an open source PDF library with about 200 classes.

● Created cibified library and tested results.● Examples and tests are run and results

compared.● To auto implement glue code I developed a

tool github.com/satya-das/cib and used it for the case study.

Page 71: CIB - Meeting C++

71

Case Study Report

Runtime Performance

AVERAGE diff +0.08 sec +0.41%

Library Binary Size

Size Diff +3366 KB +198%

Memory Usage

AVERAGE Memory Diff +2,127,705 B +4.26%

Client Binary Size (Cummulative)

Cumulative Size Diff +1989 KB +94%

Page 72: CIB - Meeting C++

72

Case Study Report

Runtime Performance

AVERAGE diff +0.08 sec +0.41%

Library Binary Size

Size Diff +3366 KB +198%

Memory Usage

AVERAGE Memory Diff +2,127,705 B +4.26%

Client Binary Size (Cummulative)

Cumulative Size Diff +1989 KB +94%

Page 73: CIB - Meeting C++

73

Case Study Report

Runtime Performance

AVERAGE diff +0.08 sec +0.41%

Library Binary Size

Size Diff +3366 KB +198%

Memory Usage

AVERAGE Memory Diff +2,127,705 B +4.26%

Client Binary Size (Cummulative)

Cumulative Size Diff +1989 KB +94%

Page 74: CIB - Meeting C++

74

Case Study Report

Runtime Performance

AVERAGE diff +0.08 sec +0.41%

Library Binary Size

Size Diff +3366 KB +198%

Memory Usage

AVERAGE Memory Diff +2,127,705 B +4.26%

Client Binary Size (Cummulative)

Cumulative Size Diff +1989 KB +94%

Page 75: CIB - Meeting C++

75

What’s more

● std::unique_ptr

● std::shared_ptr

● Intrusive pointers

● std::function

● lambda

● RTTI

● Templates

● Exceptions

● Object lifecycle management

Most things are possible and examples are already available atgithub.com/satya-das/cib

● STL objects

● Global functions

● Protected methods

● Conditional APIs

● POD struct

● Value classes

● Rvalue Reference

● Etc.

Page 76: CIB - Meeting C++

Thank You!!