| Thread overview | |||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
January 26, 2016 Fun with extern(C++) | ||||
|---|---|---|---|---|
| ||||
Okay, new issues:
extern(C++) class Base {}
class Derived : Base {}
It seems that 'Derived' is implicitly a C++ class... I guess that seems okay, but this leads to a series of edges where things start breaking down...
pragma(msg, BaseClassesTuple!Derived); -> Error: tuple index 0 exceeds 0
Okay... that's broken. But I need to know it's base class.
pragma(msg, BaseTypeTuple!ComponentType); -> (in Base)
Base is reported as an interface? That's weird... and get's me wondering:
interface Iface {}
class Derived2 : Base, Iface {}
-> Error: C++ class 'Derived2' cannot implement D interface 'Iface'
Hmmm. I wonder if this will cause problems...
Is it impossible to support a C++ class implementing a D interface?
Users will need to declare extern(C++) interfaces anytime they want to
use it on any class with a C++ base class?
I kinda hoped that having a C++ class at the bottom of the stack would just be a detail once D classes are derived from it, but it seems that any class derived from a C++ base is placed into a separate world.
At very least, I need BaseClassesTuple to work with C++ classes. I suspect this is probably fixable?
| ||||
January 26, 2016 Re: Fun with extern(C++) | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Manu | On 2016-01-26 13:59, Manu via Digitalmars-d wrote: > Hmmm. I wonder if this will cause problems... > Is it impossible to support a C++ class implementing a D interface? No that I know how the C++ compatibility works but I would guess the compiler needs to know at compile time how to call a method. If it would be possible to implement a D interface as either a D class or C++ class. The compiler cannot know which runtime type a variable which is declared as an interface can hold. interface A { void foo(); } class B : A { void foo(); } extern(C++) class C : A { void foo(); } // assuming this works A a = new B; A b = new C; // assuming this works a.foo(); b.foo(); When the compiler sees "a" or "b", how should it know it should call "foo" as a D method or C++ method? It only knows about the static type which is A, a D interface. -- /Jacob Carlborg | |||
January 26, 2016 Re: Fun with extern(C++) | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Manu | On Tuesday, 26 January 2016 at 12:59:35 UTC, Manu wrote: > Hmmm. I wonder if this will cause problems... > Is it impossible to support a C++ class implementing a D interface? D interfaces are implicitly convertible to Object. > I kinda hoped that having a C++ class at the bottom of the stack would just be a detail once D classes are derived from it, but it seems that any class derived from a C++ base is placed into a separate world. D classes are derived from Object class. | |||
January 26, 2016 Re: Fun with extern(C++) | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Jacob Carlborg | On 1/26/16 8:58 AM, Jacob Carlborg wrote:
> On 2016-01-26 13:59, Manu via Digitalmars-d wrote:
>
>> Hmmm. I wonder if this will cause problems...
>> Is it impossible to support a C++ class implementing a D interface?
>
> No that I know how the C++ compatibility works but I would guess the
> compiler needs to know at compile time how to call a method. If it would
> be possible to implement a D interface as either a D class or C++ class.
> The compiler cannot know which runtime type a variable which is declared
> as an interface can hold.
>
> interface A { void foo(); }
> class B : A { void foo(); }
> extern(C++) class C : A { void foo(); } // assuming this works
>
> A a = new B;
> A b = new C; // assuming this works
>
> a.foo();
> b.foo();
>
> When the compiler sees "a" or "b", how should it know it should call
> "foo" as a D method or C++ method? It only knows about the static type
> which is A, a D interface.
>
The short answer to this question is, no you cannot. The layouts are different. It's why I have always said, D interfaces should implicitly convert to Object and support all Object methods. Only D classes can implement D interfaces.
-Steve
| |||
January 27, 2016 Re: Fun with extern(C++) | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Jacob Carlborg | On 26 January 2016 at 23:58, Jacob Carlborg via Digitalmars-d <digitalmars-d@puremagic.com> wrote:
> On 2016-01-26 13:59, Manu via Digitalmars-d wrote:
>
>> Hmmm. I wonder if this will cause problems...
>> Is it impossible to support a C++ class implementing a D interface?
>
>
> No that I know how the C++ compatibility works but I would guess the compiler needs to know at compile time how to call a method. If it would be possible to implement a D interface as either a D class or C++ class. The compiler cannot know which runtime type a variable which is declared as an interface can hold.
>
> interface A { void foo(); }
> class B : A { void foo(); }
> extern(C++) class C : A { void foo(); } // assuming this works
>
> A a = new B;
> A b = new C; // assuming this works
>
> a.foo();
> b.foo();
>
> When the compiler sees "a" or "b", how should it know it should call "foo" as a D method or C++ method? It only knows about the static type which is A, a D interface.
I'm not sure there's a difference in the calling convention... the function being called may perform adjustment of the 'this' pointer such that it's correct relative to the class that implemented the function, but that's internal to the function being called.
| |||
January 27, 2016 Re: Fun with extern(C++) | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Kagamin | On 27 January 2016 at 00:37, Kagamin via Digitalmars-d <digitalmars-d@puremagic.com> wrote: > On Tuesday, 26 January 2016 at 12:59:35 UTC, Manu wrote: >> >> Hmmm. I wonder if this will cause problems... >> Is it impossible to support a C++ class implementing a D interface? > > > D interfaces are implicitly convertible to Object. How does that work? I've never really used classes in D. >> I kinda hoped that having a C++ class at the bottom of the stack would just be a detail once D classes are derived from it, but it seems that any class derived from a C++ base is placed into a separate world. > > > D classes are derived from Object class. So, you're saying that if you have an 'I' pointer, which may be implemented by a C++ class, it still needs to be able to cast to Object, and therefore fails? I wonder if a C++ class could somehow be promoted to a D class when being derived in D, by having an Object placed somewhere. 'this' adjustment might be required at that point though, and that's not really nice in C++. | |||
January 27, 2016 Re: Fun with extern(C++) | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Steven Schveighoffer | On 27 January 2016 at 01:38, Steven Schveighoffer via Digitalmars-d <digitalmars-d@puremagic.com> wrote:
> On 1/26/16 8:58 AM, Jacob Carlborg wrote:
>>
>> On 2016-01-26 13:59, Manu via Digitalmars-d wrote:
>>
>>> Hmmm. I wonder if this will cause problems...
>>> Is it impossible to support a C++ class implementing a D interface?
>>
>>
>> No that I know how the C++ compatibility works but I would guess the compiler needs to know at compile time how to call a method. If it would be possible to implement a D interface as either a D class or C++ class. The compiler cannot know which runtime type a variable which is declared as an interface can hold.
>>
>> interface A { void foo(); }
>> class B : A { void foo(); }
>> extern(C++) class C : A { void foo(); } // assuming this works
>>
>> A a = new B;
>> A b = new C; // assuming this works
>>
>> a.foo();
>> b.foo();
>>
>> When the compiler sees "a" or "b", how should it know it should call "foo" as a D method or C++ method? It only knows about the static type which is A, a D interface.
>>
>
> The short answer to this question is, no you cannot. The layouts are different. It's why I have always said, D interfaces should implicitly convert to Object and support all Object methods. Only D classes can implement D interfaces.
Interface is just a vtable... what makes the layout different? Surely any class can take a vtable definition and populate it with some function pointers.
| |||
January 26, 2016 Re: Fun with extern(C++) | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Manu | On 2016-01-26 16:49, Manu via Digitalmars-d wrote: > I'm not sure there's a difference in the calling convention... the > function being called may perform adjustment of the 'this' pointer > such that it's correct relative to the class that implemented the > function, but that's internal to the function being called. Isn't the layout of the vtables different? -- /Jacob Carlborg | |||
January 27, 2016 Re: Fun with extern(C++) | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Jacob Carlborg | On 27 January 2016 at 02:01, Jacob Carlborg via Digitalmars-d <digitalmars-d@puremagic.com> wrote:
> On 2016-01-26 16:49, Manu via Digitalmars-d wrote:
>
>> I'm not sure there's a difference in the calling convention... the function being called may perform adjustment of the 'this' pointer such that it's correct relative to the class that implemented the function, but that's internal to the function being called.
>
>
> Isn't the layout of the vtables different?
Probably, but the layout of the vtable is defined by the interface,
and the interface type is always known, so I don't see why there
should be any problem. Whether it's extern(C++) or extern(D), the
class populating the vtable with functions knows the layout.
I think it all comes down to this conversion to Object thing. If an
interface must do that, then that's probably an issue without jamming
an Object instance in the class somewhere.
| |||
January 26, 2016 Re: Fun with extern(C++) | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Manu | On Tuesday, 26 January 2016 at 16:13:55 UTC, Manu wrote:
>
> Probably, but the layout of the vtable is defined by the interface,
> and the interface type is always known, so I don't see why there
> should be any problem. Whether it's extern(C++) or extern(D), the
> class populating the vtable with functions knows the layout.
> I think it all comes down to this conversion to Object thing. If an
> interface must do that, then that's probably an issue without jamming
> an Object instance in the class somewhere.
For a C++ class the first entry in the vtable is actually the first virtual function. (usually the destructor).
For a D class the first entry in the vtable is the classinfo. Thus the problem if you derive a D class from a extern(C++) base class. I don't see any way to actually fix this, adjusting the this pointer won't help. Once you derive a D class from a extern(C++) base class it is no longer a fully functional D class. For example monitor (e.g. synchronized methods) won't work.
| |||
Copyright © 1999-2021 by the D Language Foundation
Permalink
Reply