C++ cast to D cast again :)

BLS nanali at nospam-wanadoo.fr
Tue Oct 2 00:36:29 PDT 2007


Bill Baxter schrieb:
> BLS wrote:
>> Bill Baxter schrieb:
>>> BLS wrote:
>>>> div0 schrieb:
>>>>> div0 wrote:
>>>>>> BLS wrote:
>>>>>>> div0 schrieb:
>>>>>>>> BLS wrote:
>>>>>>>>> Hi and sorry about picking on your nerves again  :(
>>>>>>>>> // C++
>>>>>>>>> class CWin
>>>>>>>>> {
>>>>>>>>> //
>>>>>>>>> static LRESULT CALLBACK WndProc(HWND hWnd, UINT uID, WPARAM 
>>>>>>>>> wParam, LPARAM lParam)
>>>>>>>>> {
>>>>>>>>>   CWin* pWnd=NULL;  // init pWnd
>>>>>>>>> }
>>>>>>>>>
>>>>>>>>> // later ...
>>>>>>>>> CWin* pChild=reinterpret_cast<CWin*>((HWND)
>>>>>>>>> ::GetWindowLong(pWnd->GetDlgItem( ((( LPDRAWITEMSTRUCT 
>>>>>>>>> )lParam)->CtlID) ),GWL_USERDATA) );
>>>>>>>>>
>>>>>>>>>
>>>>>>>>> }
>>>>>>>>>
>>>>>>>>> //our D class
>>>>>>>>> class CWin
>>>>>>>>> {
>>>>>>>>> static LRESULT WndProc(HWND hWnd, UINT uID, WPARAM wParam, 
>>>>>>>>> LPARAM lParam)
>>>>>>>>> {
>>>>>>>>>   CWin pWnd=null;  // init pWnd as    ---reference !
>>>>>>>>> }
>>>>>>>>> /* instead of :
>>>>>>>>> CWin* pChild=reinterpret_cast<CWin*>
>>>>>>>>> we use
>>>>>>>>> CWin pChild = cast(CWin) cast(void*)
>>>>>>>>>
>>>>>>>>> But I am not sure how to translate :
>>>>>>>>> ((HWND)
>>>>>>>>> ::GetWindowLong(pWnd->GetDlgItem( ((( LPDRAWITEMSTRUCT 
>>>>>>>>> )lParam)->CtlID) ),GWL_USERDATA) );
>>>>>>>>> */
>>>>>>>>>
>>>>>>>>> // Later we have
>>>>>>>>> if (HIWORD(pWnd))
>>>>>>>>>
>>>>>>>>> /*Since we are working with a ref. instead of a pointer this 
>>>>>>>>> will not work.
>>>>>>>>> I guess I can use :
>>>>>>>>> */
>>>>>>>>>
>>>>>>>>> if (HIWORD(cast(void*)pWnd))
>>>>>>>>> // can you confirm
>>>>>>>>> }
>>>>>>>>>
>>>>>>>>> GetWindowLong() is a Windows Api func., sure you know it.
>>>>>>>>> So what the correct translation ?
>>>>>>>>> Bjoern
>>>>>>>>> Beside, I still wonder : Having a class A, Is A* pA a legal 
>>>>>>>>> construct in D.
>>>>>>>>> What is pA from a technical view; a pointer to a reference ?
>>>>>>>>
>>>>>>>> Even if you get this to compile it won't work.
>>>>>>>> (well it will till one day until it just crashes mysteriously)
>>>>>>>>
>>>>>>>> At some point the garbage collector might decide move your Cwin 
>>>>>>>> object, invalidating the pointer you are trying to store with 
>>>>>>>> SetWindowLong/GetWindowLong.
>>>>>>>>
>>>>>>>
>>>>>>> Thanks div0,
>>>>>>> I am allready afraid that this is the case...
>>>>>>>
>>>>>>>> You'll have to either allocation your cwin objects outside the 
>>>>>>>> garbage collectors control or pin the objects. (Don't know how 
>>>>>>>> you do this, depends on whether you are using phobos or tango)
>>>>>>>>
>>>>>>>
>>>>>>> Tango.
>>>>>>>
>>>>>>> What means "pin the object", please explain.
>>>>>>> Bjoern
>>>>>>
>>>>>> Marks the object as not movable.
>>>>>> It looks like getAttr/setAttr is what you want, but I've not used 
>>>>>> it myself so don't blame me if your program crashes. ;)
>>>>>>
>>>>>> http://www.dsource.org/projects/tango/browser/trunk/lib/common/tango/core/Memory.d 
>>>>>>
>>>>>>
>>>>>>
>>>>>>>
>>>>>>>> You should probably look at how dfl interfaces with the Win32 
>>>>>>>> API, http://www.dprogramming.com/dfl.ph as that library has 
>>>>>>>> solved these issues and you should be able to work out how it's 
>>>>>>>> doing all the necessary casting/pinning.
>>>>>
>>>>> And to actually answer your original question:
>>>>>
>>>>>
>>>>> class CWin {
>>>>>     int    m_a;
>>>>>
>>>>>     this() {
>>>>>     }
>>>>> }
>>>>>
>>>>> extern(Windows){
>>>>>     typedef void* HWND;
>>>>>     int GetWindowLongA(HWND wnd, int indx);
>>>>>     int GetWindowLongW(HWND wnd, int indx);
>>>>> }
>>>>>
>>>>>
>>>>> void main()
>>>>> {
>>>>>     // do the call (assume mbcs not unicode)
>>>>>     int    r = GetWindowLongA(cast(HWND)0, 0);
>>>>>
>>>>>     // do the call & cast to CWin object pointer
>>>>>     CWin    *pWin = cast(CWin*)GetWindowLongA(cast(HWND)0, 0);
>>>>>     Stdout( r );
>>>>>     }
>>>>>
>>>>>
>>>>> Replace the 0's with the appropriate values, ie the window handle 
>>>>> and GWL_USERDATA (which is -21)
>>>>>
>>>>> compile with:
>>>>>     dmd main.d user32.lib
>>>>
>>>> We, means Bill B., Regan H., Jarret B. and me have discussed the C++ 
>>>> casting to D custing stuff a few days ago. Unfortunately our results 
>>>> regarding translating reinterpret_cast<CWin*> are different. Maybe 
>>>> we are wrong :(  ... Please have a look at :
>>>> http://www.prowiki.org/wiki4d/wiki.cgi?PortingFromCxx
>>>
>>> I don't think there's anything wrong with cast(T)(cast void*) as a 
>>> replacement for C's reinterpret_cast<T> -- ignoring any larger 
>>> context.  The issue that div0 is talking about is more global.  If 
>>> you're not storing your class pointers as class pointers anywhere 
>>> then the garbage collector might not realize there are still live 
>>> references and collect the thing prematurely.
>>>
>> ... Storing your class pointers as class pointers anywhere ...
>> Well,
>>
>> http://www.digitalmars.com/d/memory.html
>>
>> offers some ideas I don't understand. the docs are , in this case, too 
>> nitty gritty. qze!lra"lmirmglerhmohmj
>> Beeing really nagged and not far away from deleting all D related stuff.
> 
> This page would seem to be more relevant:
> http://www.digitalmars.com/d/garbage.html (though watch out -- that page 
> incorrectly implies that D uses a generational copying collector, which 
> it doesn't).
> 
> I don't know if you really have a GC problem or not here.  Div0 is at 
> least wrong about one thing -- the D GC will not try to move your 
> pointer.  D doesn't use that kind of GC.  D's GC never moves pointers. 
> It may delete them if it doesn't think they're in use, but it won't move 
> them around.  Basically the issue there is just that the GC only 
> considers pointer types.  So if you do something like this:
> 
>     size_t x = cast(size_t) new MyObject;
> 
> It doesn't matter that x holds the address to MyObject.  Since it holds 
> that address in a non-pointer type, D doesn't consider it as a potential 
> reference to memory.  And if it doesn't consider 'x', then there is 
> nothing else that points to that MyObject instance, so the GC will 
> collect it.
> 



> But BLS, taking a step back, I have to say, if you don't understand how 
> the original code works then your chances of successfully porting it 
> aren't good.  In general, there will be parts you just have to look and 
> and say -- "ok this won't work in D, this part I will rewrite".  You 
> have to understand the original code well enough to be able to detect 
> those situations, and to rewrite them as needed.

I guess you are right and I appreciate your still encouraging words.

My very optimistic goal was to translate the whole library within 3 
weeks or so, because the original code doesn't look very complicated.
But I have to realize that a 1:1 translation will not make much sense.
(at least for some parts of the lib)

And indeed, The leaning by translating approach failes.

> 
> I've given up trying to port different STL containers a couple of times 
> now, and the problem always comes down to not understanding the original 
> code well enough to rewrite some part of it.  And STL code is so hairy 
> that I start thinking it would be faster to go to the library, check out 
> a copy of Knuth's Art of Programming, read it, and implement something 
> from scratch.
> 
>>>> Of course! your comments are welcome.
>>>> Bjoern
>>>> Beside it is this part :
>>>> pWnd->GetDlgItem( ((( LPDRAWITEMSTRUCT ))lParam)->CtlID
>>>>
>>>> which makes me banging my head on the keyboard ;)
>>>
>>> looks like just
>>>   pWnd.GetDlgItem( (cast(LPDRAWITEMTRUCT)lParam).CtlID )
>>>
>>> what's the confusion?
>>>
>>> --bb
>> ((still Bad) case) of progammer's confusion. :(
>> For sure, C++ is not made for human beeings.
> 
> The C++ snippet does have an extra set of parentheses around the 
> LPDRAWITEMSTRUCT, so I guess that could be confusing.  And it helps to 
> know that in Microsoft-land "LPFOO" is just crazy talk for "FOO*".
> 
> --bb
Thanks Bill


More information about the Digitalmars-d-learn mailing list