cast class references to void and back

Regan Heath regan at netmail.co.nz
Tue Sep 18 04:33:38 PDT 2007


BLS wrote:
> Regan Heath schrieb:
>> BLS wrote:
>>> BLS schrieb:
>>>>
>>>>  From the D spec;
>>>>
>>>> Pointer Conversions
>>>> Casting pointers to non-pointers and vice versa is allowed in D, 
>>>> however, do not do this for any pointers that point to data 
>>>> allocated by the garbage collector.
>>>>
>>>> Given :
>>>> Class CWin : CMsg
>>>> {
>>>>   Cwin pWnd = null;  // create a refrence
>>>>
>>>>  /* C++
>>>>  pWnd = 
>>>> reinterpret_cast<CWin*>((long)((LPCREATESTRUCT)lParam)->lpCreateParams); 
>>>>
>>>>   */
>>>>
>>>>   // D probabely
>>>>   pWnd = cast(CWin)(cast(LPCREATESTRUCT)lParam).lpCreateParams;
>>>>
>>>> }
>>>>
>>>> The LPCREATESTRUCT from WinUser.d
>>>> struct CREATESTRUCTA {
>>>>     LPVOID    lpCreateParams;   // Here I am
>>>>     HINSTANCE hInstance;
>>>>     HMENU     hMenu;
>>>>     HWND      hwndParent;
>>>>     // etc.
>>>> }
>>>> alias CREATESTRUCTA* LPCREATESTRUCTA;
>>>>
>>>> So :
>>>> 1) Do I have to put a cast(int) in there (where the (long) was in C++)
>>>> The reason you would use 'int' and not 'long' is that long in C++ is 
>>>> typically 32 bits and long in D is 64 bits.
>>>>
>>>> 2) I'm not 100% certain that it is guaranteed to work if you cast 
>>>> class references to void and back again.  Someone else might be able 
>>>> to confirm/deny this.
>>>> 3) Following the D spec. this is also not guaranteed to work. 
>>>> confirm/deny ?
>>>>
>>>> Thanks in advance
>>>> Bjoern
>>>
>>> Still someone out there who is still mental health ? 'cause const 
>>> discussion :-)
>>>
>>> In this case just  another question,
>>> In case that I define
>>> Class CWnd
>>> {
>>>   CWnd* pWnd = 0;
>>>
>>> }
>>> Do I have then in fact CWin** (from a C++ view) ?
>>
>> Sort of, you have a pointer to a reference to a Cwnd class object. 
>> Where a 'reference' is like but not exactly the same as a pointer.
>>
>> Regan
> Thanks for clarification Regan.
> as you can see I,ve just copied the most of your comments ... ashamed 
> ... ,a bit ;-)

No problem, I just hope I'm not wrong!  <g>

After reading that bit of the spec it seems that...

The first and most important question is, what allocates the value 
assigned to lpCreateParams?  Is the CREATESTRUCTA struct allocated in a 
call to a C function?


If 'yes' then chances are the lpCreateParams value was also allocated by 
that C function.  This raises the question, if it's a pointer to a C++ 
class is it compatible with D?  Is it a COM class?

I'm not sure how D interops with COM so I'm not much help here.

What it does mean is that you should be able to cast to int and back 
again.  However, the real question there is why was it being cast in C++ 
and do you need to do it in D.  I don't know why but I'd guess it's 
related to the size of pointers in which case I believe you don't need 
it on D.


If CREATESTRUCTA is allocated within D, and lpCreateParams is a 
reference to a D class then you should not cast to int, unless that 
class has a custom 'new':

http://www.digitalmars.com/d/class.html#ClassAllocator
http://www.digitalmars.com/d/class.html#ClassDeallocator

which uses malloc and gc.addRange (though using gc.addRange may 
invalidate this, not sure).


So, either way you shouldn't cast to int.  In which case that piece of 
the spec no longer applies as LPVOID is void* (a pointer type).  So, I 
would just use:

pWnd = cast(CWin)(cast(LPCREATESTRUCT)lParam).lpCreateParams;

Regan



More information about the Digitalmars-d mailing list