Skip to content

Instantly share code, notes, and snippets.

@gaspardpetit
Created February 27, 2022 16:13
Show Gist options
  • Select an option

  • Save gaspardpetit/fe03058210154dcd440033dd39c83919 to your computer and use it in GitHub Desktop.

Select an option

Save gaspardpetit/fe03058210154dcd440033dd39c83919 to your computer and use it in GitHub Desktop.
Sample code to demonstrate how to implement a C++ object in plan C; Works only in Microsoft VS - where the vtable starts with the function pointers, as used by COM objects
#include <new>
///////
// Sample code to demonstrate how to implement a C++ object in plan C
// Works only in Microsoft VS - where the vtable starts with the function
// pointers, as used by COM objects
///////
// The C++ interface we wish to implement
class ICppA {
public:
virtual ~ICppA() {}
virtual double add(double v) = 0;
virtual double sub(double v) = 0;
virtual double get() = 0;
};
// A real C++ implementation, used for comparison
class CppA : public ICppA {
private:
double total = 0;
public:
virtual ~CppA() override {}
virtual double add(double v) override { return (total += v); }
virtual double sub(double v) override { return (total -= v); }
virtual double get() override { return total ; }
};
// The plain C implementation of the C++ interface
extern "C" {
typedef struct CA CA;
// The plain C vtable
struct CA_VTable {
void (*dtor)(CA* self);
double (*add)(CA* self, double v);
double (*sub)(CA* self, double v);
double (*get)(CA* self);
};
// The plain C implementation
struct CA {
CA_VTable* _vtable;
double total;
};
void CA_DTor(CA* o) {}
double CA_Add(CA* o, double v) { return (o->total += v); }
double CA_Sub(CA* o, double v) { return (o->total -= v); }
double CA_Get(CA* o) { return o->total; }
// Create a static vtable that all instances can use
static CA_VTable _CA_VTable = {
CA_DTor,
CA_Add,
CA_Sub,
CA_Get
};
void CA_CTor(CA* ca) { ca->_vtable = &_CA_VTable; ca->total = 0; }
} // extern "C"
// our objects should have a vtable pointer and a double
static_assert(sizeof(CppA) == sizeof(void*) + sizeof(double), "false");
static_assert(sizeof(CA) == sizeof(void*) + sizeof(double), "false");
// demonstrate that both the real C++ implementation and C implementation behave the same way
#include <iostream>
void testA(ICppA* a)
{
std::cout << "initial value: " << a->get() << std::endl;
std::cout << "add 5: " << a->add(5) << std::endl;
std::cout << "sub 2: " << a->sub(2) << std::endl;
}
int main()
{
CppA cppa;
testA(&cppa);
CA ca;
CA_CTor(&ca);
testA((ICppA*)&ca);
CA_DTor(&ca);
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment