Structs implementing interfaces in D1

Chad J gamerchad at __spam.is.bad__gmail.com
Mon Feb 9 20:32:57 PST 2009


Tom S wrote:
> /** Just a simple hack to have interfaces implemented by structs ...
> because I can :P
> Tested on DMD 1.039 [win32], GDC (various versions) [linux32] and
> codepad.org
> 
> Output:
> 
> Entering main
> Foo.func1 called ; val1 = 3.141590, val2 = Hello, world!
> Foo.func2 called ; val1 = 3.141590, val2 = Hello, world!
> Foo.func2 called ; val1 = 3.141590, val2 = Hello, world!
> Foo.func3 called ; val1 = 3.141590, val2 = Hello, world! ; p1 = 123, p2
> = some parameter
> Leaving main
> */
> 
> 
> module structIface;
> 
> extern (C) int printf(char*, ...);
> 
> 
> 
> // ---- evil implementation
> char[] structImplementInterface(char[] iface, char[][] funcs) {
>     char[] res = "private {";
>     res ~= \n"alias typeof(*this) _iface_"~iface~"_ThisType;";
> 
>     foreach (func; funcs) {
>         res ~= \n"static assert (is(typeof(&"~iface~".init."~func~")),
>             `The interface "~iface~" doesn't declare a '"~func~"'
> function, `
>             `thus struct `~_iface_"~iface~"_ThisType.stringof~` cannot
> implement it`);";
>         res ~= \n"static void _iface_" ~ iface ~ "_func_" ~ func ~ "() {";
>         version (GNU) {
>             res ~= \n\t"asm { naked; sub dword ptr 4[ESP], _iface_" ~
> iface ~ "_vtbl.offsetof; jmp " ~ func ~ "; }";
>         } else {
>             res ~= \n\t"asm { naked; sub EAX, _iface_" ~ iface ~
> "_vtbl.offsetof; jmp " ~ func ~ "; }";
>         }
>         res ~= \n"}";
>     }
>     res ~= \n ~ iface ~ " as" ~ iface ~ "() {";
>     res ~= \n\t"return cast("~iface~")cast(void*)&_iface_" ~ iface ~
> "_vtbl;";
>     res ~= \n"}";
> 
>     res ~= \n"void** _iface_" ~ iface ~ "_vtbl = cast(void**)([";
>     res ~= \n\t"null";        // for classinfo
>     foreach (func; funcs) {
>         res ~= ",\n\tcast(void*)&Foo._iface_" ~ iface ~ "_func_" ~ func;
>     }
>     res ~= \n"]).ptr;";
>     res ~= "}";
> 
>     return res;
> }
> // ---- end of the evil implementation
> 
> 
> interface IFoo {
>     void func1();
>     void func2();
> }
> 
> interface IBar {
>     void func2();
>     void func3(int, char[]);
> }
> 
> 
> struct Foo {
>     float val1;
>     char[] val2;
> 
>     void func1() {
>         printf("Foo.func1 called ; val1 = %f, val2 = %.*s"\n, val1, val2);
>     }
> 
>     void func2() {
>         printf("Foo.func2 called ; val1 = %f, val2 = %.*s"\n, val1, val2);
>     }
> 
>     void func3(int p1, char[] p2) {
>         printf("Foo.func3 called ; val1 = %f, val2 = %.*s ; p1 = %d, p2
> = %.*s"\n, val1, val2, p1, p2);
>     }
> 
>     mixin(structImplementInterface("IFoo", ["func1", "func2"]));
>     mixin(structImplementInterface("IBar", ["func2", "func3"]));
> }
> 
> 
> void main() {
>     printf("Entering main"\n);
> 
>     Foo f;
>     f.val1 = 3.14159f;
>     f.val2 = "Hello, world!";
> 
>     IFoo fi = f.asIFoo;
>     fi.func1();
>     fi.func2();
> 
>     IBar bi = f.asIBar;
>     bi.func2();
>     bi.func3(123, "some parameter");
> 
>     printf("Leaving main"\n);
> }
> 
> 
> /**
> The concept is pretty simple. The mixin creates a vtable which points to
> a set of generated functions of the form { adjust the 'this' ptr; jump
> to the real function; }. Finally, the "InterfaceName asInterfaceName()"
> functions generated inside the struct return pointers to the
> corresponding vtables.
> 
> Now this would be so much nicer if there was a way to iterate the
> functions of an interface at compile time in D1... Can we have D1 plus
> __traits? Pleaaaase? Pretty please with a cherry on top?
> 
> Thanks to downs, Hxal and Jarrett!
> */
> 
> 

Hawt!

I take it this can be done without assembly?



More information about the Digitalmars-d mailing list