namespace problem

General FreeBASIC programming questions.
jcfuller
Posts: 324
Joined: Sep 03, 2007 18:40

namespace problem

Postby jcfuller » Feb 13, 2008 20:55

Error on HWND_DESKTOP.

I also had problems using cast(LPARAM,xxx) in another app.

James

Code: Select all



#include once "windows.bi"

                                 
   

NAMESPACE name1
'':::::
function WndProc ( byval hWnd as HWND, _
                   byval wMsg as UINT, _
                   byval wParam as WPARAM, _
                   byval lParam as LPARAM ) as LRESULT
   
    function = 0
   
    select case( wMsg )
        case WM_CREATE           
            exit function

        case WM_PAINT
          dim rct as RECT
          dim pnt as PAINTSTRUCT
          dim hDC as HDC
         
            hDC = BeginPaint( hWnd, @pnt )
            GetClientRect( hWnd, @rct )
           
            DrawText( hDC, _
                    "Hello, World!", _
                    -1, _
                      @rct, _
                      DT_SINGLELINE or DT_CENTER or DT_VCENTER )
           
            EndPaint( hWnd, @pnt )
           
            exit function           
       
      case WM_KEYDOWN
         if( lobyte( wParam ) = 27 ) then
            PostMessage( hWnd, WM_CLOSE, 0, 0 )
         end if

       case WM_DESTROY
            PostQuitMessage( 0 )
            exit function
    end select
   
    function = DefWindowProc( hWnd, wMsg, wParam, lParam )   
   
end function

'':::::
function WinMain ( byval hInstance as HINSTANCE, _
                   byval hPrevInstance as HINSTANCE, _
                   byval szCmdLine as string, _
                   byval iCmdShow as integer ) as integer   
     
    dim wMsg as MSG
    dim wcls as WNDCLASS     
    dim hWnd as HWND
     
    function = 0
     
    with wcls
       .style         = CS_HREDRAW or CS_VREDRAW
       .lpfnWndProc   = @WndProc
       .cbClsExtra    = 0
       .cbWndExtra    = 0
       .hInstance     = hInstance
       .hIcon         = LoadIcon( NULL, IDI_APPLICATION )
       .hCursor       = LoadCursor( NULL, IDC_ARROW )
       .hbrBackground = GetStockObject( WHITE_BRUSH )
       .lpszMenuName  = NULL
       .lpszClassName = @"HelloWin"
    end with
         
    if( RegisterClass( @wcls ) = FALSE ) then
       MessageBox( null, "Failed to register wcls", "Error", MB_ICONERROR )
       exit function
    end if
   
    hWnd = CreateWindowEx( 0, _
                       @"HelloWin", _
                           "The Hello Program", _
                           WS_OVERLAPPEDWINDOW, _
                           CW_USEDEFAULT, _
                           CW_USEDEFAULT, _
                           CW_USEDEFAULT, _
                           CW_USEDEFAULT, _
                           HWND_DESKTOP, _
                           NULL, _
                           hInstance, _
                           NULL )
                         

    ShowWindow( hWnd, iCmdShow )
    UpdateWindow( hWnd )
     
    while( GetMessage( @wMsg, NULL, 0, 0 ) <> FALSE )   
        TranslateMessage( @wMsg )
        DispatchMessage( @wMsg )
    wend
   
    function = wMsg.wParam

end function

END NAMESPACE

END name1.WinMain( GETMODULEHANDLE( null ), null, Command( ), SW_NORMAL )
Imortis
Moderator
Posts: 1628
Joined: Jun 02, 2005 15:10
Location: USA
Contact:

Postby Imortis » Feb 14, 2008 2:15

is HWND_DESKTOP in the windows includes? I ask becaus it is not declared in your code.
stylin
Posts: 1253
Joined: Nov 06, 2005 5:19

Postby stylin » Feb 14, 2008 4:33

The program seems to works here if i change HWD_DESKTOP to GetDesktopWindow().
coderJeff
Site Admin
Posts: 3018
Joined: Nov 04, 2005 14:23
Location: Ontario, Canada
Contact:

Postby coderJeff » Feb 14, 2008 4:38

Same problem, but shorter example:

Code: Select all

type A as any ptr

#define B cptr(a,0)

namespace n

  sub foo( A as integer )
    print B
  end sub

end namespace

'' OUTPUT:
'' a.bas(8) : error 18: Syntax error, found 'a' in 'print B'


Looks like a problem expanding cptr(a,0) because 'A' is also the name of a parameter. Work-around would be to change the name of the parameter. But I think that's a bug because it works just fine if there is no namespace.
jcfuller
Posts: 324
Joined: Sep 03, 2007 18:40

Postby jcfuller » Feb 14, 2008 10:21

coderJeff,
Will you do an official bug report as your example is much smaller than mine.

James
jcfuller
Posts: 324
Joined: Sep 03, 2007 18:40

Postby jcfuller » Feb 14, 2008 13:23

On the cast error with namespace it appears a #Define problem.

Cast(Long,ParamVal) works fine but
Cast(LPARAM,ParamVal) fails

James
KristopherWindsor
Posts: 2428
Joined: Jul 19, 2006 19:17
Location: Sunnyvale, CA
Contact:

Postby KristopherWindsor » Feb 14, 2008 20:44

Are you allowed to access a Type from a different namespace, without Using?
notthecheatr
Posts: 1759
Joined: May 23, 2007 21:52
Location: Cut Bank, MT
Contact:

Postby notthecheatr » Feb 14, 2008 22:38

You can if the Type is part of the namespace above the current one.

If it were like this:

Code: Select all


NameSpace bar
  Type A As Any Ptr
End NameSpace

#define B cptr(a,0)

Namespace n

  Sub foo( A As Integer )
    Print B
  End Sub

End Namespace

'' OUTPUT:
'' a.bas(8) : error 18: Syntax error, found 'a' in 'print B'


Then yeah, you would probably need bar.A.


This stuff gets really really nasty, because preprocessor stuff doesn't regard the namespace at all, so often what may seem like a bug is simply incorrectly using the #defines or #macros with namespaces.
coderJeff
Site Admin
Posts: 3018
Joined: Nov 04, 2005 14:23
Location: Ontario, Canada
Contact:

Postby coderJeff » Apr 30, 2008 17:45

I know it's been a while...

As notthecheatr suggests:
- TYPE's respect namespaces,
- #define's do not.

That makes it difficult to use "windows.bi" with namespaces because it has both types and #defines.

Work-around for the code in the top post as follows:

Code: Select all

namespace name1

#include "windows.bi"

'':::::
Function WndProc ( Byval hWnd As HWND, _
                   Byval wMsg As UINT, _
                   Byval wParam As WPARAM, _
                   Byval lParam As LPARAM ) As LRESULT
   
    Function = 0
   
    Select Case( wMsg )
        Case WM_CREATE           
            Exit Function

        Case WM_PAINT
                    Dim rct As RECT
                    Dim pnt As PAINTSTRUCT
                    Dim hDC As HDC
         
            hDC = BeginPaint( hWnd, @pnt )
            GetClientRect( hWnd, @rct )
           
            DrawText( hDC, _
                              "Hello, World!", _
                              -1, _
                      @rct, _
                      DT_SINGLELINE Or DT_CENTER Or DT_VCENTER )
           
            EndPaint( hWnd, @pnt )
           
            Exit Function           
       
                Case WM_KEYDOWN
                        If( lobyte( wParam ) = 27 ) Then
                                PostMessage( hWnd, WM_CLOSE, 0, 0 )
                        End If

            Case WM_DESTROY
            PostQuitMessage( 0 )
            Exit Function
    End Select
   
    Function = DefWindowProc( hWnd, wMsg, wParam, lParam )   
   
End Function

'':::::
Function WinMain ( Byval hInstance As HINSTANCE, _
                   Byval hPrevInstance As HINSTANCE, _
                   Byval szCmdLine As String, _
                   Byval iCmdShow As Integer ) As Integer   
     
    Dim wMsg As MSG
    Dim wcls As WNDCLASS     
    Dim hWnd As HWND
     
    Function = 0
     
    With wcls
            .style         = CS_HREDRAW Or CS_VREDRAW
            .lpfnWndProc   = @WndProc
            .cbClsExtra    = 0
            .cbWndExtra    = 0
            .hInstance     = hInstance
            .hIcon         = LoadIcon( NULL, IDI_APPLICATION )
            .hCursor       = LoadCursor( NULL, IDC_ARROW )
            .hbrBackground = GetStockObject( WHITE_BRUSH )
            .lpszMenuName  = NULL
            .lpszClassName = @"HelloWin"
    End With
         
    If( RegisterClass( @wcls ) = FALSE ) Then
       MessageBox( null, "Failed to register wcls", "Error", MB_ICONERROR )
       Exit Function
    End If
   
    hWnd = CreateWindowEx( 0, _
                                               @"HelloWin", _
                           "The Hello Program", _
                           WS_OVERLAPPEDWINDOW, _
                           CW_USEDEFAULT, _
                           CW_USEDEFAULT, _
                           CW_USEDEFAULT, _
                           CW_USEDEFAULT, _
                           HWND_DESKTOP, _
                           NULL, _
                           hInstance, _
                           NULL )
                         

    ShowWindow( hWnd, iCmdShow )
    UpdateWindow( hWnd )
     
    While( GetMessage( @wMsg, NULL, 0, 0 ) <> FALSE )   
        TranslateMessage( @wMsg )
        DispatchMessage( @wMsg )
    Wend
   
    Function = wMsg.wParam

End Function

function WinMainEntry() as Integer
  Return WinMain( GETMODULEHANDLE( null ), null, Command( ), SW_NORMAL )
end function

End Namespace

End name1.WinMainEntry()


Problem is, "windows.bi" can only be included properly once per module, so it can be used in the global namespace or inside one namespace, but not in multiple namespaces.

It might be nice to be able to do this:

Code: Select all

namespace windows
 #include "window.bi"
end namespace

namespace ns
  '' import "windows" namespace into "ns"
  using windows

  '' code that uses windows ...
end namespace

'' import "windows" namespace in to the global one
using windows

'' more windows code ...


But to do that, #defines will have to respect namespaces. At the moment, I don't know how hard that would be to do, why it wasn't done before, impact on the C emitter, etc, etc. If anyone remembers anything about this (comments from v1ctor), it would be appreciated.
notthecheatr
Posts: 1759
Joined: May 23, 2007 21:52
Location: Cut Bank, MT
Contact:

Postby notthecheatr » Apr 30, 2008 21:40

Wow, this is way old.

I'm no developer, but I suspect the reason #defines don't respect NameSpaces is because #define occurs in the preprocessor, which knows nothing about NameSpaces. #define is little more than a "Search and Replace" function which runs before the program is actually compiled (it is a little more complicated than that, but not much). So I don't imagine it's feasible to have #defines respecting NameSpaces, although I could be wrong. I'm pretty sure that would be hard to do even if it is possible, and I doubt it would have a good effect on the C emitter because AFAIK #defines in C work just as they do in FreeBASIC.

One possibility from the other end would be to change the #defines to Consts, since Consts are handled at the compiler level (not the preprocessor) and thus respect namespaces. But naturally, there are lots of things #defines can do that Consts simply can't do (for example, a #define can be a piece of code, it isn't only restricted to being a constant numerical value) - so I don't know how well that would work, I guess it would depend on what #defines are used for in windows.bi.
coderJeff
Site Admin
Posts: 3018
Joined: Nov 04, 2005 14:23
Location: Ontario, Canada
Contact:

Postby coderJeff » Apr 30, 2008 22:24

notthecheatr wrote:Wow, this is way old.


True, but it was a bug on sf.net until I closed it today, as it's not really a bug.

#defines don't respect NameSpaces is because #define occurs in the preprocessor


Not quite true since #defines (and #macros) do respect SCOPE and scope blocks. Check out the example here: http://www.freebasic.net/wiki/wikka.php ... PgPpdefine

I guess what I need to figure out is if it was done this way on purpose, just a pain to add #define's to namespaces, is going to break loads of code if it is changed, or whatever.
notthecheatr
Posts: 1759
Joined: May 23, 2007 21:52
Location: Cut Bank, MT
Contact:

Postby notthecheatr » May 01, 2008 3:21

Hmm, well perhaps it's because Scopes simply restrict all outside access whereas NameSpaces allow access using With, Using, or just the name of the namespace and the . operator. NameSpaces are probably more complicated therefore, and maybe it's just me but something like

Code: Select all

NameSpace a
  #Define someVal "Hi"
End NameSpace

Print a.someVal


since I always considered #Define's to be nothing more than a glorified search and replace. On the other hand, it could definitely have its uses - if it isn't too hard to implement, which I suspect it is (or it would have been done by now).
counting_pine
Site Admin
Posts: 6170
Joined: Jul 05, 2005 17:32
Location: Manchester, Lancs

Postby counting_pine » May 01, 2008 4:09

Doing a quick forum search, the only piece of wisdom from v1ctor I found was: "Too bad it isn't possible to respect namespaces when declaring #define's."
http://www.freebasic.net/forum/viewtopi ... 9935#89935
coderJeff
Site Admin
Posts: 3018
Joined: Nov 04, 2005 14:23
Location: Ontario, Canada
Contact:

Postby coderJeff » May 01, 2008 14:08

Thanks, guys. notthecheatr, I hadn't thought of it in that context; that does make it complex, especially since #define/#macro also allow forward refs as in:

Code: Select all

'' G is forward ref
#define F G + 1
#define G 2
print F '' prints 3


So in a namespace gets kind of nasty, both to implement and for the programmer:

Code: Select all

namespace ns
  #define G() print F
  #define F "text"
end namespace
#define F "hello"
'' which "F" will be used?
ns.G()


I just thought of this other work-around for this situation which is probably better than putting the "windows.bi" inside the namespace:

Code: Select all

#include "windows.bi"

private sub pSomeWindowsFunc()
   '' stuff that needs windows.bi
end sub

'' Public interface
namespace ns
   sub SomeWindowsFunc()
      pSomeWindowsFunc()   
   end sub
end namespace
notthecheatr
Posts: 1759
Joined: May 23, 2007 21:52
Location: Cut Bank, MT
Contact:

Postby notthecheatr » May 01, 2008 14:33

Now what would be interesting is if you could create another keyword that works very similarly to #define but not quite the same. If you carefully define how it behaves (for example, not allowing forward references), you wouldn't necessarily have such problems. And if it's done in some middle stage between preprocessing and compiling, you could respect namespaces. It might be a useful thing, although I think it would still be difficult to implement.

Incidentally, though it isn't the same thing, flat assembler (fasm) has several different levels of preprocessing. It can be a pretty useful thing, as you can do some interesting tricks with nested macros and the like. But I imagine multi-level preprocessing could be a lot more complicated.

Return to “General”

Who is online

Users browsing this forum: Bing [Bot] and 4 guests