Thread overview
A question of function design?
Oct 27, 2016
WhatMeWorry
Oct 27, 2016
pineapple
Oct 28, 2016
WhatMeWorry
Oct 28, 2016
Mike Parker
Oct 28, 2016
WhatMeWorry
October 27, 2016
I'm using Derelict GLFW3 and I found the following GLFW3 code snippet in a demo.


float distance = 3.0;

extern(C) void key_callback(GLFWwindow* window, int key, int scancode, int action, int modifier) nothrow
{
    if (key == GLFW_KEY_ESCAPE && action == GLFW_PRESS)
    {
        glfwSetWindowShouldClose(window, GL_TRUE);
    }
    if (key == GLFW_KEY_TAB && action == GLFW_PRESS)
    {
        distance = distance + .25;
    }
}


I'm looking at the call back function and all but one of the parameters are pass by values and there is no return type.  So they use this distance variable (is this called a global variable?) which I thought was considered bad programing and the classical example of a side-effect.  Isn't this particularly dangerous as programs get larger and larger.

So given the way this function was designed, how is a programmer supposed to convey information to the outside world?  Do I just suck it up?

I looked at D code projects using this function on git hub, but stuff there was either either like this or too complex.


October 27, 2016
On Thursday, 27 October 2016 at 22:17:35 UTC, WhatMeWorry wrote:
>
> I'm using Derelict GLFW3 and I found the following GLFW3 code snippet in a demo.

In a small demo, crap like this usually isn't a big deal.

It's not common practice, though, and for good reason. You should definitely avoid imitating it.
October 28, 2016
On Thursday, 27 October 2016 at 22:51:13 UTC, pineapple wrote:
> On Thursday, 27 October 2016 at 22:17:35 UTC, WhatMeWorry wrote:
>>
>> I'm using Derelict GLFW3 and I found the following GLFW3 code snippet in a demo.
>
> In a small demo, crap like this usually isn't a big deal.
>
> It's not common practice, though, and for good reason. You should definitely avoid imitating it.

Anyone have a good example of what I should be doing?
October 28, 2016
On Friday, 28 October 2016 at 13:19:19 UTC, WhatMeWorry wrote:

>
> Anyone have a good example of what I should be doing?

I generally use GLFW event callbacks to populate an event queue with custom event types, then process the queue and handle events elsewhere. That way, the callbacks need no nothing at all about the game code.

```
void setCallbacks() {
    glfwSetKeyCallback(&key_callback);
}

private:
MyEventQueue _eventq;

extern(C) void key_callback(GLFWwindow* window, int key, int scancode, int action, int modifier) {
    eventq.push(KeyEvent(window, key, scancode, action, modifier);
}

An alternative approach is to forego the event queue and just have the callbacks process event listeners. The listeners could be delegates, function pointers, or interfaces, whatever works for your scenario, or some specific event handler class. They might be stored in flat arrays, or aas keyed on the window or a KeyEvent structure. Whatever works.

```
alias KeyHandler = bool delegate(GLFWwindow, int, int, int, int);
void registerKeyHandler(KeyHandler handler) { _keyHandlers ~= handler; }

private:
KeyHandler[] _keyHandlers;

extern(C) void key_callback(GLFWwindow* window, int key, int scancode, int action, int modifier) {
    foreach(handler; _keyHandlers) {
        if(_keyHandler(window, key, scancode, action, modifier)) break;
    }
}
```
October 28, 2016
On Friday, 28 October 2016 at 14:12:53 UTC, Mike Parker wrote:
> On Friday, 28 October 2016 at 13:19:19 UTC, WhatMeWorry wrote:
>
>> [...]
>
> I generally use GLFW event callbacks to populate an event queue with custom event types, then process the queue and handle events elsewhere. That way, the callbacks need no nothing at all about the game code.
>
> [...]

Thanks!  I'll study this code.  I guess APIs can only give you so much.