www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - cast class references to void and back

reply BLS <nanali nospam-wanadoo.fr> writes:
 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
Sep 18 2007
parent reply BLS <nanali nospam-wanadoo.fr> writes:
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) ?
Sep 18 2007
parent reply Regan Heath <regan netmail.co.nz> writes:
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
Sep 18 2007
parent reply BLS <nanali nospam-wanadoo.fr> writes:
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 ;-) Bjoern Bjoern
Sep 18 2007
parent Regan Heath <regan netmail.co.nz> writes:
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
Sep 18 2007