Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

small-c/obj.h

Open more actions menu

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

204 Commits
204 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

obj.h

A single-header supports OOP in pure C.
Using power of preprocessor and hacking on assembly to unlock the limits.

Foo f = new(Foo)(10);       // create Foo instance
assert(f->get() == 10);     // get value
f->base.release();          // release

Features

  • C++/Java inspired OOP
    • Public, private members
    • Constructor, destructor
    • Abstraction
    • Inheritance
  • Zero dependency
  • No breaking editor's intellisense
  • x86/_64 target
  • arm target

Usage

  • Just add obj.h to your C source
  • See tests for more

C++ comparison:

// C++ native OOP               // C with obj.h
class Foo {                 |   class(Foo, public(
public:                     |       int (*get)();
    Foo(int bar);           |   ), private(
    int get();              |       int bar;
private:                    |   ));
    int bar;                |
};                           |   ctor(Foo)(int bar) {
                            |       obj_setup(Foo);
Foo::Foo(int bar) {         |       obj_bind(Foo, get);
    this->bar = bar;        |       self->bar = bar;
}                           |       obj_done(Foo);
                            |   }
int Foo::get() {            |
    return this->bar;       |   method(Foo, int, get)() {
}                           |       obj_prepare(Foo);
                            |       return self->bar;
                            |   }
                            |
Foo *f = new Foo(15);       |   Foo f = new(Foo)(15);
f->get();                   |   f->get();
delete f;                   |   f->base.release();

Platform support:

GCC 4+ MSVC 14+ Clang 5+ TCC 0.9
Windows (x86 / x64) βœ… βœ… βœ… βœ…
Linux (i386 / x86_x64) βœ… _ βœ… βœ…
Mac OSX (i386 / x86_64) βœ… _ βœ… _

How it works?

We can't explain in detail, but something like binding this to a function in JavaScript.

Simulate a simple class with struct:

struct A {
    void (* todo)();  // method
};

And we have a static function:

static void fn_todo() {}

Next, bind A instance (aka this) to fn_todo πŸ™„

binded_todo = bind(fn_todo, myA);

Finally 😎

myA->todo = binded_todo;
myA->todo();    // call it like a method

Closure function?

  • This is a fork of yulon/clofn
  • Just copy function header and inject some code to pre-allocate this inside
  • Currently, support x86 and x86_64 only

Function template:

static void fn_todo() {
    volatile size_t self = ...;
    ...

Disassemble:

; prolog
    mov     rax, ...
    mov     QWORD PTR [rbp-8], rax
    ...

Generated function:

 [copied prolog]
> x86
| mov     eax, [data]
| jmp     [addr]
> x86_64
| mov     rax, [data]
| push    rax
| mov     rax, [addr]
| jmp     rax

Refs:

How we provide classes, public/private?

See obj.h for more.


ko-fi

Contributors

Languages

Morty Proxy This is a proxified and sanitized view of the page, visit original site.