digitalmars.D.learn - extern (C++) including bodies of member functions?
- cy (45/45) Jul 15 2016 I would never (ever) do this myself, but trying to understand
- Jacob Carlborg (13/46) Jul 15 2016 Yes. Just as it's possible to call C function from D, it's possible to
- cy (7/11) Jul 15 2016 So, it applies to member functions too (for C++)? Just as if you
- Jacob Carlborg (8/14) Jul 16 2016 Yes. It's a bit more than the mangling that changes. The layout of the
I would never (ever) do this myself, but trying to understand dmd, the code is absolutely packed with things like this: extern(C++) class Package : ScopeDSymbol { ... override const(char)* kind() const { return "package"; } ... override final inout(Package) isPackage() inout { return this; } ...etc... } How exactly does that... work? Is the body of such a member function written in the D Programming Language? Or is it some weird hybrid of D and C++ that just has a human programmer brain taking into account all the times that differing name mangling might produce different code? I mean, Package.resolve for instance is a non-trivial function. Can you not use templates inside such a function? Can you only use other "extern(C++)" types? Can you import from other modules, inside such a function? The documents say nothing about this, only defining their examples as stubs, like extern(C++) class Foo { void bar(); } The documentation also avoids any memory allocation in D, instead assuming C++ routines like createInstance to use malloc to allocate the classes. But the code in dmd makes extensive use of things like this: extern(C++) ... { final extern(D) this(...) { ... } } How would you create new objects of types that are declared extern(C++)? Just new, and mark the constructor as extern(D)? I realize DMD is a horrible program that was Frankensteined from C++ code ages ago and is practically still C++ itself, and that DMD has to have /full/ control of symbol mangling, but it is also sort of important, not just as a D compiler, but as one of the only programs left in the world that produces optimized assembly, rather than passing it on to gcc or LLVM. So, understanding it is kind of an interest of mine.
Jul 15 2016
On 2016-07-15 19:52, cy wrote:I would never (ever) do this myself, but trying to understand dmd, the code is absolutely packed with things like this: extern(C++) class Package : ScopeDSymbol { ... override const(char)* kind() const { return "package"; } ... override final inout(Package) isPackage() inout { return this; } ...etc... } How exactly does that... work? Is the body of such a member function written in the D Programming Language?Yes. Just as it's possible to call C function from D, it's possible to implement functions in D that can be called from C. This compatibility applies C++ and Objective-C as well. When the D compiler sees a "extern(C++)" declaration it will adopt the code and output the data structures to be compatible with C++. For example, the location of the vtable, name mangling and so on.The documents say nothing about this, only defining their examples as stubs, like extern(C++) class Foo { void bar(); } The documentation also avoids any memory allocation in D, instead assuming C++ routines like createInstance to use malloc to allocate the classes. But the code in dmd makes extensive use of things like this: extern(C++) ... { final extern(D) this(...) { ... } }IIRC, it's not possible to call a C++ constructor from D. That's why "extern(D) this" is used to be able to do the memory allocation from the D side.How would you create new objects of types that are declared extern(C++)? Just new, and mark the constructor as extern(D)? I realize DMD is a horrible program that was Frankensteined from C++ code ages ago and is practically still C++ itselfThe front end was only fairly recently converted to D. -- /Jacob Carlborg
Jul 15 2016
On Friday, 15 July 2016 at 19:20:52 UTC, Jacob Carlborg wrote:Yes. Just as it's possible to call C function from D, it's possible to implement functions in D that can be called from C. This compatibility applies C++ and Objective-C as well.So, it applies to member functions too (for C++)? Just as if you passed an extern(C++) directive to each one? And only their signature/mangling is changed, so that say in gdb for instance, they represent Type::member instead of zzTypezdxqdstuffmember?The front end was only fairly recently converted to D.Oh, I thought it happened a while ago, like when D2 came out. (Or was D2 recent as well?)
Jul 15 2016
On 2016-07-16 04:01, cy wrote:So, it applies to member functions too (for C++)? Just as if you passed an extern(C++) directive to each one? And only their signature/mangling is changed, so that say in gdb for instance, they represent Type::member instead of zzTypezdxqdstuffmember?Yes. It's a bit more than the mangling that changes. The layout of the class/struct needs to be correct and the this pointer needs to be passed correctly.Oh, I thought it happened a while ago, like when D2 came out. (Or was D2 recent as well?)No, D2 was started in something like 2007. The compiler was converted last year in August. -- /Jacob Carlborg
Jul 16 2016