extern(C++) and struct (constness mangling problem ?)

Martin Nowak dawg at dawgfoto.de
Tue Nov 29 11:28:36 PST 2011


On Tue, 29 Nov 2011 19:50:10 +0100, deadalnix <deadalnix at gmail.com> wrote:

> Le 29/11/2011 18:08, Martin Nowak a écrit :
>> On Tue, 29 Nov 2011 16:46:55 +0100, deadalnix <deadalnix at gmail.com>  
>> wrote:
>>> Notably, it's very difficult to map a C++ POD class with a default
>>> constructor and copy constructor/assignement overload. struct doesn't
>> Don't want to be picky, but a struct with default constructor is not a  
>> POD.
>> And yes it is not possible to map all C++ concepts to D.
>>
>
> OK, usage of POD was not the right term. But as matter of fact, C++  
> gives you 2 general direction to use structs/classes :
> 1/ You make your struct/class non copyable (making copy constructor and  
> assignement operator private for exemple), the destructor virtual and  
> use it as a polymorphic type. This is what D's class is supposed to do.
> 2/ Use that stract/class as a value type. You can do POD, but also  
> define constructor and destructor, copy constructor and overload  
> assignement. Anyway, you'll never be able to use proper polymorphism  
> here, because it would require virtual destructor at least. This is IMO,  
> what D's struct should achieve.
>
> The 2/ case is overly used in almost any C++ program. And D struct  
> should be able to match them. It wouldn't require much to make it  
> working :
>   - Default constructor.
>   - The hability to define opAssign for it's own type if this(this) is  
> disabled.
>
> Today we have 2 options in D : go for struct and get an error prone  
> binding (it's very easy to get a garbage struct, because you cannot  
> enforce that you'll go throw the constructor, and you cannot map copy  
> constructor, even with additionnal C++ code).
>
> Or you can go final class, but you don't have a value type anymore and  
> it become quite hard to pass the object to/from C++, because of the  
> header of the object. If you get one from C++, you need the rewrap it in  
> a object on the D side, but . . . the copy constructor isn't mappable.  
> So you need to play ping pong between D and C++ to allocated the D  
> object, then go back to C++ to copy the data using the proper copy code,  
> and then go back to D to do something with that. Plus you need an heap  
> allocation (which isn't inexpansive ATM, because of the lock in it, and  
> cannot compete with stack anyway).
>
The focus lays on 'interfacing' C++ not integrating it.
The interfacing of C/C++ structs is limited to compatible memory layout.

It might seem arbitrary restrictive, but from what you describe
you could directly use a shared_ptr<T> in D code. This is likely too
much, as it conflicts with the semantic differences you observe.

As you have to redeclare a POD anyhow you could make it a two face  
structure,
i.e. implementing some methods on both sides which might also gives you  
more efficient code.

P.S.:
There is also a bug of passing struct values for x86_64.
http://d.puremagic.com/issues/show_bug.cgi?id=5570

>>> allow for default constructor and copy constructor isn't mappable
>>> using posblit. final class imply an overhead, and are references types
>>> (so cannot be passed by value).
>> References only cost you an allocation, the call overhead is practically
>> inexistent
>> (I'm not aware of any language that achieves this).
>>
>> I've recently posted a feasible solution to allocate C++ classes using  
>> the
>> D garbage collector and profit from automatic lifetime management.
>> https://gist.github.com/1391734
>>
>> Given that all bugs get sorted out, one can expect three mechanisms to
>> work.
>>
>> - Calling free C++ functions and probably non-virtual methods
>> - Pass POD data forth and back
>> - Call virtual methods of classes with known vtable layout
>>
>> Some more things as calling namespace function or certain templates  
>> could
>> probably be provided by a library. But it should suffice to provide zero
>> overhead
>> interfacing to most C++ code.
>> Interfacing QT with it's heavy use of virtual calls,  
>> multiple-inheritance
>> and a custom pre-processor will require an additional simplifying
>> wrapper layer
>> on the C++ side.
>>
>> martin
>
> I did had a look at that code just befor you posted (somebody mention  
> that on irc). This is a nice piece of code. But clearly solve another  
> problem that the one I'm talking about.
>
> If your are interested I wrote something about starting thread on the  
> C++ side but remaining compatible with D (so you can call D code from  
> the C++ thread) here :  
> http://www.deadalnix.42/2011/11/24/interfacing-d-with-c-start-new-thread/  
> (require 42registry).


More information about the Digitalmars-d mailing list