Jump to page: 1 2
Thread overview
[BUG] casting Interface to class-instance generates bogus code
Apr 05, 2004
Kris
Apr 05, 2004
Kris
Apr 05, 2004
Ant
Apr 05, 2004
Kris
Apr 05, 2004
Ant
Apr 05, 2004
Walter
Apr 05, 2004
Kris
Apr 05, 2004
Walter
Apr 05, 2004
Kris
Apr 05, 2004
Kris
Apr 05, 2004
Walter
Apr 05, 2004
Hauke Duden
Apr 05, 2004
Walter
Apr 06, 2004
C
Apr 06, 2004
Hauke Duden
Apr 06, 2004
Ben Hinkle
Apr 06, 2004
Russ Lewis
April 05, 2004
I have a concrete-class that implements a generic interface. On occasion, said interface needs to be upcast to the concrete-class to access specialized functionality. Check out the cast(SocketConduit) code below ... it explicitly sets the lValue to zero.  Good Grief ...

112:          char[] getRemoteAddress (IConduit conduit)
00403290   enter       0Ch,0
00403294   mov         dword ptr [ebp-0Ch],eax
113:          {
114:                  SocketConduit socket = cast(SocketConduit) conduit;
00403297   xor         eax,eax
00403299   mov         dword ptr [socket],eax



April 05, 2004
On a hunch, I thought I'd try the old (void *) trick.

As you can see below, it actually persuaded the compiler into doing the right thing. Oh well; onto the next showstopper.

112:          char[] getRemoteAddress (IConduit conduit)
00403290   enter       0Ch,0
00403294   mov         dword ptr [ebp-0Ch],eax
113:          {
114:                  SocketConduit socket = cast(SocketConduit) cast(void
*) conduit;
00403297   mov         eax,dword ptr [conduit]
0040329A   mov         dword ptr [socket],eax


April 05, 2004
On Sun, 04 Apr 2004 19:25:18 -0800, Kris wrote:

> On a hunch, I thought I'd try the old (void *) trick.
> 
> 114:                  SocketConduit socket = cast(SocketConduit) cast(void
> *) conduit;

great. I had the same problem before and my work
around was... so complex that I even don't remember.

Ant

April 05, 2004
Oops; I'm afraid I jumped the gun on that one. The (void *) cast drops some
of the vTable offsets (or something), so it end's up calling the wrong
place. I'm not sure if that's better or worse than before :-)

I was just going through the code to see if I could avoid the interface altogether, and I'm afraid that would make the whole system specific to SocketConduit only. Hence that is simply not an option.

If you can recall what you did to resolve your issue? I'd really appreciate any help Ant.

Cheers,

- Kris

> Ant wrote:
> great. I had the same problem before and my work
> around was... so complex that I even don't remember.
>
> Ant
>


April 05, 2004
On Sun, 04 Apr 2004 19:48:27 -0800, Kris wrote:

> Oops; I'm afraid I jumped the gun on that one. The (void *) cast drops some
> of the vTable offsets (or something), so it end's up calling the wrong
> place. I'm not sure if that's better or worse than before :-)
> 
> I was just going through the code to see if I could avoid the interface altogether, and I'm afraid that would make the whole system specific to SocketConduit only. Hence that is simply not an option.
> 
> If you can recall what you did to resolve your issue? I'd really appreciate any help Ant.
> 
> Cheers,
> 
> - Kris

Sorry, I don't think I can help, I really don't
remember but I think I redesign something
and I'm avoiding it since.

I believe this is covered on Burton Radons
interface and inheritance bug report let's
hope Walter is looking at that.

Ant

April 05, 2004
The problem here is that all an interface is, when implemented, is a pointer to a vtbl[]. There's no way the runtime can tell where it came from, so there is no way to upcast it.

The way to deal with this is to add a member function to the interface that is equivalent to the 'ClassFactory' function in COM programming. Then, in the implementation of that function, which does know the object type enclosing the interface, the cast can be done.

interface IConduit
{
    SocketConduit isSocketConduit();
}

class SocketConduit : IConduit
{
    SocketConduit isSocketConduit() { return this; }
}

char[] getRemoteAddress(IConduit conduit)
{
    SocketConduit socket = conduit.isSocketConduit();
}


"Kris" <someidiot@earthlink.dot.dot.dot.net> wrote in message news:c4qi35$24f8$1@digitaldaemon.com...
> I have a concrete-class that implements a generic interface. On occasion, said interface needs to be upcast to the concrete-class to access specialized functionality. Check out the cast(SocketConduit) code below
...
> it explicitly sets the lValue to zero.  Good Grief ...
>
> 112:          char[] getRemoteAddress (IConduit conduit)
> 00403290   enter       0Ch,0
> 00403294   mov         dword ptr [ebp-0Ch],eax
> 113:          {
> 114:                  SocketConduit socket = cast(SocketConduit) conduit;
> 00403297   xor         eax,eax
> 00403299   mov         dword ptr [socket],eax
>
>
>


April 05, 2004
Thank-you Walter. I truly appreciate your help on this.

BTW, is this the expected long-term solution? If so (and I don't think it should be <g>) the compiler really needs to toss an error, rather than emitting grossly unjust access-violators ...

- Kris


"Walter" <walter@digitalmars.com> wrote in message news:c4sk0f$2eon$1@digitaldaemon.com...
> The problem here is that all an interface is, when implemented, is a
pointer
> to a vtbl[]. There's no way the runtime can tell where it came from, so there is no way to upcast it.
>
> The way to deal with this is to add a member function to the interface
that
> is equivalent to the 'ClassFactory' function in COM programming. Then, in the implementation of that function, which does know the object type enclosing the interface, the cast can be done.
>


April 05, 2004
Whoops -- I meant to add why I feel this should not be the accepted procedure:

The solution provided works fine to skirt the issue at hand, but the methodology requires that the base-class (or base-interface) is pre-configured to know about *all possible derivations* (subclasses). That, is simply unrealistic.

- Kris

"Walter" <walter@digitalmars.com> wrote in message news:c4sk0f$2eon$1@digitaldaemon.com...
> The problem here is that all an interface is, when implemented, is a
pointer
> to a vtbl[]. There's no way the runtime can tell where it came from, so there is no way to upcast it.
>
> The way to deal with this is to add a member function to the interface
that
> is equivalent to the 'ClassFactory' function in COM programming. Then, in the implementation of that function, which does know the object type enclosing the interface, the cast can be done.
>>


April 05, 2004
Please forgive my gratuitous overuse of this NG ...

Thinking about this a little more Walter, if the base-interface were to implement just the upcast to a concrete Object, then dynamic-casting should handle it from there. For example:

interface IConduit
{
    Object  toObject();
}

class SocketConduit : IConduit
{
    Object  toObject() { return this; }
}

char[] getRemoteAddress(IConduit conduit)
{
    SocketConduit socket = cast(SocketConduit) conduit.toObject();
}

This, at least, is extensible. Though I'm torn as to whether it's the right-thing-to-do <g>

Note:  one might be tempted to implement this instead as:

interface IConduit
{
    Conduit  toConduit();
}

...assuming there were a base-class implementation for IConduit.

However, that doesn't lend itself toward a sense of 'pattern' (let alone the potential "forward reference" issues that an Interfaces is handy for resolving).

If, in fact, you were to decide the suggested approach is the long-term solution, then you might consider adding a hidden toObject() declaration to each interface, and the corresponding "return this;" implementation to each of the appropriate classes. If so, toObject() could thus become a property of any Interface. Not too sure about that attitude though.





"Kris" <someidiot@earthlink.dot.dot.dot.net> wrote in message news:c4skns$2fu9$1@digitaldaemon.com...
> The solution provided works fine to skirt the issue at hand, but the
> methodology requires that the base-class (or base-interface) is
> pre-configured to know about *all possible derivations* (subclasses).
That,
> is simply unrealistic.
>


April 05, 2004
Walter wrote:
> The problem here is that all an interface is, when implemented, is a pointer
> to a vtbl[]. There's no way the runtime can tell where it came from, so
> there is no way to upcast it.

"No way", as in "impossible", or in "no way" as in "not for 1.0"? ;)

Couldn't there be a virtual function "Object __getObject()" that is automatically generated for all classes? Then the cast operator could simply call this function when casting an interface to an object. Seems like the only way to have the cast operator behave consistently.

Hauke
« First   ‹ Prev
1 2