On Saturday, 17 June 2023 at 12:34:41 UTC, Dibyendu Majumdar wrote:
> Hi
I am looking for details of how interface method dispatch works in D.
I would be grateful for any documentation of code references I can lookup.
In particular, I wanted to understand how similar / different the implementation is compared to Java.
Regards
Dibyendu
Note: While writing this answer, I found the actual specified answer in the D ABI docs: https://dlang.org/spec/abi.html#classes
I still think this explanation is good though.
I don't know for sure, but I think pretty much every single-inheritance with interface implementation in a C-like language works like this:
You have a class C. C has a vtable of dynamic methods:
C {
C_VTable* __vtable;
classdata goes here
}
C_VTable {
void function(void*) method1;
void function(void*) method2;
void function(void*) method3;
}
You have a class D that inherits from C. It starts with a pointer to a D_VTable, that looks like this:
D_VTable {
// all methods that D overrides are replaced in the C part
C_VTable parent;
// methods that only appear in D go here
void function(void*) method4;
}
It has to be like this, so that you can take a pointer to D and implicitly treat it as a pointer to C.
Now what about interfaces? They're a bit complicated.
Obviously an interface pointer cannot be the same pointer as the class pointer of the class that implements it. Because the interface methods would have to be at a fixed offset from the start of the vtable, and then they could collide with methods added by the class. So an interface reference is an additional vtable pointer in the object, that points at a dedicated interface vtable. That vtable usually also has the offset from the vtable pointer to the start of the object, because we need that to get the object reference back so we can actually call methods with it.
C : I
{
C_VTable* __vtable;
C data goes here.
// I i = c; results in a pointer *to this field.*
I_VTable* __i_vtable;
}
I_VTable {
size_t i_to_c_offset = -20; // or whatever
void function(void*) i_method_1;
void function(void*) i_method_2;
void function(void*) i_method_3;
}
Anyway, how does all that compare to Java? No clue! Sorry. I can only assume it's pretty similar, because this is really is the "unambiguously sensible" way to do it.