digitalmars.D - C++ constructors, destructors and operator access
- Igor Stepanov (60/60) May 18 2013 At the current time D have powerful mechanism of access to C++
- =?UTF-8?B?QWxpIMOHZWhyZWxp?= (3/4) May 18 2013 That's part of the problem: C++ name mangling is not standardized.
- Igor Stepanov (14/19) May 18 2013 But D compilers are using C++ mangle for extern(C++) functions
- Iain Buclaw (19/65) May 18 2013 part of interface. Thus the most of C++ classes can be bound without any
- Igor Stepanov (7/8) May 19 2013 Ok. As I know, there is running process to moving DMD front-end
- Iain Buclaw (6/14) May 19 2013 All new'ing will be done in D. The C++ glue-layer methods are a problem...
- Igor Stepanov (8/8) May 19 2013 Is this mean, that D functions will _not_ create C++ objects with
- Daniel Murphy (12/17) May 19 2013 This is not how we're moving it. The entire frontend will be moved in o...
- Igor Stepanov (15/40) May 19 2013 Yes, language shouldn't be modified for the sake of one goal.
- Daniel Murphy (13/26) May 20 2013 Mapping constructors is complicated... Do they have the same semantics ...
- Igor Stepanov (51/64) May 20 2013 You have misunderstood me.
- evilrat (10/70) May 20 2013 you can do this yourself just with mixins and templates, but the
- nazriel (8/68) May 20 2013 Isn't it possible already with something like:
- nazriel (7/87) May 20 2013 Of course I mean:
- Igor Stepanov (6/96) May 20 2013 If we'll implement generateCPPMangle template, we'll can do all:)
At the current time D have powerful mechanism of access to C++ classes. For access to methods of C++ classes (virtual and not) we can use extern(C++) interface. //С++ class CPPTest1 { int a; int b; public: virtual int boom(); int fun(); static int gun(); CPPTest1(int); virtual ~CPPTest1(); int& operator[](size_t); }; class CPPTest2: public CPPTest1 { int boom(); }; //D extern(C++)interface CPPTest1 { int boom(); static int gun(); final int fun(); } extern(C++)interface CPPTest2: CPPTest1 { //int boom(); } As a rule, non-static fields are not public in C++ classes and is not part of interface. Thus the most of C++ classes can be bound without any glue c++ code. However D dont support C++ overloaded operators and constructors. Yes, we cannot make mapping C++ operators to D operators and C++ constructors to D constructors). Nonetheless С++ operators and constructors are the simple C++ functions or methods with special mangling. Thus I've suggest next mechanism: Allow special pragma(cppSymbol, string_arg), when string_arg is the name of c++ thing. Example: extern(C++)interface CPPTest1 { int boom(); static int gun(); final int fun(); ///!!!! pragma(cppSymbol, "constructor") final void ctor(int); //linked with CPPTest1(int); pragma(cppSymbol, "destructor") void dtor(); //linked with virtual ~CPPTest1(); pragma(cppSymbol, "[]") ref int indexOf(size_t); //linked with int& operator[](size_t); } This pragma must apply to the function (or method), use natural C++ mangle, but set operatror or constructor or destructor mangled name instead of function name. Is it useful idea?
May 18 2013
On 05/18/2013 03:23 PM, Igor Stepanov wrote:natural C++ mangleThat's part of the problem: C++ name mangling is not standardized. Ali
May 18 2013
On Saturday, 18 May 2013 at 22:55:34 UTC, Ali Çehreli wrote:On 05/18/2013 03:23 PM, Igor Stepanov wrote:But D compilers are using C++ mangle for extern(C++) functions now. I think, this trouble can be solved in a glue layer of compiler. Now, on posix we can use gcc c++ mangle, on windows - dmc/visual c++ mangle. As I know, there is not many kinds of c++ mangle. over 10:) Current implementation use only two: dmc for windows, gcc for posix. If another back-end will be added, we can add another mangle support. I think, C++ to D binding is a very important issue. If D will provide good mechanism of binding, some projects will can be simple moved to D and some project leaders will can choose D to develop his projects.natural C++ mangleThat's part of the problem: C++ name mangling is not standardized. Ali
May 18 2013
On May 18, 2013 11:25 PM, "Igor Stepanov" <wazar.leollone yahoo.com> wrote:At the current time D have powerful mechanism of access to C++ classes. For access to methods of C++ classes (virtual and not) we can useextern(C++) interface.//=F3++ class CPPTest1 { int a; int b; public: virtual int boom(); int fun(); static int gun(); CPPTest1(int); virtual ~CPPTest1(); int& operator[](size_t); }; class CPPTest2: public CPPTest1 { int boom(); }; //D extern(C++)interface CPPTest1 { int boom(); static int gun(); final int fun(); } extern(C++)interface CPPTest2: CPPTest1 { //int boom(); } As a rule, non-static fields are not public in C++ classes and is notpart of interface. Thus the most of C++ classes can be bound without any glue c++ code.However D dont support C++ overloaded operators and constructors. Yes, wecannot make mapping C++ operators to D operators and C++ constructors to D constructors). Nonetheless =F3++ operators and constructors are the simple C++ functions or methods with special mangling. Thus I've suggest next mechanism:Allow special pragma(cppSymbol, string_arg), when string_arg is the nameof c++ thing.Example: extern(C++)interface CPPTest1 { int boom(); static int gun(); final int fun(); ///!!!! pragma(cppSymbol, "constructor") final void ctor(int); //linked withCPPTest1(int);pragma(cppSymbol, "destructor") void dtor(); //linked with virtual~CPPTest1();pragma(cppSymbol, "[]") ref int indexOf(size_t); //linked with int&operator[](size_t);} This pragma must apply to the function (or method), use natural C++mangle, but set operatror or constructor or destructor mangled name instead of function name.Is it useful idea?No. Regards --=20 Iain Buclaw *(p < e ? p++ : p) =3D (c & 0x0f) + '0';
May 18 2013
No.Ok. As I know, there is running process to moving DMD front-end from C++ to D. As I remember, process expect to be gradual. Thus I the same moment will be C++ classes and D classes in the frontend. How you are planning create new C++ objects from D? Are you planning add to all classes special "constructor" static method, which will create new instances of C++ classes and return it, or you see another way to do it?
May 19 2013
On 19 May 2013 13:20, Igor Stepanov <wazar.leollone yahoo.com> wrote:No.All new'ing will be done in D. The C++ glue-layer methods are a problem, and we will be moving to using a visitor interface between the two. -- Iain Buclaw *(p < e ? p++ : p) = (c & 0x0f) + '0';Ok. As I know, there is running process to moving DMD front-end from C++ to D. As I remember, process expect to be gradual. Thus I the same moment will be C++ classes and D classes in the frontend. How you are planning create new C++ objects from D? Are you planning add to all classes special "constructor" static method, which will create new instances of C++ classes and return it, or you see another way to do it?
May 19 2013
Is this mean, that D functions will _not_ create C++ objects with new? For example: You have moved parser to D, but you haven't moved expressions to D yet. And you want to create new Expression object in parser (in D code), but Expression class defined in C++. What will you do in this case?
May 19 2013
"Igor Stepanov" <wazar.leollone yahoo.com> wrote in message news:wuevxraaffhaaceapqfv forum.dlang.org...Is this mean, that D functions will _not_ create C++ objects with new? For example: You have moved parser to D, but you haven't moved expressions to D yet. And you want to create new Expression object in parser (in D code), but Expression class defined in C++. What will you do in this case?This is not how we're moving it. The entire frontend will be moved in one go, there will never be a need to create a C++ class from D. That said, the glue layer will remain in C++ and will need to create instances of classes defined in D. The current glue layer calls 43 different constructors. I don't have a solution for this yet, but it will probably be: a) Extend D to allow creating classes with constructors callable from C++ b) Create/generate factory functions for each class new'd in the glue layer c) Remove all class allocations from the glue layer I'm leaning towards b, or maybe c, and I think you should too.
May 19 2013
On Sunday, 19 May 2013 at 13:56:56 UTC, Daniel Murphy wrote:"Igor Stepanov" <wazar.leollone yahoo.com> wrote in message news:wuevxraaffhaaceapqfv forum.dlang.org...Yes, language shouldn't be modified for the sake of one goal. But do you think, that calling C++ constructors from D is not typical task? I sure, that we must get a common way to bind C++ classes to D. No templates, no exceptions. But operators and constructors/destructors is needed. It may be special tool, that eat C++ header and return D file + C++ glue file. This util should transform all fields and constructors to D final methods for extern(C++) interface. In addition to this tool we can make a D binding layer, which simplify typical operations such as creating C++ objects using ::operator new() (or class operator new() if in exists) and destroying with operator delete() (local or global). By the way: Why D disallow static __gshared C++ variables in classes? This is a principled feature (if yes: why?) or omission?Is this mean, that D functions will _not_ create C++ objects with new? For example: You have moved parser to D, but you haven't moved expressions to D yet. And you want to create new Expression object in parser (in D code), but Expression class defined in C++. What will you do in this case?This is not how we're moving it. The entire frontend will be moved in one go, there will never be a need to create a C++ class from D. That said, the glue layer will remain in C++ and will need to create instances of classes defined in D. The current glue layer calls 43 different constructors. I don't have a solution for this yet, but it will probably be: a) Extend D to allow creating classes with constructors callable from C++ b) Create/generate factory functions for each class new'd in the glue layer c) Remove all class allocations from the glue layer I'm leaning towards b, or maybe c, and I think you should too.
May 19 2013
"Igor Stepanov" <wazar.leollone yahoo.com> wrote in message news:pckdwxwvumenyzbuvdpv forum.dlang.org...Yes, language shouldn't be modified for the sake of one goal. But do you think, that calling C++ constructors from D is not typical task? I sure, that we must get a common way to bind C++ classes to D. No templates, no exceptions. But operators and constructors/destructors is needed. It may be special tool, that eat C++ header and return D file + C++ glue file. This util should transform all fields and constructors to D final methods for extern(C++) interface. In addition to this tool we can make a D binding layer, which simplify typical operations such as creating C++ objects using ::operator new() (or class operator new() if in exists) and destroying with operator delete() (local or global).Mapping constructors is complicated... Do they have the same semantics in both languages? Both on the heap and on the stack? Eg. how on earth do you map a default constructor for a struct? Same problems with destructors. Which allocator do you use for the heap? etc Operator overloads are much worse, they just don't all map. Do we support part of the set? Or add the missing ones to D? eg comparison operatorsBy the way: Why D disallow static __gshared C++ variables in classes? This is a principled feature (if yes: why?) or omission?It does? Is this problem linux only? I don't see any reason why it would be excluded on purpose. That said, extern(C++) is mostly untested. There are some truly awful bugs lurking if you try to use complicated types/declarations. This is slowly improving.
May 20 2013
Mapping constructors is complicated... Operator overloads are much worse, they just don't all map.You have misunderstood me. I spoke out against the mapping. I spoke only about access. For example if we automatically generate a binding extern(C++) interface we can add a special methods to access to operators and constructors/destructors. For example: С++: class Foo { int operator<(const Foo&); int operator>(const Foo&); int& operator[](size_t); Foo(); ~Foo(); }; D automatically generated interface: extern(C++) interface Foo { final int __operator_lt(const Foo); final int __operator_gt(const Foo); final ref int __operator_index(size_t); final void __constructor(); final void __destructor(); } Those operator-access methods shouldn't have operator semantic in D. If user want to use C++ __operator_lt for compare objects in D, him cat manually create opCmp method and use __operator_lt in it. But it is user task. I think, we should only provide access to operators and constructors methods. About constructors: In addition those methods we can add some information methods. For example size_t __sizeof() method which return size of this object. After this we can provide some allocate+constructor functions. For example: auto foo = cppNewClass!Foo(args); This template functions perform next actions: 1. Try to find overloaded operator new(). If overloaded new has been finded then cppNewClass will use it, otherwise cppNewClass will use default new. 2. Try to find constructor, which can called with specified args. 3. Allocate memory using __sizeof() method. 4. Call constructor over alloated memory. for pair to cppNewClass can be provided cppDeleteClass function with same semantic. This support layer will very simplify interface with C++ code.Ok. I've created pull request https://github.com/D-Programming-Language/dmd/pull/2053By the way: Why D disallow static __gshared C++ variables in classes? This is a principled feature (if yes: why?) or omission?It does? Is this problem linux only? I don't see any reason why it would be excluded on purpose.That said, extern(C++) is mostly untested. There are some truly awful bugs lurking if you try to use complicated types/declarations. This is slowly improving.I've bumped two old bugzilla issues about extern(C++) http://d.puremagic.com/issues/show_bug.cgi?id=1687 http://d.puremagic.com/issues/show_bug.cgi?id=4620 Please comment it and close if they are invalid.
May 20 2013
On Saturday, 18 May 2013 at 22:23:51 UTC, Igor Stepanov wrote:At the current time D have powerful mechanism of access to C++ classes. For access to methods of C++ classes (virtual and not) we can use extern(C++) interface. //С++ class CPPTest1 { int a; int b; public: virtual int boom(); int fun(); static int gun(); CPPTest1(int); virtual ~CPPTest1(); int& operator[](size_t); }; class CPPTest2: public CPPTest1 { int boom(); }; //D extern(C++)interface CPPTest1 { int boom(); static int gun(); final int fun(); } extern(C++)interface CPPTest2: CPPTest1 { //int boom(); } As a rule, non-static fields are not public in C++ classes and is not part of interface. Thus the most of C++ classes can be bound without any glue c++ code. However D dont support C++ overloaded operators and constructors. Yes, we cannot make mapping C++ operators to D operators and C++ constructors to D constructors). Nonetheless С++ operators and constructors are the simple C++ functions or methods with special mangling. Thus I've suggest next mechanism: Allow special pragma(cppSymbol, string_arg), when string_arg is the name of c++ thing. Example: extern(C++)interface CPPTest1 { int boom(); static int gun(); final int fun(); ///!!!! pragma(cppSymbol, "constructor") final void ctor(int); //linked with CPPTest1(int); pragma(cppSymbol, "destructor") void dtor(); //linked with virtual ~CPPTest1(); pragma(cppSymbol, "[]") ref int indexOf(size_t); //linked with int& operator[](size_t); } This pragma must apply to the function (or method), use natural C++ mangle, but set operatror or constructor or destructor mangled name instead of function name. Is it useful idea?you can do this yourself just with mixins and templates, but the real problem is c++ abi and name mangling. so you will need to do runtime search for c++ mangled names and which runtime used, get it and call placement new and ctor(with the help of asm{} of course), do the same for other operators. it is possible, but this is never be safe at least due to non-standardized name mangling. you can write small library which would help doing this all if you really want this.
May 20 2013
On Saturday, 18 May 2013 at 22:23:51 UTC, Igor Stepanov wrote:At the current time D have powerful mechanism of access to C++ classes. For access to methods of C++ classes (virtual and not) we can use extern(C++) interface. //С++ class CPPTest1 { int a; int b; public: virtual int boom(); int fun(); static int gun(); CPPTest1(int); virtual ~CPPTest1(); int& operator[](size_t); }; class CPPTest2: public CPPTest1 { int boom(); }; //D extern(C++)interface CPPTest1 { int boom(); static int gun(); final int fun(); } extern(C++)interface CPPTest2: CPPTest1 { //int boom(); } As a rule, non-static fields are not public in C++ classes and is not part of interface. Thus the most of C++ classes can be bound without any glue c++ code. However D dont support C++ overloaded operators and constructors. Yes, we cannot make mapping C++ operators to D operators and C++ constructors to D constructors). Nonetheless С++ operators and constructors are the simple C++ functions or methods with special mangling. Thus I've suggest next mechanism: Allow special pragma(cppSymbol, string_arg), when string_arg is the name of c++ thing. Example: extern(C++)interface CPPTest1 { int boom(); static int gun(); final int fun(); ///!!!! pragma(cppSymbol, "constructor") final void ctor(int); //linked with CPPTest1(int); pragma(cppSymbol, "destructor") void dtor(); //linked with virtual ~CPPTest1(); pragma(cppSymbol, "[]") ref int indexOf(size_t); //linked with int& operator[](size_t); } This pragma must apply to the function (or method), use natural C++ mangle, but set operatror or constructor or destructor mangled name instead of function name. Is it useful idea?Isn't it possible already with something like: extern(C++) interface Foo { pragma(mangle, typeof(this).mangleof ~ generateCPPMangle!"myOwnFunctionMangling") void foo(); } AFAIK, mangle pragma was merged recently.
May 20 2013
On Monday, 20 May 2013 at 20:11:27 UTC, nazriel wrote:On Saturday, 18 May 2013 at 22:23:51 UTC, Igor Stepanov wrote:Of course I mean: extern(C++) interface Foo { pragma(mangle, generateCPPMangle!(typeof(this).mangleof, "myOwnFunctionMangling")) void foo(); }At the current time D have powerful mechanism of access to C++ classes. For access to methods of C++ classes (virtual and not) we can use extern(C++) interface. //С++ class CPPTest1 { int a; int b; public: virtual int boom(); int fun(); static int gun(); CPPTest1(int); virtual ~CPPTest1(); int& operator[](size_t); }; class CPPTest2: public CPPTest1 { int boom(); }; //D extern(C++)interface CPPTest1 { int boom(); static int gun(); final int fun(); } extern(C++)interface CPPTest2: CPPTest1 { //int boom(); } As a rule, non-static fields are not public in C++ classes and is not part of interface. Thus the most of C++ classes can be bound without any glue c++ code. However D dont support C++ overloaded operators and constructors. Yes, we cannot make mapping C++ operators to D operators and C++ constructors to D constructors). Nonetheless С++ operators and constructors are the simple C++ functions or methods with special mangling. Thus I've suggest next mechanism: Allow special pragma(cppSymbol, string_arg), when string_arg is the name of c++ thing. Example: extern(C++)interface CPPTest1 { int boom(); static int gun(); final int fun(); ///!!!! pragma(cppSymbol, "constructor") final void ctor(int); //linked with CPPTest1(int); pragma(cppSymbol, "destructor") void dtor(); //linked with virtual ~CPPTest1(); pragma(cppSymbol, "[]") ref int indexOf(size_t); //linked with int& operator[](size_t); } This pragma must apply to the function (or method), use natural C++ mangle, but set operatror or constructor or destructor mangled name instead of function name. Is it useful idea?Isn't it possible already with something like: extern(C++) interface Foo { pragma(mangle, typeof(this).mangleof ~ generateCPPMangle!"myOwnFunctionMangling") void foo(); }AFAIK, mangle pragma was merged recently.
May 20 2013
On Monday, 20 May 2013 at 20:13:47 UTC, nazriel wrote:On Monday, 20 May 2013 at 20:11:27 UTC, nazriel wrote:If we'll implement generateCPPMangle template, we'll can do all:) This way one of the possible. There are another way to do it. I don't know, what a best way now. But I think, this (simple binding C++ code to D) is important issue and we should solve it using one of the possible way.On Saturday, 18 May 2013 at 22:23:51 UTC, Igor Stepanov wrote:Of course I mean: extern(C++) interface Foo { pragma(mangle, generateCPPMangle!(typeof(this).mangleof, "myOwnFunctionMangling")) void foo(); }At the current time D have powerful mechanism of access to C++ classes. For access to methods of C++ classes (virtual and not) we can use extern(C++) interface. //С++ class CPPTest1 { int a; int b; public: virtual int boom(); int fun(); static int gun(); CPPTest1(int); virtual ~CPPTest1(); int& operator[](size_t); }; class CPPTest2: public CPPTest1 { int boom(); }; //D extern(C++)interface CPPTest1 { int boom(); static int gun(); final int fun(); } extern(C++)interface CPPTest2: CPPTest1 { //int boom(); } As a rule, non-static fields are not public in C++ classes and is not part of interface. Thus the most of C++ classes can be bound without any glue c++ code. However D dont support C++ overloaded operators and constructors. Yes, we cannot make mapping C++ operators to D operators and C++ constructors to D constructors). Nonetheless С++ operators and constructors are the simple C++ functions or methods with special mangling. Thus I've suggest next mechanism: Allow special pragma(cppSymbol, string_arg), when string_arg is the name of c++ thing. Example: extern(C++)interface CPPTest1 { int boom(); static int gun(); final int fun(); ///!!!! pragma(cppSymbol, "constructor") final void ctor(int); //linked with CPPTest1(int); pragma(cppSymbol, "destructor") void dtor(); //linked with virtual ~CPPTest1(); pragma(cppSymbol, "[]") ref int indexOf(size_t); //linked with int& operator[](size_t); } This pragma must apply to the function (or method), use natural C++ mangle, but set operatror or constructor or destructor mangled name instead of function name. Is it useful idea?Isn't it possible already with something like: extern(C++) interface Foo { pragma(mangle, typeof(this).mangleof ~ generateCPPMangle!"myOwnFunctionMangling") void foo(); }AFAIK, mangle pragma was merged recently.
May 20 2013