Thread overview
Destructors for structs
Mar 23, 2005
John C
Mar 23, 2005
Andrew Fedoniouk
Mar 23, 2005
Chris Sauls
Mar 23, 2005
John C
Mar 23, 2005
John C
Mar 24, 2005
Russ Lewis
March 23, 2005
Is it possible to simulate destructors for structs? I've run into a situation where using a class isn't workable because it has to interop with Win32 COM.

    struct Variant {

        static Variant opCall(int value) {
            Variant var;
            var.vt = VARTYPE.I4;
            var.lVal = value;
            return var;
        }

        static Variant opCall(wchar[] value) {
            Variant var;
            var.vt = VARTYPE.BSTR;
            var.bstr = SysAllocString(toUTF16z(value));
            return var;
        }

        ushort vt;
        ...
        int lVal;
        wchar* bstr;
        ...

    }

It's basically a wrapper for a COM VARIANT, but instead of having the user do all the tedious initialisation themselves, I want the struct to handle it via opCall. The problem is, of course, without a destructor, I don't get a chance to free the memory allocated from SysAllocString() with SysFreeString().

I've tried implementing it as a class, but it doesn't play well with others (ie, COM functions).


March 23, 2005
Probably out of scope:

To use variants in variant pool - cyclic buffer.
In other words - poor man resource GC

struct Variant {
    static Variant opCall(int value)
       {
            poolPos = (poolPos + 1) & 0xFF;
            FreeVariant(pool[poolPos]);
            InitVariant(pool[poolPos], .......);
            return pool[poolPos];
      }
}

Variant[256] pool;
uint poolPos;

As a rule COM VARIANTs are short living objects used for passing parameters to IDispatch derived objects so this approach will work.

Andrew.




"John C" <johnch_atms@hotmail.com> wrote in message news:d1s4b0$2n42$1@digitaldaemon.com...
> Is it possible to simulate destructors for structs? I've run into a situation where using a class isn't workable because it has to interop with Win32 COM.
>
>    struct Variant {
>
>        static Variant opCall(int value) {
>            Variant var;
>            var.vt = VARTYPE.I4;
>            var.lVal = value;
>            return var;
>        }
>
>        static Variant opCall(wchar[] value) {
>            Variant var;
>            var.vt = VARTYPE.BSTR;
>            var.bstr = SysAllocString(toUTF16z(value));
>            return var;
>        }
>
>        ushort vt;
>        ...
>        int lVal;
>        wchar* bstr;
>        ...
>
>    }
>
> It's basically a wrapper for a COM VARIANT, but instead of having the user do all the tedious initialisation themselves, I want the struct to handle it via opCall. The problem is, of course, without a destructor, I don't get a chance to free the memory allocated from SysAllocString() with SysFreeString().
>
> I've tried implementing it as a class, but it doesn't play well with others (ie, COM functions).
> 


March 23, 2005
John C wrote:
> Is it possible to simulate destructors for structs? I've run into a
> situation where using a class isn't workable because it has to interop with
> Win32 COM.

Actually, and please someone correct me quickly if I'm wrong, but I believe D's class/interface system is designed with COM compatability in mind.  Check std.windows.iunknown in Phobos, which defines IUnknown for D as a class.

-- Chris Sauls
March 23, 2005
John C wrote:
> Is it possible to simulate destructors for structs? I've run into a situation where using a class isn't workable because it has to interop with Win32 COM.
> 
>     struct Variant {
> 
>         static Variant opCall(int value) {
>             Variant var;
>             var.vt = VARTYPE.I4;
>             var.lVal = value;
>             return var;
>         }
> 
>         static Variant opCall(wchar[] value) {
>             Variant var;
>             var.vt = VARTYPE.BSTR;
>             var.bstr = SysAllocString(toUTF16z(value));
>             return var;
>         }
> 
>         ushort vt;
>         ...
>         int lVal;
>         wchar* bstr;
>         ...
> 
>     }
> 
> It's basically a wrapper for a COM VARIANT, but instead of having the user do all the tedious initialisation themselves, I want the struct to handle it via opCall. The problem is, of course, without a destructor, I don't get a chance to free the memory allocated from SysAllocString() with SysFreeString().
> 
> I've tried implementing it as a class, but it doesn't play well with others (ie, COM functions). 
> 
> 

How about a class with an overloaded opCast? (please, don't kill me for this suggestion ;))

_______________________
Carlos Santander Bernal
March 23, 2005
"Chris Sauls" <ibisbasenji@gmail.com> wrote in message news:d1sc8u$2vi5$2@digitaldaemon.com...
> John C wrote:
> > Is it possible to simulate destructors for structs? I've run into a situation where using a class isn't workable because it has to
> interop with
> > Win32 COM.
>
> Actually, and please someone correct me quickly if I'm wrong, but I believe D's class/interface system is designed with COM compatability in mind.  Check std.windows.iunknown in Phobos, which defines IUnknown for D as a class.

Yes, D interfaces are compatible with COM interfaces, which is great. But VARIANT isn't a COM interface, it's a plain old struct, and (unlike in C++) D classes aren't compatible with structs because of the vtbl.

>
> -- Chris Sauls


March 23, 2005
"Carlos Santander B." <csantander619@gmail.com> wrote in message news:d1skpd$79a$1@digitaldaemon.com...
> John C wrote:
>> Is it possible to simulate destructors for structs? I've run into a situation where using a class isn't workable because it has to interop with Win32 COM.
>>
>>     struct Variant {
>>
>>         static Variant opCall(int value) {
>>             Variant var;
>>             var.vt = VARTYPE.I4;
>>             var.lVal = value;
>>             return var;
>>         }
>>
>>         static Variant opCall(wchar[] value) {
>>             Variant var;
>>             var.vt = VARTYPE.BSTR;
>>             var.bstr = SysAllocString(toUTF16z(value));
>>             return var;
>>         }
>>
>>         ushort vt;
>>         ...
>>         int lVal;
>>         wchar* bstr;
>>         ...
>>
>>     }
>>
>> It's basically a wrapper for a COM VARIANT, but instead of having the user do all the tedious initialisation themselves, I want the struct to handle it via opCall. The problem is, of course, without a destructor, I don't get a chance to free the memory allocated from SysAllocString() with SysFreeString().
>>
>> I've tried implementing it as a class, but it doesn't play well with others (ie, COM functions).
>
> How about a class with an overloaded opCast? (please, don't kill me for this suggestion ;))

Using opCast() had occurred to me, but I didn't try it until just now. It won't work with inout attributes on parameters -- lvalue hell -- but if I avoid those it's fine.

Thanks for the tip!

>
> _______________________
> Carlos Santander Bernal


March 24, 2005
Struct destructors would be nice, but since we don't have them, you can do it like this:

struct->class->data

So the struct contains the interface; it can call into the class object, which actually stores the data (or, at least, some of it).  The class object won't be GC'd until the struct is also garbage; at that point, you can clean things up with the class destructor.

This might be an interesting template.  Something like this, perhaps:



class Destructor(T) {
  T val;
  void delegate(Destructor) destructor;

  this(void delegate(Destructor) dg) { destructor = dg; }
  ~this() { destructor(this); }
}