Passing ALLEGRO_* by reference
Geek on Skates

Hey there, new guy here. I've written a function that does all the initializing (al_init, al_create_display, etc.) so I can keep all that stuff out of main(); it's also important because I'd like to pass them to other functions later. I would like to pass by reference, but some of the structures like ALLEGRO_DISPLAY, ALLEGRO_EVENT_QUEUE etc. seem to have something "incomplete" about them (if you don't make it a pointer, Visual Studio screams "incomplete type is not allowed"). Now I've been working in C for awhile, and I've used structs before (and created plenty myself), and I've never seen this error. I don't know what makes Allegro's "incomplete", but apparently it is because {reasons}. In other words, I'm trying to do:

ALLEGRO_DISPLAY * screen = NULL;
ALLEGRO_EVENT_QUEUE * event_q = NULL;
ALLEGRO_EVENT_SOURCE * keyboard = NULL;
int setup = load_allegro(screen, event_q, keyboard);
// this "load_allegro" returns a value indicating whether
// it worked and what failed if it didn't.

The function works as expected, I get a display for a second, and it returns 0 (no error), but then the variables go out of scope, so all those pointers are NULL again, so I can't do anything with them.

So normally, if I want output variables, I would pass by reference (using "&"), but trying that here results in the same error. I'm sure there's some super-simple solution I just haven't seen before... or is there? Maybe it's a Visual Studio issue? I suppose I could just make them global and have a header with all my global variables, but I'd rather not do that if I can help it. I've been all over Google and I'm all out of theories, so I figured I'd ask the experts. Any info on the subject would be awesome. Thanks! :)

Doctor Cop

Geek on Skates said

So normally, if I want output variables, I would pass by reference (using "&"), but trying that here results in the same error. I'm sure there's some super-simple solution I just haven't seen before... or is there?

passing & of screen seems wrong since screen is a reference.

if you are doing something like

    // In main
    int setup = load_allegro(screen, event_q, keyboard);

    // Outside main
    load_allegro(ALLEGRO_DISPLAY &screen, ALLEGRO_EVENT_QUEUE &event_q, ALLEGRO_EVENT_SOURCE &keyboard){
            // Your code
         }

Then it should not be a problem. Try updating your IDE.
I don't guarantee that it will work.

What you are trying to do is a bad practice, that's how cool kids create bottlenecks for their programs. They try to push the uncool code into a separate function and try to make C code look like python code, don't be like them.

and upload source code from next time, its really hard to guess what you're doing actually wrong.

Geek on Skates

Thanks for the advice, and I apologize for not pasting more code in. I didn't think there was anything particularly wrong about separating stuff out into different functions; I was thinking more along the lines of keeping the code organized. But of course it's always better to follow best practices. So a 1000-line main() it is. (;D)

Seriously though, while I was waiting for this I actually put all my load_allegro and unload_allegro code into main, and while it's a bit more "speaghetti-like" but it definitely works, and in my main event loop I can still use other functions without having to do that anyway. So thanks again & have a great weekend. :)

PS: Speaking of posting code, how did you make your code indented and use syntax highlighting? I don't see any button for it. Or is this one of those where you can just do [CODE]//my code[/CODE}?

Doctor Cop

Its like HTML code <code>
and <quote>

don't forget to close the tags with </tagname>

Edgar Reynaldo

You don't need to pass by reference, since they're already pointers. You would only need a reference if you wanted to change the variable itself. And passing a reference to an allegro struct is usually wrong.

For a quick example, say you wanted to write a function that initializes all your allegro variables :

#SelectExpand
1bool SetupAllegro(ALLEGRO_DISPLAY** pdisplay , ALLEGRO_EVENT_QUEUE** pqueue , ALLEGRO_TIMER** ptimer) { 2 if (!pdisplay || !pqueue || !ptimer) {return false;} 3 4 ALLEGRO_DISPLAY* d = al_create_display(800,600); 5 ALLEGRO_EVENT_QUEUE* q = al_create_event_queue(); 6 ALLEGRO_TIMER* t = al_create_timer(1.0/60.0); 7 8 if (q) { 9 al_register_event_source(q , al_get_timer_event_source(t)); 10 al_register_event_source(q , al_get_display_event_source(d)); 11 } 12 13 if (!d) { 14 printf("Failed to create display.\n"); 15 } 16 if (!q) { 17 printf("Failed to create event queue.\n"); 18 } 19 if (!t) { 20 printf("Failed to create timer.\n"); 21 } 22 23 *pdisplay = d; 24 *pqueue = q; 25 *ptimer = t; 26 return d && q && t; 27}

ALLEGRO_DISPLAY* d = 0;
ALLEGRO_EVENT_QUEUE* q = 0;
ALLEGRO_TIMER* t = 0;

if (!SetupAllegro(&d , &q , &t)) {
   printf("Setup failed.\n");
}

Now you can pass a reference to a pointer, but you cannot pass a reference to most allegro structs, because they are opaque data structure.

What you are trying to do is a bad practice, that's how cool kids create bottlenecks for their programs. They try to push the uncool code into a separate function and try to make C code look like python code, don't be like them.

Using functions to organize and separate data is not only NOT a bad practice, it is ESSENTIAL to writing good code. It has nothing to do with Python. Python can be just as unorganized and messy as C can.

Thread #617656. Printed from Allegro.cc