CIB C omponent I nterface B inder: ABI stable architecture for a C++ - - PowerPoint PPT Presentation

cib
SMART_READER_LITE
LIVE PREVIEW

CIB C omponent I nterface B inder: ABI stable architecture for a C++ - - PowerPoint PPT Presentation

CIB C omponent I nterface B inder: ABI stable architecture for a C++ SDK Satya Das About me A developer at T omT om Previously I was at Adobe 2 ABI Stability Binary compatibility of older client with new library 3 Agenda ABI


slide-1
SLIDE 1

CIB

Component Interface Binder:

ABI stable architecture for a C++ SDK

Satya Das

slide-2
SLIDE 2

2

About me

  • A developer at T
  • mT
  • m
  • Previously I was at Adobe
slide-3
SLIDE 3

3

ABI Stability

Binary compatibility of older client with new library

slide-4
SLIDE 4

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
slide-5
SLIDE 5

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;

};

slide-6
SLIDE 6

6

Hourglass Interface

slide-7
SLIDE 7

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
slide-8
SLIDE 8

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 fjrst parameter as pointer of the class.

slide-9
SLIDE 9

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

slide-10
SLIDE 10

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

slide-11
SLIDE 11

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

slide-12
SLIDE 12

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

slide-13
SLIDE 13

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;

slide-14
SLIDE 14

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);

}

slide-15
SLIDE 15

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);

}

slide-16
SLIDE 16

16

Proxy Class Sequence Diagram

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

slide-17
SLIDE 17

17

Class use sequence diagram

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

slide-18
SLIDE 18

18

Class use sequence diagram

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

slide-19
SLIDE 19

19

Class use sequence diagram

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

slide-20
SLIDE 20

20

Class use sequence diagram

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

slide-21
SLIDE 21

21

Class use sequence diagram

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

slide-22
SLIDE 22

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;

};

slide-23
SLIDE 23

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

MethodT able is only appended

slide-24
SLIDE 24

24

MethodTable Vs Virtual Table

  • MethodT

able is NOT replacement of virtual table.

slide-25
SLIDE 25

25

MethodTable Vs Virtual Table

  • MethodT

able is NOT replacement of virtual table.

  • MethodT

able is just a mechanism for cross component function call.

slide-26
SLIDE 26

26

MethodTable Vs Virtual Table

  • MethodT

able is NOT replacement of virtual table.

  • MethodT

able is just a mechanism for cross component function call.

  • MethodT

able is shared between components.

slide-27
SLIDE 27

27

MethodTable Vs Virtual Table

  • MethodT

able is NOT replacement of virtual table.

  • MethodT

able is just a mechanism for cross component function call.

  • MethodT

able is shared between components.

  • Virtual table remains local.
slide-28
SLIDE 28

28

MethodTable Vs Virtual Table

  • MethodT

able is NOT replacement of virtual table.

  • MethodT

able is just a mechanism for cross component function call.

  • MethodT

able is shared between components.

  • Virtual table remains local.
  • MethodT

able is handy in supporting backward compatibility.

slide-29
SLIDE 29

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;

};

slide-30
SLIDE 30

30

Client’s Backward Compatiblity

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

slide-31
SLIDE 31

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

slide-32
SLIDE 32

32

MethodTable Vs Virtual Table

  • MethodT

able is NOT replacement of virtual table.

  • MethodT

able is just a mechanism for cross component function call.

  • MethodT

able is shared between components.

  • Virtual table remains local.
  • MethodT

able is handy in supporting backward compatibility.

  • MethodT

able does NOT inherit.

slide-33
SLIDE 33

33

EXAMPLE 2

INHERITANCE

slide-34
SLIDE 34

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

slide-35
SLIDE 35

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

slide-36
SLIDE 36

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

slide-37
SLIDE 37

37

Inheritance

MethodT able 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 };

}

slide-38
SLIDE 38

38

Inheritance

MethodT able 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 };

}

slide-39
SLIDE 39

39

Inheritance

MethodT able 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

slide-40
SLIDE 40

40

Inheritance

Base Class defjnition 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);

}

slide-41
SLIDE 41

41

Inheritance

Derived Class defjnition 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); }

slide-42
SLIDE 42

42

Inheritance

CLIENT LIBRARY V1

Base

pImpl

Base

pImpl

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

slide-43
SLIDE 43

43

Inheritance

CLIENT LIBRARY V2

Base

pImpl

Base2

pImpl

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

Base

slide-44
SLIDE 44

44

EXAMPLE 3

INTERFACE CLASS

slide-45
SLIDE 45

45

Interface Class Demo

slide-46
SLIDE 46

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

slide-47
SLIDE 47

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

slide-48
SLIDE 48

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

slide-49
SLIDE 49

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

slide-50
SLIDE 50

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

slide-51
SLIDE 51

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

slide-52
SLIDE 52

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

slide-53
SLIDE 53

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

slide-54
SLIDE 54

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

slide-55
SLIDE 55

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

slide-56
SLIDE 56

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

slide-57
SLIDE 57

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);

}

slide-58
SLIDE 58

58

Client side interface defjnition

class ContextImpl; class Context { public: virtual ~Context(); virtual void DrawCircle(float r) = 0; ContextImpl* const pImpl; protected: Context(); };

slide-59
SLIDE 59

59

Client side interface defjnition

class ContextImpl; class Context { public: virtual ~Context(); virtual void DrawCircle(float r) = 0; ContextImpl* const pImpl; protected: Context(); };

slide-60
SLIDE 60

60

Client side interface defjnition

class ContextImpl; class Context { public: virtual ~Context(); virtual void DrawCircle(float r) = 0; ContextImpl* const pImpl; protected: Context(); };

slide-61
SLIDE 61

61

Client side interface defjnition

extern "C" MethodTableGenericCtx DLLIMPORT gMethodTableGenericCtx; Context::Context() : pImpl(gMethodTableGenericCtx.Create(this, &gMethodTableCtx))

{}

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

}

slide-62
SLIDE 62

62

Client side interface defjnition

extern "C" MethodTableGenericCtx DLLIMPORT gMethodTableGenericCtx; Context::Context() : pImpl(gMethodTableGenericCtx.Create(this, &gMethodTableCtx))

{}

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

}

slide-63
SLIDE 63

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

slide-64
SLIDE 64

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

slide-65
SLIDE 65

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

slide-66
SLIDE 66

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

slide-67
SLIDE 67

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

slide-68
SLIDE 68

68

Auto generating glue code

  • We can have a tool that can generate all this

glue code automatically.

slide-69
SLIDE 69

69

Glue code for next version

  • Glue code generation for next version can

use MethodT able of previous version.

  • We saw this tool in action in the demo
slide-70
SLIDE 70

70

Case Study (with PoDoFo library)

  • PoDoFo is an open source PDF library with

about 200 classes.

  • Created cibifjed library and tested results.
  • Examples and tests are run and results

compared.

  • T
  • auto implement glue code I developed a

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

slide-71
SLIDE 71

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%

slide-72
SLIDE 72

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%

slide-73
SLIDE 73

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%

slide-74
SLIDE 74

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%

slide-75
SLIDE 75

75

What’s more

  • std::unique_ptr
  • std::shared_ptr
  • Intrusive pointers
  • std::function
  • lambda
  • RTTI
  • T

emplates

  • Exceptions
  • Object lifecycle management

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

  • STL objects
  • Global functions
  • Protected methods
  • Conditional APIs
  • POD struct
  • Value classes
  • Rvalue Reference
  • Etc.
slide-76
SLIDE 76

Thank You!!