www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - extern(C++) template problem

reply Manu <turkeyman gmail.com> writes:
C++:
---------------------------------------
class C {};

template <typename T>
void create(T** x);
---------------------------------------

D:
---------------------------------------
extern(C++) class C {}

void create(T)(T* x);
---------------------------------------

Trouble is; in CPP, the template mangles as a C, but in D, the class
mangles as C*... so the mangling doesn't match.

`template<typename Class>` is an unbelievably common occurrence in
C++... but how do we express a signature that mangles correctly in D?
D always mangles `Class` as `Class*`... which changes the signature.

_<
May 23 2018
parent reply Nicholas Wilson <iamthewilsonator hotmail.com> writes:
On Wednesday, 23 May 2018 at 07:09:40 UTC, Manu wrote:
 C++:
 ---------------------------------------
 class C {};

 template <typename T>
 void create(T** x);
 ---------------------------------------

 D:
 ---------------------------------------
 extern(C++) class C {}

 void create(T)(T* x);
 ---------------------------------------

 Trouble is; in CPP, the template mangles as a C, but in D, the 
 class mangles as C*... so the mangling doesn't match.

 `template<typename Class>` is an unbelievably common occurrence 
 in C++... but how do we express a signature that mangles 
 correctly in D? D always mangles `Class` as `Class*`... which 
 changes the signature.

_<
I believe you are looking for
 extern(C++,class) struct C {}

 void create(T)(T** x);
or
 extern(C++,struct) class C {}

 void create(T)(T** x);
I can't remember which is the one you want here (still half asleep from jet lag). in the case of e.g. extern(C++,struct) class C {} this tells the D compiler that is should mangle it as though it is a struct (as it is declared in C++ as a struct) but it actually has a vtable and behaves like a class from the D school of thought. Vice versa for extern(C++,class) struct C {}
May 23 2018
parent reply Manu <turkeyman gmail.com> writes:
On 23 May 2018 at 03:14, Nicholas Wilson via Digitalmars-d
<digitalmars-d puremagic.com> wrote:
 On Wednesday, 23 May 2018 at 07:09:40 UTC, Manu wrote:
 C++:
 ---------------------------------------
 class C {};

 template <typename T>
 void create(T** x);
 ---------------------------------------

 D:
 ---------------------------------------
 extern(C++) class C {}

 void create(T)(T* x);
 ---------------------------------------

 Trouble is; in CPP, the template mangles as a C, but in D, the class
 mangles as C*... so the mangling doesn't match.

 `template<typename Class>` is an unbelievably common occurrence in C++...
 but how do we express a signature that mangles correctly in D? D always
 mangles `Class` as `Class*`... which changes the signature.

 _<
I believe you are looking for
 extern(C++,class) struct C {}

 void create(T)(T** x);
or
 extern(C++,struct) class C {}

 void create(T)(T** x);
I can't remember which is the one you want here (still half asleep from jet lag). in the case of e.g. extern(C++,struct) class C {} this tells the D compiler that is should mangle it as though it is a struct (as it is declared in C++ as a struct) but it actually has a vtable and behaves like a class from the D school of thought. Vice versa for extern(C++,class) struct C {}
Sadly, neither of these are correct. The type is a class (has vtable, etc), so it is declared in D as a class... It is also a class in C++, so it must mangle like a class. It's also the case that it's passed by pointer, in C++ and in D. It's a class that definitely behaves like a class. The trouble is getting the class name into the function signature as T, where the D compiler really wants to put Class* because that's the type it sees a D class to be.
May 23 2018
parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 5/23/2018 10:48 AM, Manu wrote:
 Sadly, neither of these are correct.
 The type is a class (has vtable, etc), so it is declared in D as a
 class... It is also a class in C++, so it must mangle like a class.
 It's also the case that it's passed by pointer, in C++ and in D. It's
 a class that definitely behaves like a class.
 The trouble is getting the class name into the function signature as
 T, where the D compiler really wants to put Class* because that's the
 type it sees a D class to be.
One way is to create a wrapper for C in another module: ---- a.d ----- extern (C++) class C { ... } ---- b.d ----- import a; extern (C++) struct C { a.C m; alias m this; } -------------- This relies on D regarding a.C and b.C as different symbols, even though they mangle the same.
May 25 2018
parent Manu <turkeyman gmail.com> writes:
On 25 May 2018 at 11:28, Walter Bright via Digitalmars-d
<digitalmars-d puremagic.com> wrote:
 On 5/23/2018 10:48 AM, Manu wrote:
 Sadly, neither of these are correct.
 The type is a class (has vtable, etc), so it is declared in D as a
 class... It is also a class in C++, so it must mangle like a class.
 It's also the case that it's passed by pointer, in C++ and in D. It's
 a class that definitely behaves like a class.
 The trouble is getting the class name into the function signature as
 T, where the D compiler really wants to put Class* because that's the
 type it sees a D class to be.
One way is to create a wrapper for C in another module: ---- a.d ----- extern (C++) class C { ... } ---- b.d ----- import a; extern (C++) struct C { a.C m; alias m this; } -------------- This relies on D regarding a.C and b.C as different symbols, even though they mangle the same.
Ah, interesting strategy! Although, they don't mangle the same... extern (C++, class) struct C { ... } That should do it! :)
May 25 2018