October 01, 2007
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'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
October 02, 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
1 2
Next ›   Last »