How to make a Callback -
Pghpunkid - 14.06.2011
I went through a bit of problems when making a multi-parameter callback, so i thought id share the things i went through. So lets get started.
This isn't a from the ground up plugin example, If that is what you are looking for, click
here.
So, in your plugin, you have your code, and now you want a callback to Pawn. (inb4 "Your doing it wrong.. etc etc etc")
Step 1: Setup
Now what i did to help organize these callbacks, is to make a separate function.
Plugin:
Код:
int AnEventForCallingBack(int number,char string[])
{
}
This will be our function within the plugin itself. With this callback, we want to send a string, and a number to our callback that we will call "OnSomethingHappens". The callback in pawn would look something like this:
Pawn:
pawn Код:
public OnSomethingHappens(number1,string1[])
{
}
The last step to setting this all up, is the function definition for the plugin (and for pawn if your not using an include.)
Plugin:
Код:
int AnEventForCallingBack(int number1, char string1[]);
This goes outside of any function, above all of the functions. I place mine below my includes, and variables.
Pawn:
pawn Код:
forward OnSomethingHappens(number1,string1[]);
These are crucial to work.
There. The easy part is done. Now to make the plugin send the data to the callback.
Step 2: Plugin Function
When sending multiple variables to a callback using the amx_Push functions, you may not get things right the first time.. like i did. So lets look at how to do the plugin's function.
First you need to send the data from wherever in your plugin, to the function. We are going to be utilizing a string and number, both just put in somewhere for tutorial purposes, and not really useful practically.
Код:
Somewhere in the plugin:
AnEventForCallingBack(5,"This is a string.");
So we call our plugin's function. Great! Now to send it to pawn.
Our Plugin function needs to push the integer and string to our callback "OnSomethingHappens" in Pawn. But before we can do that, we need to make sure we have something to send.
Код:
int AnEventForCallingBack(int number1,char string1[])
{
if (strlen(string1) == 0)
return 0;
if (number1 == NULL)
return 0;
return 1;
}
You should be checking each value, and if they are null or not. For example, checking if the length of your string is 0, by using strlen. if any of these variables are null or not given, then you should stop the function from sending bad data. Now if all checks are good, it returns 1, or a true boolean value (even though its an integer...)
Now for the amx stuff. Im not an expert at the amx address and all that, so as long as you use the right variable types in this next part, it should work just fine.
Код:
int AnEventForCallingBack(int number1,char string1[])
{
if (strlen(string1) == 0)
return 0;
if (number1 == NULL)
return 0;
int idx;
cell ret, amx_Address,*phys_addr;
int amxerr = amx_FindPublic(pAMX, "OnSomethingHappens", &idx);
if (amxerr == AMX_ERR_NONE)
{
return 1;
}
return 0;
}
Okay so now our variables actually contain data, getting to the rest of the plugin's function. This is where, if you are following along with your own example, you would replace "OnSomethingHappens" with your own callback name. Also note, we moved return 1; inside the completed if statement. What this does is return 0 if there is a AMX Error, and 1 if there is no error, and it completes.
To make the plugin finally call your data, you utilize the amx_Push functions. There are 3 types (I believe); amx_Push, amx_PushString, and amx_PushArray. We will be using amx_Push, and amx_PushString.
Код:
int AnEventForCallingBack(int number1,char string1[])
{
if (strlen(string1) == 0)
return 0;
if (number1 == NULL)
return 0;
int idx;
cell ret, amx_Address,*phys_addr;
int amxerr = amx_FindPublic(pAMX, "OnSomethingHappens", &idx);
if (amxerr == AMX_ERR_NONE)
{
amx_PushString(pAMX,&amx_Address,&phys_addr,string1,0,0);
amx_Push(pAMX, number1);
return 1;
}
return 0;
}
One thing to keep in mind if you are using multiple parameters, is to push them in
reverse order. This caused me several hours of needless debugging, and now im hoping to save you the same. So we call our string first, then the integer. Now, just to execute it.
Код:
int AnEventForCallingBack(int number1,char string1[])
{
if (strlen(string1) == 0)
return 0;
if (number1 == NULL)
return 0;
int idx;
cell ret, amx_Address,*phys_addr;
int amxerr = amx_FindPublic(pAMX, "OnSomethingHappens", &idx);
if (amxerr == AMX_ERR_NONE)
{
amx_PushString(pAMX,&amx_Address,&phys_addr,string1,0,0);
amx_Push(pAMX, number1);
amx_Exec(pAMX, &ret, idx);
return 1;
}
return 0;
}
If i am not mistaken, the variable
ret is your return, however, your not expecting a return value from the Pawn call back, so NULL is a valid replacement, and you can go without the
ret variable.
Step 3: Pawn, Compile and Test
Now go put a printf in your callback, compile it, and give it a shot. See what happens!
Hope this helps at least 1 person with their project!
Re: How to make a Callback -
Raimis_R - 14.06.2011
Nice,and thanks
Re: How to make a Callback -
Lorenc_ - 14.06.2011
This looks interesting, hopefully i can try this out.
Thanks a lot dude, your help is well appreciated!
Re: How to make a Callback -
kacper55331 - 14.06.2011
And how to make the argument Float?
Re: How to make a Callback -
Lorenc_ - 14.06.2011
Quote:
Originally Posted by kacper55331
And I make the argument Float?
|
function(Decimal hi)
I'm pretty sure.
Re: How to make a Callback -
Pghpunkid - 14.06.2011
Quote:
Originally Posted by Lorenc_
function(Decimal hi)
I'm pretty sure.
|
i think in C++ float still exists, but you use amx_Push. I would try that before anything. Ill tinker in a bit and revise the OP.
EDIT: Now that i think about it, i don't think that is possible with Pawn. Think about all the SAMP callbacks.. none of them return floats..
EDIT2: You might be able to pass it as a string, then use floatstr to change it to a float.
Re: How to make a Callback - 0x5A656578 - 14.06.2011
You can do floats with amx_ftoc
Код:
float some_float;
some_float = ...;
...
amx_Push(amx, amx_ftoc(some_float));
amx_Exec(...);
Re: How to make a Callback -
kacper55331 - 14.06.2011
I tried to do ProXdectory(GodFather) the plugin, but there is a need Float-type arguments.
Код:
// SendClienMessageEx(Float:radi, playerid, string[], col1, col2, col3, col4, col5, bool:echo=false)
int _SendClientMessageEx(float radi[], int playerid, char string[], int c1, int c2, int c3, int c4, int c5, int echo, AMX *amx)
{
int index;
if(amx_FindPublic(amx, "SendClientMessageEx", &index) == AMX_ERR_NONE)
{
cell retVal,
amx_addr,
amx_ret,
* amx_physAddr;
int numb;
amx_Push(amx, echo);
amx_Push(amx, c5);
amx_Push(amx, c4);
amx_Push(amx, c3);
amx_Push(amx, c2);
amx_Push(amx, c1);
amx_PushString(amx, &amx_addr, &amx_physAddr, string, 0, 0);
amx_Push(amx, playerid);
amx_PushArray(amx, &amx_addr, &amx_physAddr, radi, 0);
if(amx_Exec(amx, &retVal, &index) == AMX_ERR_NONE)
{
return true;
}
else
{
amx_Release(amx, amx_addr);
return false;
}
return true;
}
return false;
}
Re: How to make a Callback -
Pghpunkid - 14.06.2011
Quote:
Originally Posted by kacper55331
I tried to do ProXdectory(GodFather) the plugin, but there is a need Float-type arguments.
Код:
// SendClienMessageEx(Float:radi, playerid, string[], col1, col2, col3, col4, col5, bool:echo=false)
int _SendClientMessageEx(float radi[], int playerid, char string[], int c1, int c2, int c3, int c4, int c5, int echo, AMX *amx)
{
int index;
if(amx_FindPublic(amx, "SendClientMessageEx", &index) == AMX_ERR_NONE)
{
cell retVal,
amx_addr,
amx_ret,
* amx_physAddr;
int numb;
amx_Push(amx, echo);
amx_Push(amx, c5);
amx_Push(amx, c4);
amx_Push(amx, c3);
amx_Push(amx, c2);
amx_Push(amx, c1);
amx_PushString(amx, &amx_addr, &amx_physAddr, string, 0, 0);
amx_Push(amx, playerid);
amx_PushArray(amx, &amx_addr, &amx_physAddr, radi, 0);
if(amx_Exec(amx, &retVal, &index) == AMX_ERR_NONE)
{
return true;
}
else
{
amx_Release(amx, amx_addr);
return false;
}
return true;
}
return false;
}
|
Did you try this?
Quote:
Originally Posted by 0x5A656578
You can do floats with amx_ftoc
Код:
float some_float;
some_float = ...;
...
amx_Push(amx, amx_ftoc(some_float));
amx_Exec(...);
|
Perhaps give it a shot, and let us know?
Re: How to make a Callback -
RyDeR` - 30.06.2011
What about things like GetPlayerPos? Can you possibly give some examples?
Re: How to make a Callback -
Omega-300 - 30.06.2011
The 'GetPlayerPos' is not an callback but rather a usual function, the references are gained by Amx_GetAddr.
Though I suggest you to be familiar with C++ quite a bit and know how AMX works so you don't just do it with trial-and-error approach(which is not good at all) and actually understand why something is done!
Example:
Код:
cell *pFirstParam = NULL;
if(amx_GetAddr(amx, params[1], &pFirstParam) == AMX_ERR_NONE)
{
*pFirstParam = 123;
}
Re: How to make a Callback -
RyDeR` - 30.06.2011
I am quite familiar with C++ and either I do quite a bit know how AMX works, don't worry about that. The reason I asked this here is because I am also using a callback to call PAWN functions in C++.
http://forum.sa-mp.com/showpost.php?...1&postcount=17 (example here)
And yes I know, amx_FindNative is also a possibility.
Thanks for the example.
Re: How to make a Callback -
Kyosaur - 07.07.2011
Quote:
Originally Posted by RyDeR`
I am quite familiar with C++ and either I do quite a bit know how AMX works, don't worry about that. The reason I asked this here is because I am also using a callback to call PAWN functions in C++.
http://forum.sa-mp.com/showpost.php?...1&postcount=17 (example here)
And yes I know, amx_FindNative is also a possibility.
Thanks for the example.
|
Hey man you might want to check out
THIS.
Its a bit rushed, so sorry about that (i wanted to make a nice plugin tutorial that would cover some frequently asked questions, but this is as good as it gets for now :\).
Re: How to make a Callback -
Gamer_Z - 08.07.2011
Am I the only one with 'error: identifier 'pAMX' is undefined' while I included the SA:MP SDK etc..?
Re: How to make a Callback -
RyDeR` - 08.07.2011
Quote:
Originally Posted by gamer_Z
Am I the only one with 'error: identifier 'pAMX' is undefined' while I included the SA:MP SDK etc..?
|
pAMX is an AMX variable. You have to assign it on amx load (it's a pointer in which script the natives are).
PS: Thanks for sharing Kyosaur!
Re: How to make a Callback -
Gamer_Z - 08.07.2011
okay what I did was
in the global script and
in PLUGIN_CALL AmxLoad( AMX *amx ) , that will hopefully be good,
anyone interested in a drift counter plugin?
I just need help with this line:
pawn Код:
if(Invoke::callNative(&PAWN::GetPlayerState, playerid) == PLAYER_STATE_DRIVER){
Invoke::callNative(&PAWN::GetVehicleVelocity, PlayerVehicleID, &SpeedX, &SpeedY, &SpeedZ);
Invoke:: is underscored by a red line, what to do? ^^
Re: How to make a Callback -
MovieDrifting - 06.12.2012
bro perfection 10 out of 10