Thread overview
extern(C++) template problem
May 23, 2018
Manu
May 23, 2018
Nicholas Wilson
May 23, 2018
Manu
May 25, 2018
Walter Bright
May 26, 2018
Manu
May 23, 2018
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
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
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 25, 2018
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
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! :)