www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - toHash() and Interfaces

reply Nrgyzer <nrgyzer gmail.com> writes:
Hey guys,

I'm trying to call toHash() in a class which receives an interface
class as input param. But I always get "Error: no property 'toHash'
for type...".

My code looks like:

module iFBlock;

private {
   import std.stream;
}

interface IFBlock {
   public {
      void write(Stream);
   }
}

module myFile;

private {
   import iFBlock;
}

class MyFile {
   private {
       IFBlock[hash_t] pBlocks;
   }
   public {
       void addBlock(IFBlock b) {
           pBlocks[b.toHash()] = b;
       }
   }
}

Is there any chance to get the hash of the FBlock-interface?

Thanks in advance!
May 05 2011
next sibling parent reply "Steven Schveighoffer" <schveiguy yahoo.com> writes:
On Thu, 05 May 2011 17:03:51 -0400, Nrgyzer <nrgyzer gmail.com> wrote:

 Hey guys,

 I'm trying to call toHash() in a class which receives an interface
 class as input param. But I always get "Error: no property 'toHash'
 for type...".

 My code looks like:

 module iFBlock;

 private {
    import std.stream;
 }

 interface IFBlock {
    public {
       void write(Stream);
    }
 }

 module myFile;

 private {
    import iFBlock;
 }

 class MyFile {
    private {
        IFBlock[hash_t] pBlocks;
    }
    public {
        void addBlock(IFBlock b) {
            pBlocks[b.toHash()] = b;
        }
    }
 }

 Is there any chance to get the hash of the FBlock-interface?

(cast(Object)b).toHash() D has this horrible notion that any interface can be for a COM object, even though COM interfaces can only inherit from IUnknown (known statically). Therefore, interfaces that don't inherit from IUnknown are not considered Objects, even though they could and should be. So you have to manually cast an interface to Object in order to call an Object function. -Steve
May 06 2011
next sibling parent Nrgyzer <nrgyzer gmail.com> writes:
== Auszug aus Steven Schveighoffer (schveiguy yahoo.com)'s Artikel
 On Thu, 05 May 2011 17:03:51 -0400, Nrgyzer <nrgyzer gmail.com>

 Hey guys,

 I'm trying to call toHash() in a class which receives an interface
 class as input param. But I always get "Error: no property


 for type...".

 My code looks like:

 module iFBlock;

 private {
    import std.stream;
 }

 interface IFBlock {
    public {
       void write(Stream);
    }
 }

 module myFile;

 private {
    import iFBlock;
 }

 class MyFile {
    private {
        IFBlock[hash_t] pBlocks;
    }
    public {
        void addBlock(IFBlock b) {
            pBlocks[b.toHash()] = b;
        }
    }
 }

 Is there any chance to get the hash of the FBlock-interface?

D has this horrible notion that any interface can be for a COM

 even though COM interfaces can only inherit from IUnknown (known
 statically).  Therefore, interfaces that don't inherit from

 not considered Objects, even though they could and should be.
 So you have to manually cast an interface to Object in order to

 Object function.
 -Steve

Ah, okay - a bit dirty solution, but it works, thanks!
May 06 2011
prev sibling parent Stewart Gordon <smjg_1998 yahoo.com> writes:
On 06/05/2011 13:02, Steven Schveighoffer wrote:
<snip>
 D has this horrible notion that any interface can be for a COM object, even
though COM
 interfaces can only inherit from IUnknown (known statically). Therefore,
interfaces that
 don't inherit from IUnknown are not considered Objects, even though they could
and should be.

Firstly, IUnknown is defined in the Phobos files, not a language built-in. There might be multiple IUnknowns, defined in different modules (e.g. because some set of bindings has its own copy). How should the compiler identify the IUnknown to use? By name? By the signatures of functions specified within it? By fully qualified name? Secondly, I guess it's perfectly possible for some other system, besides COM, to create non-D objects that implement D interfaces.
 So you have to manually cast an interface to Object in order to call an Object
function.

Which you can do, if you are certain that the object will always be a D object. I guess the whole point is to protect you from those cases where you can't be sure. Stewart.
May 11 2011
prev sibling parent "Steven Schveighoffer" <schveiguy yahoo.com> writes:
On Wed, 11 May 2011 19:43:03 -0400, Stewart Gordon <smjg_1998 yahoo.com>  
wrote:

 On 06/05/2011 13:02, Steven Schveighoffer wrote:
 <snip>
 D has this horrible notion that any interface can be for a COM object,  
 even though COM
 interfaces can only inherit from IUnknown (known statically).  
 Therefore, interfaces that
 don't inherit from IUnknown are not considered Objects, even though  
 they could and should be.

Firstly, IUnknown is defined in the Phobos files, not a language built-in. There might be multiple IUnknowns, defined in different modules (e.g. because some set of bindings has its own copy). How should the compiler identify the IUnknown to use? By name? By the signatures of functions specified within it? By fully qualified name?

No, the compiler treats it specially, COM interfaces and classes have a different layout than D objects, so the compiler has to generate different code if the class implements an interface which inherits from std.c.windows.com.IUnknown. From the spec: A COM interface is defined as one that derives from the interface std.c.windows.com.IUnknown. A COM interface differs from a regular D interface in that: * It derives from the interface std.c.windows.com.IUnknown. * It cannot be the argument of a DeleteExpression. * References cannot be upcast to the enclosing class object, nor can they be downcast to a derived interface. To accomplish this, an appropriate QueryInterface() would have to be implemented for that interface in standard COM fashion. * Classes derived from COM interfaces are COM classes. * The default linkage for member functions of COM classes is extern(System). * The first member of the vtbl[] is not the pointer to the InterfaceInfo, but the first virtual function pointer. ---------------- There is nothing here that makes it seem like this is undetectable at compile time. IMO: * cast(Object)someComInterface => compiler error * Object o = someComInterface => compiler error * Object o = someNormalInterface => success Is all doable without incurring any problems.
 Secondly, I guess it's perfectly possible for some other system, besides  
 COM, to create non-D objects that implement D interfaces.

But none of these exist today. All cases of 'alternative' interfaces have alternative layouts and statically detectable triggers (such as IUnknown) that would allow us to statically allow or disallow implicit casting to Object. If we simply make a rule right now that alternative layouts have to be typed with some modifier (like extern(C++) for example) we can have implicit casting to object and get rid of all these ridiculous problems.
 So you have to manually cast an interface to Object in order to call an  
 Object function.

Which you can do, if you are certain that the object will always be a D object. I guess the whole point is to protect you from those cases where you can't be sure.

The compiler can always be sure, it just isn't programmed to know it yet... -Steve
May 16 2011