January 31, 2007 interface ABI | ||||
---|---|---|---|---|
| ||||
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(); } |
January 31, 2007 Re: interface ABI | ||||
---|---|---|---|---|
| ||||
Posted in reply to mpt | 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. |
Copyright © 1999-2021 by the D Language Foundation