www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Destructors for structs

reply "John C" <johnch_atms hotmail.com> writes:
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). 
Mar 23 2005
next sibling parent "Andrew Fedoniouk" <news terrainformatica.com> writes:
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).
 

Mar 23 2005
prev sibling next sibling parent reply Chris Sauls <ibisbasenji gmail.com> writes:
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 

 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
Mar 23 2005
parent "John C" <johnch_atms hotmail.com> writes:
"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

 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 

Mar 23 2005
prev sibling next sibling parent reply "Carlos Santander B." <csantander619 gmail.com> writes:
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
Mar 23 2005
parent "John C" <johnch_atms hotmail.com> writes:
"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 

Mar 23 2005
prev sibling parent Russ Lewis <spamhole-2001-07-16 deming-os.org> writes:
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); }
}
Mar 24 2005