digitalmars.D - H1 2015 - C++ integration
- Guillaume Chatelet (35/35) Feb 13 2015 I'm working on integration of D with the C++ STL (at least the
- Kagamin (2/2) Feb 13 2015 It's not like you're free to choose, because struct and class can
- Guillaume Chatelet (8/10) Feb 13 2015 I'm not sure I get your point. In C++ classes without vtables are
- Kagamin (4/8) Feb 13 2015 Do you want it to be compatible with Gnu Linux only?
- Guillaume Chatelet (4/12) Feb 13 2015 Thx, according to wikipedia
- Daniel Murphy (5/12) Feb 13 2015 This is not a good example, because the return type is clearly not mangl...
- Guillaume Chatelet (5/21) Feb 14 2015 You're absolutely right, my bad.
- Guillaume Chatelet (22/22) Feb 14 2015 I did a few tests. Using a class doesn't work because of the
- Paolo Invernizzi (14/37) Feb 14 2015 I'm also using pragma(mangle) and struct with a fake virtual
- Daniel Murphy (12/23) Feb 14 2015 This is a bug, D currently adds a vptr even if there are no members. It...
- Guillaume Chatelet (4/6) Feb 14 2015 I just created it
- Andrei Alexandrescu (20/31) Feb 14 2015 Yah, this is still a bit in the air. The point here is that the simplest...
- Guillaume Chatelet (19/54) Feb 14 2015 I think we can do with 'never copy' but never create seems a bit
- Guillaume Chatelet (4/4) Feb 15 2015 I updated https://github.com/gchatelet/dlang_cpp_std to provide a
- Paolo Invernizzi (12/16) Feb 15 2015 That's a great work.
- Guillaume Chatelet (20/30) Feb 15 2015 Thx :)
- Paolo Invernizzi (5/39) Feb 15 2015 Thanks for sharing!
- Andrei Alexandrescu (10/14) Feb 15 2015 Awesome work, thanks. After further thinking of this, Walter and I
- Guillaume Chatelet (11/14) Feb 17 2015 ctor/dtor C++ naming :
- Guillaume Chatelet (9/9) Feb 17 2015 We'll also have to provide a new pragma to allow correct mangling
- Benjamin Thaut (4/13) Feb 17 2015 Yes please. I'm running into the same issue right now. Changing
- Guillaume Chatelet (3/19) Feb 17 2015 Created https://issues.dlang.org/show_bug.cgi?id=14193
- Andrei Alexandrescu (2/11) Feb 17 2015 Yah, I don't think we can get away without that. -- Andrei
- Paolo Invernizzi (5/14) Feb 17 2015 +1 please!
- Andrei Alexandrescu (6/17) Feb 17 2015 This is tricky. I'd say for now we shouldn't allow default-constructed
- Guillaume Chatelet (5/8) Jul 05 2015 I finally took some time to put up a first draft
I'm working on integration of D with the C++ STL (at least the linux gnu one). * You can have a look at a current draft implementation (1). * There is a name mangling issue in dmd related to the compression of usual stl types when the type is const eg. dmd will mangle 'std::vector<int>::size() const' as '_ZNK3std6vectorIiSaIiEE4sizeEv' where it should be mangled '_ZNKSt6vectorIiSaIiEE4sizeEv'. Note 'std' is being compressed into 'St'. I believe this is coming from https://github.com/D-Programming-Language/dmd/blob/master/src/cppmangle.c#L453 which tests only the non const type pattern. According to (2) this substitution seems illegal "Note that substitutable components are the represented symbolic constructs, not their associated mangling character strings." This lead to undefined reference when linking and that's why my code overrides the name mangling. * In the video Walter posted recently (3), he states that one should use a class to represent a std::string or std::vector in D because most of the time we want to have reference semantic. I find this a bit counter intuitive for people coming from C++ since they are clearly value semantic. std::string and std::vector should behave the same in C++ and D to confirm the principle of least astonishment. I started implementing them as struct (4) but then I can only have disable default constructors. I would like to gather opinions on struct vs class. Any ideas ? Guillaume --- 1. https://github.com/gchatelet/dlang_cpp_std 2. http://mentorembedded.github.io/cxx-abi/abi.html#mangling-compression 3. https://www.youtube.com/watch?v=IkwaV6k6BmM 4. https://github.com/gchatelet/dlang_cpp_std/blob/master/std_string.d
Feb 13 2015
It's not like you're free to choose, because struct and class can use different mangling.
Feb 13 2015
On Friday, 13 February 2015 at 13:03:18 UTC, Kagamin wrote:It's not like you're free to choose, because struct and class can use different mangling.I'm not sure I get your point. In C++ classes without vtables are exactly like structs. Also I don't see any difference between a struct or a class name mangling on Gnu Linux. class/struct S{}; S foo(); foo gets mangled "_Z3foov" if S is a struct or a class. What did I miss ? Do you have compelling examples ?
Feb 13 2015
On Friday, 13 February 2015 at 14:07:44 UTC, Guillaume Chatelet wrote:I'm not sure I get your point. In C++ classes without vtables are exactly like structs. Also I don't see any difference between a struct or a class name mangling on Gnu Linux.Do you want it to be compatible with Gnu Linux only?What did I miss ? Do you have compelling examples ?AFAIK, MSVC++. There are other C++ compilers too.
Feb 13 2015
On Friday, 13 February 2015 at 14:15:10 UTC, Kagamin wrote:On Friday, 13 February 2015 at 14:07:44 UTC, Guillaume Chatelet wrote:Thx, according to wikipedia (http://en.wikipedia.org/wiki/Visual_C%2B%2B_name_mangling#Data_Type) VisualC++ is indeed encoding struct and class with U anv V.I'm not sure I get your point. In C++ classes without vtables are exactly like structs. Also I don't see any difference between a struct or a class name mangling on Gnu Linux.Do you want it to be compatible with Gnu Linux only?What did I miss ? Do you have compelling examples ?AFAIK, MSVC++. There are other C++ compilers too.
Feb 13 2015
"Guillaume Chatelet" wrote in message news:gvnxmwplwkyfrydwrulq forum.dlang.org...I'm not sure I get your point. In C++ classes without vtables are exactly like structs. Also I don't see any difference between a struct or a class name mangling on Gnu Linux. class/struct S{}; S foo(); foo gets mangled "_Z3foov" if S is a struct or a class. What did I miss ? Do you have compelling examples ?This is not a good example, because the return type is clearly not mangled into the function name. (Because you can't overload on return type.) void foo(S); should show the problem with some mangling schemes.
Feb 13 2015
On Friday, 13 February 2015 at 18:47:53 UTC, Daniel Murphy wrote:"Guillaume Chatelet" wrote in message news:gvnxmwplwkyfrydwrulq forum.dlang.org...You're absolutely right, my bad. class/struct S {}; void foo(S s){} foo gets mangled "_Z3foo1S" if S is a struct or a class.I'm not sure I get your point. In C++ classes without vtables are exactly like structs. Also I don't see any difference between a struct or a class name mangling on Gnu Linux. class/struct S{}; S foo(); foo gets mangled "_Z3foov" if S is a struct or a class. What did I miss ? Do you have compelling examples ?This is not a good example, because the return type is clearly not mangled into the function name. (Because you can't overload on return type.) void foo(S); should show the problem with some mangling schemes.
Feb 14 2015
I did a few tests. Using a class doesn't work because of the added vptr. The data would be managed at the same time on the D and the C++ side. Structs work however because we can add something like this : struct std_string { void[8] _ = void; // to match sizeof(std::string) and pad the object correctly. } The padding will be left untouched on the D side because of void initializer and will be managed entirely on the C++ side. Using a class crashes (C++ and D step on each others toes). Structs work expect for : - name mangling on linux (bug reported in my first message) - name mangling on Windows at least (name would be mangled as a struct instead of class) - disabled default constructor. Mangling on Linux is fixable as well as default construction : we can provide a special function that would create a new instance. But for the windows name mangling, I don't see a way out in the language as it is right now. Any ideas ?
Feb 14 2015
On Saturday, 14 February 2015 at 17:24:51 UTC, Guillaume Chatelet wrote:I did a few tests. Using a class doesn't work because of the added vptr. The data would be managed at the same time on the D and the C++ side. Structs work however because we can add something like this : struct std_string { void[8] _ = void; // to match sizeof(std::string) and pad the object correctly. } The padding will be left untouched on the D side because of void initializer and will be managed entirely on the C++ side. Using a class crashes (C++ and D step on each others toes). Structs work expect for : - name mangling on linux (bug reported in my first message) - name mangling on Windows at least (name would be mangled as a struct instead of class) - disabled default constructor. Mangling on Linux is fixable as well as default construction : we can provide a special function that would create a new instance. But for the windows name mangling, I don't see a way out in the language as it is right now. Any ideas ?I'm also using pragma(mangle) and struct with a fake virtual table... ;-( I think that another problem is that, if you use a class in D instead of a struct, it's a mess with C++ functions taking a reference: D - class vector ..... C++ - foo(const vector& a) ... C++ - foo(const vector* a) ... How do we specify the right mangling for the reference? --- /P
Feb 14 2015
"Guillaume Chatelet" wrote in message news:fzxoskcrswitmsdsztso forum.dlang.org...I did a few tests. Using a class doesn't work because of the added vptr.This is a bug, D currently adds a vptr even if there are no members. It's just one that doesn't happen to affect ddmd so I never got around to fixing it.struct std_string { void[8] _ = void; // to match sizeof(std::string) and pad the object correctly. } The padding will be left untouched on the D side because of void initializer and will be managed entirely on the C++ side.Just remember to be careful that any C++ structs don't rely on interior pointers.- name mangling on linux (bug reported in my first message)Is this in bugzilla?- name mangling on Windows at least (name would be mangled as a struct instead of class)We can probably use pragma(mangle) to fix this or add a new pragma for it. eg pragma(cpp_class/cpp_struct);- disabled default constructor.Yeeeeah I've always felt like we're going to have to add default struct ctors to D eventually.
Feb 14 2015
On Saturday, 14 February 2015 at 19:54:53 UTC, Daniel Murphy wrote:I just created it https://issues.dlang.org/show_bug.cgi?id=14178- name mangling on linux (bug reported in my first message)Is this in bugzilla?
Feb 14 2015
On 2/13/15 4:23 AM, Guillaume Chatelet wrote:* In the video Walter posted recently (3), he states that one should use a class to represent a std::string or std::vector in D because most of the time we want to have reference semantic. I find this a bit counter intuitive for people coming from C++ since they are clearly value semantic. std::string and std::vector should behave the same in C++ and D to confirm the principle of least astonishment.Yah, this is still a bit in the air. The point here is that the simplest route to getting std::vector working in D is to avoid the many little difference between C++ copy ctors and D's postblit. As such, we say: pass std::vector by reference from/to C++, and never construct or copy one on the D side. I think that's a usable policy - most of the time containers are not supposed to be copied and people must carefully pass them by reference everywhere. The annoying part is having one as a member in a D type. Clearly we need to think this through carefully.I started implementing them as struct (4) but then I can only have disable default constructors.I think that can be made to work, too.I would like to gather opinions on struct vs class. Any ideas ?To also reply to your more recent message:I did a few tests. Using a class doesn't work because of the added vptr. The data would be managed at the same time on the D and the C++ side.That should work. You don't need any layout information at all for std::vector on the D side; all you do is pass a pointer to std::vector around D code, and when you want to mess with it you pass the pointer to "this" appropriately. It all works; there's no need for D to know the layout, only the correct pointer and method signatures. I think a gating issue right now is handling C++ exceptions in D code. C++ stdlib types are not really usable without exceptions. Andrei
Feb 14 2015
On Saturday, 14 February 2015 at 18:04:50 UTC, Andrei Alexandrescu wrote:On 2/13/15 4:23 AM, Guillaume Chatelet wrote:I think we can do with 'never copy' but never create seems a bit rough. If you want to call a C++ function that takes a vector you'd need to allocate it somehow. And struct would make allocation predictable by default.* In the video Walter posted recently (3), he states that one should use a class to represent a std::string or std::vector in D because most of the time we want to have reference semantic. I find this a bit counter intuitive for people coming from C++ since they are clearly value semantic. std::string and std::vector should behave the same in C++ and D to confirm the principle of least astonishment.Yah, this is still a bit in the air. The point here is that the simplest route to getting std::vector working in D is to avoid the many little difference between C++ copy ctors and D's postblit. As such, we say: pass std::vector by reference from/to C++, and never construct or copy one on the D side.I think that's a usable policy - most of the time containers are not supposed to be copied and people must carefully pass them by reference everywhere. The annoying part is having one as a member in a D type. Clearly we need to think this through carefully.Definitely. I think I'll do two implementations and see how far I can go with both (class vs struct). My understanding is that if we go with struct we can allocate on the D side and we have value semantic (for what I tested copy does work and does not leak memory).I agree but I see several potential issues : - you can't control the object lifetime on the D side (can't allocate on D side without a C++ helper function, can't delete the object) - using scoped!std_string will crash.I did a few tests. Using a class doesn't work because of the added vptr. The data would be managed at the same time on the D and the C++ side.That should work. You don't need any layout information at all for std::vector on the D side; all you do is pass a pointer to std::vector around D code, and when you want to mess with it you pass the pointer to "this" appropriately. It all works; there's no need for D to know the layout, only the correct pointer and method signatures.I think a gating issue right now is handling C++ exceptions in D code. C++ stdlib types are not really usable without exceptions.For string and vector a lot of the functions are nothrow, so those would be safe to use at least.
Feb 14 2015
I updated https://github.com/gchatelet/dlang_cpp_std to provide a struct and class implementation of string. Also added a README to weigh the pros and cons of each, list bugs I encountered and other things we need to think about.
Feb 15 2015
On Sunday, 15 February 2015 at 14:42:46 UTC, Guillaume Chatelet wrote:I updated https://github.com/gchatelet/dlang_cpp_std to provide a struct and class implementation of string. Also added a README to weigh the pros and cons of each, list bugs I encountered and other things we need to think about.That's a great work. Guillaume, I'll try to ask this question again. I'm wrapping the C++ API of OpenCV [1], and it works great. I'm using a D struct for std::string instead of D class, because I agree with your findings that's more convenient. But, in case I would like to use a D class for std::string, how to call a C++ function that takes a std::string&? It's feasible right now? I think we need more control over the mangle in extern(C++)... [1] http://docs.opencv.org/trunk/modules/refman.html
Feb 15 2015
On Sunday, 15 February 2015 at 15:37:33 UTC, Paolo Invernizzi wrote:That's a great work.Thx :)Guillaume, I'll try to ask this question again. I'm wrapping the C++ API of OpenCV [1], and it works great. I'm using a D struct for std::string instead of D class, because I agree with your findings that's more convenient. But, in case I would like to use a D class for std::string, how to call a C++ function that takes a std::string&? It's feasible right now? I think we need more control over the mangle in extern(C++)... [1] http://docs.opencv.org/trunk/modules/refman.htmlI just pushed a new commit which shows how to do it with classes as well: https://github.com/gchatelet/dlang_cpp_std/commit/892a736386ecd84516b7330fef4ee75f1b4d2ad3 This requires to pervert the type system though so it's pretty unsafe. I added the two following helper functions to reinterpret a D reference semantic as a C++ value semantic : const (basic_string*) c_ptr() const { return cast(const std_string*)(this); } ref const(basic_string) c_ref() const { return *cast(const std_string*)(this); } You can then call the C++ function : getStringSize(s.c_ref); This is cumbersome and unsafe but workable. Because the C++ function contains a const ref to string we have to provide the correct mangling manually anyways because of mangling bug https://issues.dlang.org/show_bug.cgi?id=14178
Feb 15 2015
On Sunday, 15 February 2015 at 19:44:39 UTC, Guillaume Chatelet wrote:On Sunday, 15 February 2015 at 15:37:33 UTC, Paolo Invernizzi wrote:Thanks for sharing! --- /PThat's a great work.Thx :)Guillaume, I'll try to ask this question again. I'm wrapping the C++ API of OpenCV [1], and it works great. I'm using a D struct for std::string instead of D class, because I agree with your findings that's more convenient. But, in case I would like to use a D class for std::string, how to call a C++ function that takes a std::string&? It's feasible right now? I think we need more control over the mangle in extern(C++)... [1] http://docs.opencv.org/trunk/modules/refman.htmlI just pushed a new commit which shows how to do it with classes as well: https://github.com/gchatelet/dlang_cpp_std/commit/892a736386ecd84516b7330fef4ee75f1b4d2ad3 This requires to pervert the type system though so it's pretty unsafe. I added the two following helper functions to reinterpret a D reference semantic as a C++ value semantic : const (basic_string*) c_ptr() const { return cast(const std_string*)(this); } ref const(basic_string) c_ref() const { return *cast(const std_string*)(this); } You can then call the C++ function : getStringSize(s.c_ref); This is cumbersome and unsafe but workable. Because the C++ function contains a const ref to string we have to provide the correct mangling manually anyways because of mangling bug https://issues.dlang.org/show_bug.cgi?id=14178
Feb 15 2015
On 2/15/15 6:42 AM, Guillaume Chatelet wrote:I updated https://github.com/gchatelet/dlang_cpp_std to provide a struct and class implementation of string. Also added a README to weigh the pros and cons of each, list bugs I encountered and other things we need to think about.Awesome work, thanks. After further thinking of this, Walter and I concluded we should make std::string, std::vector etc. be structs in D code as well lest we confuse the heck out of people. Please file bugs for any constructor/destructor issues you find (I notice you filed one already). Walter is up to the task and of course I'm counting on others, too. Let's aim for passable support for 2.068. Thanks, Andrei
Feb 15 2015
On Sunday, 15 February 2015 at 19:49:28 UTC, Andrei Alexandrescu wrote:Please file bugs for any constructor/destructor issues you find (I notice you filed one already). Walter is up to the task and of course I'm counting on others, too.ctor/dtor C++ naming : https://issues.dlang.org/show_bug.cgi?id=14086 invalid stl manlging : https://issues.dlang.org/show_bug.cgi?id=14178 Questions : + Shall I add one more to allow default ctor for struct when they are extern C++ ? (ie. no disable) + I guess this C++ STL binding will end up in phobos. Any idea of where this should be put ?
Feb 17 2015
We'll also have to provide a new pragma to allow correct mangling of types on Windows. Maybe something like : extern(C++, std) { pragma(mangleAs, "class") struct basic_string() { ... } }
Feb 17 2015
On Tuesday, 17 February 2015 at 11:39:06 UTC, Guillaume Chatelet wrote:We'll also have to provide a new pragma to allow correct mangling of types on Windows. Maybe something like : extern(C++, std) { pragma(mangleAs, "class") struct basic_string() { ... } }Yes please. I'm running into the same issue right now. Changing everything to struct on the c++ side is not always possible.
Feb 17 2015
On Tuesday, 17 February 2015 at 12:09:11 UTC, Benjamin Thaut wrote:On Tuesday, 17 February 2015 at 11:39:06 UTC, Guillaume Chatelet wrote:Created https://issues.dlang.org/show_bug.cgi?id=14193We'll also have to provide a new pragma to allow correct mangling of types on Windows. Maybe something like : extern(C++, std) { pragma(mangleAs, "class") struct basic_string() { ... } }Yes please. I'm running into the same issue right now. Changing everything to struct on the c++ side is not always possible.
Feb 17 2015
On 2/17/15 3:39 AM, Guillaume Chatelet wrote:We'll also have to provide a new pragma to allow correct mangling of types on Windows. Maybe something like : extern(C++, std) { pragma(mangleAs, "class") struct basic_string() { ... } }Yah, I don't think we can get away without that. -- Andrei
Feb 17 2015
On Tuesday, 17 February 2015 at 11:39:06 UTC, Guillaume Chatelet wrote:We'll also have to provide a new pragma to allow correct mangling of types on Windows. Maybe something like : extern(C++, std) { pragma(mangleAs, "class") struct basic_string() { ... } }+1 please! --- Paolo
Feb 17 2015
On 2/17/15 3:34 AM, Guillaume Chatelet wrote:On Sunday, 15 February 2015 at 19:49:28 UTC, Andrei Alexandrescu wrote:This is tricky. I'd say for now we shouldn't allow default-constructed C++ objects. We can later add a special type e.g. CppDefault to mean "invoke the C++ default constructor".Please file bugs for any constructor/destructor issues you find (I notice you filed one already). Walter is up to the task and of course I'm counting on others, too.ctor/dtor C++ naming : https://issues.dlang.org/show_bug.cgi?id=14086 invalid stl manlging : https://issues.dlang.org/show_bug.cgi?id=14178 Questions : + Shall I add one more to allow default ctor for struct when they are extern C++ ? (ie. no disable)+ I guess this C++ STL binding will end up in phobos. Any idea of where this should be put ?core.stdcpp. Andrei
Feb 17 2015
On Friday, 13 February 2015 at 12:23:58 UTC, Guillaume Chatelet wrote:I'm working on integration of D with the C++ STL (at least the linux gnu one). [...]I finally took some time to put up a first draft https://github.com/D-Programming-Language/druntime/pull/1316 There's a bunch of questions in there as well, please destroy :)
Jul 05 2015