Amiga-Development

Please login or register.

Login with username, password and session length
Advanced search  

News:

Created for developers of all Amiga camps

Author Topic: Trying to open screen  (Read 3046 times)

0 Members and 1 Guest are viewing this topic.

adminZRt75

  • Administrator
  • Hero Member
  • *****
  • Posts: 591
    • View Profile
Trying to open screen
« on: December 26, 2012, 12:20:14 PM »

Started by Berneaud on utilitybase

Berneaud
Member

   Posted: 2007-Oct-5 19:10:12

When trying to compile a screen opening example I got on the net, I'm getting the following erros messages:

ram:screen.c:13: warning: assignment makes pointer from integer without a cast
ram:screen.c:15: error: 'Screen1' undeclared (first use in this function)
ram:screen.c:15: error: (Each undeclared identifier is reported only once
ram:screen.c:15: error: for each function it appears in.)


The example is this:

#include <proto/intuition.h>
#include <proto/dos.h>
#include <intuition/screens.h>

int main() {
struct Screen *myScreen;

myScreen = OpenScreenTagList(NULL,
SA_Left, 0, SA_Top, 0, SA_Width, 640, SA_Height, 480,
SA_Depth, 8, SA_Title, "My New Screen",
SA_Type, PUBLICSCREEN,
SA_SysFont, 1,
TAG_DONE);
Delay(500);
if (myScreen) CloseScreen(&Screen1);
}


Anyone can point me what's wrong? I was hoping was "clean", just type and go.
As you may have guessed, I'm not an experienced programmer... ;)



hans
Member

   Posted: 2007-Oct-5 19:42:47

Screen1 doesn't exist, replace "&Screen1" with "myScreen".
"OpenScreenTagList" should be "OpenScreenTags".

Hans



ZeroG
Member

   Posted: 2007-Oct-5 19:43:39 · Edited by: ZeroG

Ok, lets see:

1. you should include proto/exec.h

2. for varargsfunction calls you have to use (in this case) OpenScreenTags() not OpenScreenTagList().

3. you have nothing named "Screen1" in your code...

4. if you dont link with -lauto you have to open the Libraries (DOS and Intuition)

5. for OS4 you have to define __USE_INLINE__ or use the Interfacepointer, for example IDOS->Delay()      #define __USE_INLINE__

#include <proto/exec.h>
#include <proto/intuition.h>
#include <proto/dos.h>
#include <intuition/screens.h>

void main()
{
   struct Screen *myScreen;

   myScreen = OpenScreenTags(NULL,
   SA_Left, 0,
   SA_Top, 0,
   SA_Width, 640,
   SA_Height, 480,
   SA_Depth, 8,
   SA_Title, "My New Screen",
   SA_Type, PUBLICSCREEN,
   SA_SysFont, 1,
   TAG_DONE);

   Delay(500);

   if(myScreen)
   CloseScreen(myScreen);
}


compile with: gcc -o test test.c -lauto



Berneaud
Member

   Posted: 2007-Oct-5 20:00:48

@Hans & ZeroG

I've been looking up on the net and trying it up, that's why some code seems wrong (like the absence of "Screen1").
Also, some examples are apparently obsolete, using stuff not compatible with OS4. For example, in the original example, no mention was made of the "proto/exec.h" bit.

It compiled ok, now. Thanks! ;)

I've been having a hard time getting to grips with Amiga C. I have basic C knowledge, but it's the Amiga-specific bits that frustrate me...



ZeroG
Member

   Posted: 2007-Oct-5 20:13:52 · Edited by: ZeroG

@Berneaud

Try to get a copy of the Amiga ROM Kernel Reference Manual: Libraries 3rd Edition, it is a very good start.
You can find it for example on the AmigaOS Developer Cds.

It covers only upto OS 2 but most of thinks are useable and true for OS4.

Also have a look in SDK:Documentation/Developer Info/General/os4_migration_guide.pdf it covers most differences between OS4 and older AmigaOS versions.



Berneaud
Member

   Posted: 2007-Oct-5 20:41:22

I've read the migration guide, but there are still many issues that seems out of my reach.

Not wanting to make you my personal C trainer, but I can't see why this fails:

(NOTE: this was me trying to "merge" a successful window example with another to enable the close gadget)

#define __USE_INLINE__

#include <proto/intuition.h>
#include <proto/gadtools.h>
#include <proto/exec.h>
#include <proto/dos.h>
#include <intuition/intuition.h>

int main() {
struct Window *myWindow;
int closewin = FALSE; /* Flag used to end program */
struct IntuiMessage *msg; /* Structure to store Intuition message data */
ULONG msgClass; /* Class value */

myWindow = OpenWindowTags(NULL,
WA_Left, 20, WA_Top, 20,
WA_Width, 200, WA_Height, 150,
WA_IDCMP, IDCMP_CLOSEWINDOW,
WA_Flags, WFLG_SIZEGADGET | WFLG_DRAGBAR | WFLG_DEPTHGADGET | WFLG_CLOSEGADGET | WFLG_ACTIVATE,
WA_Title, "My Window",
WA_PubScreenName, "Workbench",
TAG_DONE);
while (closewin == FALSE) {
Wait(1L << myWindow->UserPort->mp_SigBit);
msg = GT_GetIMsg(myWindow->UserPort);
msgClass = msg->Class;
GT_ReplyIMsg(msg);
if (msgClass == IDCMP_CLOSEWINDOW) {
CloseWindow(myWindow);
closewin = TRUE;
}
}
return(0);
}


It complains about "undefined references to IINtuition.



hans
Member

   Posted: 2007-Oct-5 21:08:13

Quoting ZeroG:      compile with: gcc -o test test.c -lauto


The auto lib should initialise IntuitionBase and IIntuition.

While you're learning OS4 coding, it would be helpful for others to turn your test code into examples/tutorials for others. You're one of the best people to find what beginners need, as you're learning the Amiga API from the ground up.

Hans



salass00
Member

   Posted: 2007-Oct-5 21:16:03
      4. if you dont link with -lauto you have to open the Libraries (DOS and Intuition)



dos.library is opened by the standard startup code so you don't need to open it unless for some reason you're not linking with startup code (f.e. if you're writing a library, device or a handler/filesystem).



ZeroG
Member

   Posted: 2007-Oct-5 21:32:28

@Berneaud

You should check if the Window is really open before calling Wait().
      It complains about "undefined references to IINtuition.


see hans post above.

Can you please use the .c-button to enable syntax highlighting, sourcecode is difficult to read without it.

@salass00
Of course it does, but it is a good exercise for beginners to open/close every used library manually.



hans
Member

   Posted: 2007-Oct-5 22:31:51
      Of course it does, but it is a good exercise for beginners to open/close every used library manually.


And if opening a library fails, it's good practise to pop up a requester with a localized error message. IIRC, the auto library opening code typically just quits without warning. That's my number one complaint of Linux programs, they quit without telling you why.

Of course, I still have to add this to some of my own code too (but none of it's released yet anyway).

Hans



salass00
Member

   Posted: 2007-Oct-6 07:16:25 · Edited by: salass00

@ZeroG

And how exactly would you go about doing that without getting a complaint from the linker that there are two definitions of DOSBase and IDOS (one in the startup code and one in your own code)?



ZeroG
Member

   Posted: 2007-Oct-6 09:08:48

@salass00

Just tried it to be sure.
I dont get problems with the linker...      /* gcc -Wall -o test test.c */
#include <proto/exec.h>
#include <proto/dos.h>

struct Library *DOSBase = 0;
struct DOSIFace *IDOS = 0;

void main()
{
   if(!(DOSBase = IExec->OpenLibrary("dos.library", 52)))
   goto error;
   if(!(IDOS = (struct DOSIFace *)IExec->GetInterface(DOSBase, "main", 1, NULL)))
   goto error;
   IDOS->Delay(300);
   error:
   IExec->DropInterface((struct Interface *)IDOS);
   IExec->CloseLibrary(DOSBase);
}



rachy
Flower Power! @-->--

   Posted: 2007-Oct-6 09:23:56

@salass00

You won't get complaints from the linker if you explicitly defined any base or interface structure pointers, which are present in the libauto.a, because those pointers are defined as weak binded variables, thus you can override them. But why would you override any of them?



Berneaud
Member

   Posted: 2007-Oct-6 10:57:33

@ZeroG

Sorry about the absence of the syntax highlighting. I never knew it existed here on UtilBase! ;)

About the problem, I used -lauto, as you told me in the original post. Still, I get the compiler IIntuition complaints.
Did you compile my code fine? If so, something could be wrong with my SDK...



Berneaud
Member

   Posted: 2007-Oct-6 11:01:02

Just tried to compile the code and now, I get only the "undefined reference to IGadTools" error. The IIntuition one is gone!
What's happening here?!?!?
I didn't change the code...



Berneaud
Member

   Posted: 2007-Oct-6 11:17:48

By using "pedantic errors", I got this(which means little to me...):


In file included from SDK:include/include_h/devices/inputevent.h:13,
        from SDK:include/include_h/intuition/intuition.h:45,
        from SDK:include/include_h/intuition/intuitionbase.h:21,
        from SDK:include/include_h/proto/intuition.h:14,
        from ram:Windowgadget.c:5:
SDK:include/include_h/devices/timer.h:49: error: comma at end of enumerator list
In file included from SDK:include/include_h/exec/exec.h:43,
        from SDK:include/include_h/interfaces/intuition.h:13,
        from SDK:include/include_h/proto/intuition.h:45,
        from ram:Windowgadget.c:5:
SDK:include/include_h/exec/memory.h:223: error: comma at end of enumerator list
In file included from SDK:include/include_h/exec/exec.h:79,
        from SDK:include/include_h/interfaces/intuition.h:13,
        from SDK:include/include_h/proto/intuition.h:45,
        from ram:Windowgadget.c:5:
SDK:include/include_h/exec/execbase.h:274: error: comma at end of enumerator list
In file included from SDK:include/include_h/utility/utility.h:21,
        from SDK:include/include_h/proto/exec.h:14,
        from ram:Windowgadget.c:7:
SDK:include/include_h/utility/data_structures.h:72: error: comma at end of enumerator list
[csource][/csource]



rachy
Flower Power! @-->--

   Posted: 2007-Oct-6 11:54:58 · Edited by: rachy

@Berneaud

No need for turning pedantic mode on, practically useless. -Wall and -Werror do the trick, which means: all warnings are on, and all warnings cause error (stops compiling). IMO: every warning means something and have to be checked.



ZeroG
Member

   Posted: 2007-Oct-6 15:04:39

@Berneaud
      Just tried to compile the code and now, I get only the "undefined reference to IGadTools" error. The IIntuition one is gone!
What's happening here?!?!?
I didn't change the code...


Seems like libauto.a does not have autoinitcode for gadtools.library.
Open it manually. A example with dos.library is above.



Berneaud
Member

   Posted: 2007-Oct-6 15:47:34

@ZeroG

I tried to merge the "dos" example with my own code (putting "gadtools" where "dos" was), but got errors saying "struct ExecIFace has no member named IExec" and "struct DOSIFace has no member named IDOS".

And this is just for a (supposedly) simple window program.
At this point, I must say I'm a bit lost at how Amiga C works... :(((
I'm not sure I'll be able to ever understand all this. I learn BASIC fast and well, but then I was young and had plenty of time for reading and researching.

Here's my code now:      
/* unsuccessful window close gadget example */

#define __USE_INLINE__

#include <proto/intuition.h>
#include <proto/gadtools.h>
#include <proto/exec.h>
#include <proto/dos.h>
#include <intuition/intuition.h>

int main() {
   struct Window *myWindow;
   int closewin = FALSE;
   struct IntuiMessage *msg;
   ULONG msgClass;

   if(!(DOSBase = IExec->OpenLibrary("gadtools.library", 1)))
   goto error;
   if(!(IDOS = (struct DOSIFace *)IExec->GetInterface(DOSBase, "main", 1, NULL)))
   goto error;
   IDOS->Delay(300);
   error:
   IExec->DropInterface((struct Interface *)IDOS);
   IExec->CloseLibrary(DOSBase);

   struct NewWindow winlayout = {
       20, 20,
       200, 150,
       0,1,
       IDCMP_CLOSEWINDOW,
       WFLG_SIZEGADGET | WFLG_DRAGBAR | WFLG_DEPTHGADGET | WFLG_CLOSEGADGET | WFLG_ACTIVATE,
       NULL, NULL,
       "My Window",
       NULL,NULL,
       0,0,
       600,400,
       WBENCHSCREEN
   };
   myWindow = OpenWindow(&winlayout);
   while (closewin == FALSE) {/* Run program until window is closed */
       Wait(1L << myWindow->UserPort->mp_SigBit); /* Wait for an event! */
       msg = GT_GetIMsg(myWindow->UserPort); /* Get message data */
       msgClass = msg->Class; /* What has been clicked? */
       GT_ReplyIMsg(msg); /* Close message */
       if (msgClass == IDCMP_CLOSEWINDOW) {/* Check here if Close Window selected */
           CloseWindow(myWindow); /* Close window */
           closewin = TRUE;}
   }
   return (0);
}




hans
Member

   Posted: 2007-Oct-6 16:48:15

@Bernaud

You're opening the gadtools library so don't set DOSBase and IDOS to the library base and interface of gadtools. This will cause your program to crash because you'll try to use the gadtools library like the DOS library.

create the following 2 global variables:      struct Library *GadToolsBase = NULL;
struct GadToolsIFace *IGadTools = NULL;


I don't know if a capital T or lowercase t should work.
Changeif(!(IDOS = (struct DOSIFace *)IExec->GetInterface(DOSBase, "main", 1, NULL)))


toif(!(IGadTools = (struct GadToolsIFace *)IExec->GetInterface(GadToolsBase, "main", 1, NULL)))



Also, there's another problem, you're opening the gadtools, then waiting 300 seconds, and then closing it, BEFORE you actually use it. Closing should be done at the end of the program. Delete the Delay(300) call and move error: and the library closing code to the end of your program.

Hans



ZeroG
Member

   Posted: 2007-Oct-6 17:38:42 · Edited by: ZeroG

Remove the Interfacepointer infront of the OS-calls.

If you make use of __USE_INLINE__ the preprocessor will add the Interfacepointer for you - even if you already have set them (the compiler then ends up with something like IExec->IExec->example()).

EDIT:      I don't know if a capital T or lowercase t should work.


capital T



Berneaud
Member

   Posted: 2007-Oct-6 17:41:57 · Edited by: Berneaud

@Hans
ok. I made the changes, but still get "struct ExecIFace has no member named IExec".
The error line is this one:      GadtoolsBase = IExec->OpenLibrary("gadtools.library", Null);



What exactly is wrong here? Where can I find the members of struct ExecIFace?
I removed error-checking for now,until I know what I'm doing here, which may take a while... ;)


@ZeroG

Disregard the "IExec member" error. I was foolishly saving my code in the wrong place.

I get these now:

ram:Gadgetv3.c:21: warning: passing argument 3 of 'IExec->OpenLibrary' makes integer from pointer without a cast
ram:Gadgetv3.c:39: error: dereferencing pointer to incomplete type
ram:Gadgetv3.c:41: error: dereferencing pointer to incomplete type

The offending line is this one:
GadToolsBase = OpenLibrary ("gadtools.library", NULL);



Hypex
Member

   Posted: 2007-Oct-7 17:01:31

@Berneaud

If I may just step in here, as the other guys are doing a great job. :-)
      What exactly is wrong here? Where can I find the members of struct ExecIFace?
I removed error-checking for now,until I know what I'm doing here, which may take a while... ;)



It's that IExec, with __USE_INLINE__ defined remove it, as ZeroG was saying.
I get these now:

ram:Gadgetv3.c:21: warning: passing argument 3 of 'IExec->OpenLibrary' makes integer from pointer without a cast
ram:Gadgetv3.c:39: error: dereferencing pointer to incomplete type
ram:Gadgetv3.c:41: error: dereferencing pointer to incomplete type

The offending line is this one:
GadToolsBase = OpenLibrary ("gadtools.library", NULL);



I don't know about 39 and 41 as I can't see the lines, but on line 21 you are passing NULL as the library version. NULL is defined as a null pointer, so just replace it with a zero. Or LIBRARY_MINIMUM is a better idea. And putting in the version you actually need based on what API functions you need is the best idea.

For example:GadToolsBase = OpenLibrary ("gadtools.library", 39);



hans
Member

   Posted: 2007-Oct-7 18:24:17

Just to follow up on Hypex's comments, a confusing thing with C and macros is that the error messages that you get are for the code, after the preprocessor has expanded the macros. When you use __USE_INLINE__, the compiler prepends the  interface to all library calls, e.g., OpenLibrary() becomes IExec->OpenLibrary(). This is great if you're updating old code, or writing code for multiple Amiga platforms. So if you write IExec->OpenLibrary(), this will become IExec->IExec->OpenLibrary(). One of my software engineering lecturers recommended not using macros for this very reason.

One other thing you should note, which is a quirk of OS4 library interfaces: the underlying library function calls have a self pointer to the interface (just look in the header files in the "include_h/interfaces" directory) as parameter 1. The compiler inserts that for you automatically. So, when it says parameter 3, it's actually parameter 2 in your code that it's talking about.

Hans



Hypex
Member

   Posted: 2007-Oct-7 18:36:15 · Edited by: Hypex

@hans
      One other thing you should note, which is a quirk of OS4 library interfaces: the underlying library function calls have a self pointer to the interface (just look in the header files in the "include_h/interfaces" directory) as parameter 1. The compiler inserts that for you automatically. So, when it says parameter 3, it's actually parameter 2 in your code that it's talking about.



Yes, I had forgot to mention this! I was thinking of it when typing. This can be confusing, it got me a few times, before I knew what was going on. I think I had to examine all the interface files to understand what it was talking about.

And stop me from checking the wrong argument to the right of the error!



Berneaud
Member

   Posted: 2007-Oct-8 23:32:44 · Edited by: Berneaud

I removed the IExec occurrences, but still won't compile.

Now it's "conflicting types for IGadTools" and "Previous declaration was on proto/gadtools".
If I comment out the "struct GadtoolsIFace *IGadTools = NULL;" bit (which was supposedly duplicated, I revert to "undefined reference to IGadTools".
Shouldn't the "conflict" be gone now? I may be missing/overlooking some concept here... ;)

I also get a dereferencing pointer to incomplete type.

Here's the code:      /* unsuccessful window close gadget example */

#define __USE_INLINE__

#include <stdio.h>
#include <proto/intuition.h>
#include <proto/gadtools.h>
#include <proto/exec.h>
#include <proto/dos.h>
#include <intuition/intuition.h>

struct Library *GadToolsBase = NULL;
struct GadtoolsIFace *IGadTools = NULL;

int main() {
   struct Window *myWindow;
   int closewin = FALSE;
   struct IntuiMessage *msg;
   ULONG msgClass;

   GadToolsBase = OpenLibrary ("gadtools.library", 0);

   struct NewWindow winlayout = {
       20, 20,
       200, 150,
       0,1,
       IDCMP_CLOSEWINDOW,
       WFLG_SIZEGADGET | WFLG_DRAGBAR | WFLG_DEPTHGADGET | WFLG_CLOSEGADGET | WFLG_ACTIVATE,
       NULL, NULL,
       "My Window",
       NULL,NULL,
       0,0,
       600,400,
       WBENCHSCREEN
   };
   myWindow = OpenWindow(&winlayout);
   while (closewin == FALSE) {/* Run program until window is closed */
       Wait(1L << myWindow->UserPort->mp_SigBit); /* Wait for an event! */
       msg = GT_GetIMsg(myWindow->UserPort); /* Get message data */
       msgClass = msg->Class; /* What has been clicked? */
       GT_ReplyIMsg(msg); /* Close message */
       if (msgClass == IDCMP_CLOSEWINDOW) {/* Check here if Close Window selected */
           CloseWindow(myWindow); /* Close window */
           closewin = TRUE;}
   }
   return (0);
}




hans
Member

   Posted: 2007-Oct-9 04:05:32

C is case sensitive. The error message is telling you that the type specified in "proto/gadtools.h" which is defined as "extern struct GadToolsIFace *IGadTools;", is not the same as "struct GadtoolsIFace *IGadTools;". Note the capital T in GadToolsIFace. That's my mistake for using lower-case t everywhere. Basically, the "proto/gadtools.h" file declares that a variable called IGadTools of type struct GadToolsIFace exists somewhere (externally to the file), but doesn't actually allocate memory for the variable. That's what you do in your C file.

The "dereferencing to incomplete type" error occurs because struct GadtoolsIFace (note the lower-case t) was never declared (because it should have been GadToolsIFace), so the compiler doesn't know what it is. Fix that "T", and both errors should disappear.

Hans



Berneaud
Member

   Posted: 2007-Oct-9 22:07:35

@Hans

I had changed that to capitals, but, after all the "versions" I had stored, must have fetched the wrong one.
It compiled, but...
...that's not the end of the story.
After running the program and trying to close the window, the Grim Reaper showed up! Something is still not as it should be.



hans
Member

   Posted: 2007-Oct-9 22:55:09

Just looking at the last source file you posted, it's missing:      if(!(IGadTools = (struct GadToolsIFace *)IExec->GetInterface(GadToolsBase, "main", 1, NULL)))



Also, you're not closing the gadtools library at the end. You need to close all interfaces & libraries that you open.

Try compiling with the -ggdb option. When it crashes, get the grimreaper to save a crashlog, and lookup the source line at which it crashed using addr2line -e test [address given by grimreaper]. You could also post your newest version for us to look at.

One final comment, the program needs more error checking. You should check if GadTools is opened correctly by checking that GadToolsBase isn't NULL. The same goes for the OpenWindow call; check that it isn't NULL, and exit gracefully (with an error message preferably) if it is NULL.

Hans



Hypex
Member

   Posted: 2007-Oct-10 06:24:41 · Edited by: Hypex

Going on from Hans, yes I do agree, after looking at it it does run too freely. For a simple test program the following structure would suffice:
      if (this_opened)
{
   if (that_opened)
   {
       if (what_opens)
       {
           do_stuff();

           close_what();
       }

       close_that();
   }

   close_this();
}



Otherwise, I follow the AmigaE with it's exception handling by copying it like this:
{
   if (!this_opened) Error("this didn't open");

   if (!that_opened) Error("that didn't open");

   if (!what_opens) Error("what didn't open");

   do_stuff();

   close_all();
}

void Error(s)
{
   printf(s);
   close_all();
}

void close_all()
{
   if (what) close_what();

   if (that) close_that();

   if (this) close_this();
}



I think you get the picture. You gotta make sure you clear all your variables first that store system resources. And a rule I always follow, make sure you always free resources in the exact reverse order they were allocated. As a simple example, if you opened intution, a screen and a window you can't close the screen before you close the window! And you can't close intution if you still have a screen and window hanging about!



Berneaud
Member

   Posted: 2007-Oct-10 22:15:40

@Hans & Hypex

Thanks for your sugestions. I will follow them.
As you "may" have noticed, I'm at a pretty basic level. I could say that the above code is my biggest C project ever. ;)

I removed some error checking from the original example (from the net), to help find out what was wrong. I still have some trouble with concepts like "interfaces" and "resources". From where I came from (AMOS Pro!), there was none of that.
I'll keep reading the books I have about C. Unfortunately, there are no Amiga books available, that would be a godsend.

Again, thanks for your help. I've learned a few concepts, maybe I'll get there eventually. ;)



ZeroG
Member

   Posted: 2007-Oct-10 22:28:11

@Berneaud      Unfortunately, there are no Amiga books available, that would be a godsend.


Not in paperform, but the Amiga ROM Kernel Reference Manuals and a LOT more docs and examples are on the Amiga Developer CDs.

For example you can get one from here.

I think that CD is a must have for any Amigacoder.



Hypex
Member

   Posted: 2007-Oct-11 09:19:39 · Edited by: Hypex

@ZeroG
      I think that CD is a must have for any Amigacoder.



Absolutely. It changed my life! Before then I was scrounging around on OS 1.3 Abacus books, looking up functions on the amiga.com site when they were there and examining include files like in AmigaE.

I also discovered what those strange guru codes in program hex dumps were--tag lists! :-) He he.

P.S.
Amiga must have decided that the AutoDocs were closed source as well! Because once you were able to look up those functions, then after another buy out thay were taken away. Tolk about encouraging the Amiga community. Sheesh!
Logged