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