Jump to page: 1 2 3
Thread overview
Vtable for virtual functions in D
Mar 06, 2018
Henrik
Mar 07, 2018
sarn
Mar 07, 2018
Patrick Schluter
Mar 07, 2018
Patrick Schluter
Mar 07, 2018
Guillaume Piolat
Mar 07, 2018
Henrik
Mar 07, 2018
H. S. Teoh
Apr 03, 2018
Laeeth Isharc
Mar 07, 2018
sarn
Mar 08, 2018
Mike Franklin
Mar 08, 2018
sarn
Apr 02, 2018
sarn
Apr 02, 2018
Mike Franklin
Apr 03, 2018
Kagamin
Mar 08, 2018
Guillaume Piolat
Mar 08, 2018
Henrik
Mar 09, 2018
sarn
Mar 09, 2018
Manu
Apr 03, 2018
Mike Franklin
Apr 03, 2018
sarn
Apr 03, 2018
Kagamin
March 06, 2018
Does anyone know if D is using the vtable implementation for virtual functions just like most C++ compilers? If yes, can someone explain the advantages of this strategy? A function pointer in C is regarded as expensive because of missing inlining, but a double indirection through a vtable just looks insane - if there aren't really good reasons for such an implementation. Does it make class inheritance or class polymorphism much simpler to implement or what is the reason?

I have worked with C in embedded systems for many years now, and for our modern Linux systems we are using a combination of C and Java today. Java for parts where memory safety is more important than speed/determinism, and C for the critical real time parts. There should exist a language between these worlds, where we can achieve memory safety at relatively small costs. C++ is not really an alternative, and D looks much more pleasant for us C programmers than for example Rust.

March 07, 2018
On Tuesday, 6 March 2018 at 21:20:22 UTC, Henrik wrote:
> Does anyone know if D is using the vtable implementation for virtual functions just like most C++ compilers? If yes, can someone explain the advantages of this strategy? A function pointer in C is regarded as expensive because of missing inlining, but a double indirection through a vtable just looks insane - if there aren't really good reasons for such an implementation. Does it make class inheritance or class polymorphism much simpler to implement or what is the reason?
>
> I have worked with C in embedded systems for many years now, and for our modern Linux systems we are using a combination of C and Java today. Java for parts where memory safety is more important than speed/determinism, and C for the critical real time parts. There should exist a language between these worlds, where we can achieve memory safety at relatively small costs. C++ is not really an alternative, and D looks much more pleasant for us C programmers than for example Rust.

D uses vtables.

It's a tradeoff between having double indirection and bloating each instance with the function pointers.  In cases where bloating isn't a problem, I just explicitly add normal function pointer members.
March 07, 2018
On Tuesday, 6 March 2018 at 21:20:22 UTC, Henrik wrote:
> Does anyone know if D is using the vtable implementation for virtual functions just like most C++ compilers? If yes, can someone explain the advantages of this strategy? A function pointer in C is regarded as expensive because of missing inlining, but a double indirection through a vtable just looks insane - if there aren't really good reasons for such an implementation. Does it make class inheritance or class polymorphism much simpler to implement or what is the reason?
>
> I have worked with C in embedded systems for many years now, and for our modern Linux systems we are using a combination of C and Java today. Java for parts where memory safety is more important than speed/determinism, and C for the critical real time parts. There should exist a language between these worlds, where we can achieve memory safety at relatively small costs. C++ is not really an alternative, and D looks much more pleasant for us C programmers than for example Rust.

p0nce[1] has a link to an excellent article explaining in detail how the implementation of the vtable, single inheritance with interfaces work. The article isn't about D per se but D classes use the same mechanism.

[1]: https://p0nce.github.io/d-idioms/#Inside-the-D-Object-Model
March 07, 2018
On Tuesday, 6 March 2018 at 21:20:22 UTC, Henrik wrote:
>
> I have worked with C in embedded systems for many years now, and for our modern Linux systems we are using a combination of C and Java today. Java for parts where memory safety is more important than speed/determinism, and C for the critical real time parts. There should exist a language between these worlds, where we can achieve memory safety at relatively small costs. C++ is not really an alternative, and D looks much more pleasant for us C programmers than for example Rust.

D is the perfect fit for your description. Converting java to D can be surprisingly easy, unless one used a lot of libraries which are quite different.
As for C, I'm of the opinion that D is much more respectful of its C heritage than even C++ is.
March 07, 2018
On Tuesday, 6 March 2018 at 21:20:22 UTC, Henrik wrote:
> Does anyone know if D is using the vtable implementation for virtual functions just like most C++ compilers?

Yes, except without multiple inheritance / virtual inheritance.

> If yes, can someone explain the advantages of this strategy? A function pointer in C is regarded as expensive because of missing inlining, but a double indirection through a vtable just looks insane - if there aren't really good reasons for such an implementation.

Without measuring, I'd tend to agree with you that it should be more expensive (let's not use the arguments that "this part of memory will be hot" which means it will take a share of cache that could go to something else).

I guess the reason is simple: low overhead with regards to layout (only a pointer gets added to each instance). The v-table point itself to TypeInfo so you hide this pointer too.
TypeInfo is a bit like RTTI in the C++ world.

Note that even in C++ if a virtual call is expensive in the profiler you can switch on a type tag and devirtualize by casting (virtual functions are only expensive when the runtime type is unknown to the compiler).

The alternative layout is to embed the v-table in each object when priming a new object, and having the TypeInfo pointer in each class instance in addition to a pointer for each virtual method.

> Does it make class inheritance or class polymorphism much simpler to implement or what is the reason?

I don't know. Intuitively it doesn't seem much easier with v-table.
COM objects are expected to have such a layout too.

> I have worked with C in embedded systems for many years now, and for our modern Linux systems we are using a combination of C and Java today. Java for parts where memory safety is more important than speed/determinism, and C for the critical real time parts. There should exist a language between these worlds, where we can achieve memory safety at relatively small costs. C++ is not really an alternative, and D looks much more pleasant for us C programmers than for example Rust.

If you know enough D maybe you can implement your own virtual functions on top of D structs. It seems no one has made it yet.


March 07, 2018
Hi everyone,

thank you all for your great answers. I'm playing around with @nogc right now, and it looks really promising. Strings and static arrays all seem to be located on the stack, which is so much better compared to std::string and std::vector in C++. The double indirection for virtual functions bother me, and it isn't getting better with all methods being virtual by default - I guess I'll be writing the keyword "final" very intensively in all my programs. I would also gladly pay some bytes in pointer bloat to have my virtual functions speed up. Strange that D kept the vtable approach when breaking with C++.

I know that D concentrated much on C++ compatibility a while ago. Are there any plans to support the direct inclusion on C header files? Many important libraries like ICU have C interfaces even when written in C++. The direct support of C headers would be very convenient in migrating parts of C/C++ projects to D. It would also open up POSIX which is used extensively in our work.

This looks great:
https://github.com/D-Programming-Deimos/
but it must be tedious to keep such files up to date.

Despite the point where I'm complaining, I must say that D looks very impressive. Beautiful syntax, large standard library, and standardized inline assembler (Thank you!). I'll definitely try to find a suitable project to try out D under serious conditions.

March 07, 2018
On Wednesday, 7 March 2018 at 12:49:40 UTC, Guillaume Piolat wrote:
> If you know enough D maybe you can implement your own virtual functions on top of D structs. It seems no one has made it yet.

When I wrote Xanthe a year ago, I rolled my own classes using alias this and explicit vtables:
https://gitlab.com/sarneaud/xanthe/blob/master/src/game/rigid_body.d#L15
(I did this because normal D classes use the druntime library, and Xanthe was an experiment in not using the D runtime at all.)

Henrik: you might be interested in this post I wrote about making that:
https://theartofmachinery.com/2017/02/28/bare_metal_d.html
NB: things are moving fast and some things have already improved since then.
March 07, 2018
On Wed, Mar 07, 2018 at 09:14:12PM +0000, Henrik via Digitalmars-d wrote: [...]
> The direct support of C headers would be very convenient in migrating parts of C/C++ projects to D. It would also open up POSIX which is used extensively in our work.
[...]

There's already core.sys.posix.*, which are POSIX headers translated into D, and which you can import and use right away. E.g.:

	import core.sys.posix.unistd;
	char[1024] buf;
	int fd = open("/tmp/file", O_RDONLY);
	auto len = read(fd, buf.ptr, buf.length);
	...
	close(fd);

Similarly, C standard library functions are directly available via core.stdc.*:

	import core.stdc.stdlib;
	void* buf = malloc(1024);
	... // use buf here
	free(buf);

In principle, although direct support of C headers is not supported (yet?), it's pretty easy to declare C functions in D and then just call it directly, e.g.:

	// Declare C function here
	extern(C) size_t strlen(const(char)* s);

	void main()
	{
		import std.string : toStringz;

		// Call here
		auto len = strlen("blah blah".toStringz);
	}

In the above example I purposely used std.string to showcase how easy it is to interoperate with C API functions, with toStringz and fromStringz providing convenient conversions to/from C's char* strings.  The only wrinkle here is that toStringz may allocate (because D strings are not null-terminated in general), so cannot be used in @nogc code.

However, D string *literals* are always null-terminated, so the above code could actually be replaced with just:

	auto len = strlen("blah blah".ptr);

and it will work in @nogc as well. Just be careful not to do that with non-literal strings (or append a null manually and then it should be safe).

The trouble with general C headers is that sometimes complicated macros are used, and D does not come with a C macro processor, so it is tricky to interface with those kinds of headers.  Still, if your code is not directly dependent on the macros, you could just run the header through a C preprocessor and then translate the C prototypes into D.  (There are some cases for which this may not be so straightforward, but generally you should be able to get quite far this way.)


T

-- 
Caffeine underflow. Brain dumped.
March 08, 2018
On Wednesday, 7 March 2018 at 22:02:17 UTC, sarn wrote:

> When I wrote Xanthe a year ago, I rolled my own classes using alias this and explicit vtables:
> https://gitlab.com/sarneaud/xanthe/blob/master/src/game/rigid_body.d#L15
> (I did this because normal D classes use the druntime library, and Xanthe was an experiment in not using the D runtime at all.)

Nice!  I was thinking about something almost exactly like this recently since 2.079.0 has features to further decouple the language from the runtime.  It would be nice to read a blog post about this technique.

Mike


March 08, 2018
On Wednesday, 7 March 2018 at 22:02:17 UTC, sarn wrote:
> On Wednesday, 7 March 2018 at 12:49:40 UTC, Guillaume Piolat wrote:
>> If you know enough D maybe you can implement your own virtual functions on top of D structs. It seems no one has made it yet.
>
> When I wrote Xanthe a year ago, I rolled my own classes using alias this and explicit vtables:
> https://gitlab.com/sarneaud/xanthe/blob/master/src/game/rigid_body.d#L15
> (I did this because normal D classes use the druntime library, and Xanthe was an experiment in not using the D runtime at all.)
>
> Henrik: you might be interested in this post I wrote about making that:
> https://theartofmachinery.com/2017/02/28/bare_metal_d.html
> NB: things are moving fast and some things have already improved since then.

Very interesting
« First   ‹ Prev
1 2 3