www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - interface ABI

reply mpt <foo bar.com> writes:
I wrote a scripting system where the virtual machine relies on storing
objects in void* pointers. The problem is that D handles interfaces and
classes differently. The code below prints different addresses (8 byte
offset) when Base is an interface, but same addresses when it is a class.
So my question is, why are they different like this?

Another thing I found is that when Base is an interface, the resulting
machine code is 5 operations longer (and slower). The extra code checks if
the cast object is null and calculates the offset.

import std.stdio;

interface Base {
    void Func();
}

class Foo : Base {
    void Func() {}
}

void main( char[][] args ) {
    Foo f = new Foo();
    Base b = f;

    writefln( cast(void*)f );
    writefln( cast(void*)b );

    f.Func();
    b.Func();
}
Jan 31 2007
parent BCS <BCS pathlink.com> writes:
mpt wrote:
 I wrote a scripting system where the virtual machine relies on storing
 objects in void* pointers. The problem is that D handles interfaces and
 classes differently. The code below prints different addresses (8 byte
 offset) when Base is an interface, but same addresses when it is a class.
 So my question is, why are they different like this?
 
 Another thing I found is that when Base is an interface, the resulting
 machine code is 5 operations longer (and slower). The extra code checks if
 the cast object is null and calculates the offset.
 
 import std.stdio;
 
 interface Base {
     void Func();
 }
 
 class Foo : Base {
     void Func() {}
 }
 
 void main( char[][] args ) {
     Foo f = new Foo();
     Base b = f;
 
     writefln( cast(void*)f );
     writefln( cast(void*)b );
 
     f.Func();
     b.Func();
 }

An interface is implemented by adding a second v-table pointer to the class. The layout of the vtable is defined by the interface and includes an offset to the start of the object. calling a interface method should look something like this size_t* inter; // pointer to interface inter[indexOfMethoud](inter+inter[0], args...) Calling a class member looks something like this size_t* inter; // pointer to interface inter[indexOfMethoud](inter, args...) <rant> Personally I'd like to see interfaces implemented as fat pointers carrying the object (or context) pointer and the vtable pointer separately. This would result in this code: size_t[2]* inter; // array of 2 ptrs inter[1][indexOfMethoud](inter[0], args...) This would allow structs to implement interfaces without having to add a vtable to them (thus keeping them a POD). Also other things like functions would be able to implement interfaces just as you can get a delegate from a function, struct or class.
Jan 31 2007