Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

pawn_register_callback, handler_return and callback parameters #19

Closed
George480 opened this issue Aug 18, 2019 · 2 comments
Closed

pawn_register_callback, handler_return and callback parameters #19

George480 opened this issue Aug 18, 2019 · 2 comments

Comments

@George480
Copy link

George480 commented Aug 18, 2019

A normal handler:

pawn_register_callback("OnPlayerConnect", "AntiFlood_OPC");

calls AntiFlood_OPC with correct playerid. A special handler with handler_return calls AntiFlood_OPC with correct return value but wrong playerid.

From wiki:
flags specify how the function should be handled. handler_return will place an additional by-ref parameter before the callback parameters to specify what should be returned from the callback.

pawn_register_callback("OnPlayerConnect", "AntiFlood_OPC", handler_return, "d", 0);
forward public AntiFlood_OPC(break_hook_chain, playerid);
public AntiFlood_OPC(break_hook_chain, playerid)
{
    ...

    if (condition)
    {
        break_hook_chain = 1; // do not call other handlers for OnPlayerConnect
    }
    return break_hook_chain;
}

playerid has value of 3964 when debugging it. If I change value 0 from pawn_register_callback to something random, it is printed correctly so the issue is only with the callback parameters.

@IS4Code
Copy link
Owner

IS4Code commented Aug 18, 2019

Hello, the function seems to be working as intended:

pawn_register_callback("OnPlayerConnect", "AntiFlood_OPC", handler_return, "d", 0);

This creates a closure from AntiFlood_OPC, storing the value of 0 inside. When your function is called, the first argument is the value 0 that you stored inside the callback, the second argument is the address of the variable where the return value will be provided, and the rest are the original arguments to the callback. Thus with pawn_register_callback("OnPlayerConnect", "AntiFlood_OPC", handler_return, "d", 0);, the function should be this:

public AntiFlood_OPC(always_zero, &break_hook_chain, playerid)
{
    ...
}

I should point out three things.

First, "d", 0 is pointless to have when registering the callback (unless it is not 0 and some dynamic value instead). The stored value is provided by-value to the public function and you will not be able to change it inside the function.

Second, returning a non-zero value is sufficient to break the chain, even without handler_return. handler_return is only useful if you want to inspect the value returned from the previous handler, or if you want to return 0 from the function and stop the chain at the same time.

Third, the parameter introduced by handler_return is by-ref, so it should be defined with the ampersand as &break_hook_chain. Since the way you defined AntiFlood_OPC is different from the way you told PawnPlus to call it, playerid contains the address of the variable where you are supposed to store the result from the function (if any).

@George480
Copy link
Author

Oh, I thought I had to pass a value for the return handler. I also used & but because it was passing the value 0, it was printing wrong values so I removed it.

I tried now your way and without handler_return and both work. Thank you.

This was referenced Aug 12, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants