Can you please "point" me a good tutor about prototypes?
I am trying to learn from PB's chm help file and "PB Survival Guide" but the subject seems so hard. I need extra support...
Prototypes make me sick
Quickie Example 
Thalius

Code: Select all
; Define a testfunction
Procedure Popup(String.s)
MessageRequester("Hi",String.s)
EndProcedure
; We Create a Prototype for our Function which basically creates a Structure that we can assign
; to a variable (which remains local if not specified otherwise). This can be handy to have functions
; only local.
;
; With Pseudotypes we could pass for example our String always as ASCII
; to the function, even when compile din unicode mode. Useful for old
; codes or dlls which dont accept unicode strings.
; Pseudotype:
; PrototypeC.l _MyPopupPrototype(String.p-ascii)
;
PrototypeC.l _MyPopupPrototype(String.s)
; Define the new Prototype command ( basically a variable ) & assign our ptototype structure to it
; and give it the function adress from our custom function
; via:
; foo._myprototype = GetFunction(#Library,"name_of_function")
; you can also give it the adress of a library function to simply wrap a dll command.
MyNewPopup._MyPopupPrototype = @Popup()
;Call our new prototype function
MyNewPopup("Hello World!")
"In 3D there is never enough Time to do Things right,
but there's always enough Time to make them *look* right."
"psssst! i steal signatures... don't tell anyone!
"
but there's always enough Time to make them *look* right."
"psssst! i steal signatures... don't tell anyone!

I don't understand the concept of prototypes at all. In your example above,
what's the purpose of wrapping the MessageRequester command like that?
In which situations is it advantageous to use prototypes? Do they enable
functionality that standard commands don't?
what's the purpose of wrapping the MessageRequester command like that?
In which situations is it advantageous to use prototypes? Do they enable
functionality that standard commands don't?
Last edited by PB on Thu Nov 22, 2007 9:01 pm, edited 1 time in total.
1. Understand the CallFunctionFast() system.
2. Read it:
A prototype is a type that you give a variable. That variable can then be used as a pointer (to a procedure), but instead of using CallFunctionFast() on it, you can use it directly.
3. Try it:
So a prototyped variable is just a normal function pointer that you call without CallFunctionFast(). The prototype is the type of the variable, and it used for checking that you use the correct parameters.
2. Read it:
A prototype is a type that you give a variable. That variable can then be used as a pointer (to a procedure), but instead of using CallFunctionFast() on it, you can use it directly.
3. Try it:
Code: Select all
Procedure TestProc(A.s)
MessageRequester("", A)
EndProcedure
FunctionPointer = @TestProc() ; Or Use GetFunction() if the function is in a dll
CallFunctionFast(FunctionPointer, "Function pointer")
Prototype ProtoTestProc(A.s)
Proto.ProtoTestProc
Proto = FunctionPointer
CallFunctionFast(Proto, "Proto 1")
Proto("Simpler syntax")
Prototypes are also far more flexible than using CallFunctionFast() etc. because it can deal with different kinds of parameters and return types; floats, quads etc. Something which CallFunctionFast() cannot handle.
Prototypes are very very useful and very simple once you get the hang of them.
Prototypes are very very useful and very simple once you get the hang of them.
I may look like a mule, but I'm not a complete ass.
- netmaestro
- PureBasic Bullfrog
- Posts: 8451
- Joined: Wed Jul 06, 2005 5:42 am
- Location: Fort Nelson, BC, Canada
Look at it like this. Here is a structure which serves as a template for data to be organized in a certain way:
Now when you want to create a variable of this type, you might do:
var.stuff
and var is a pointer to a memory block set aside and organized according to the stuff structure. You know exactly what you're dealing with and where to find each member. It's a concept you're familiar with as an experienced PB programmer, so you understand it well by now.
A prototype is the same concept applied to procedures. You do something like:
Prototype.q action(number.l, float.f, byte.b)
and you've created a template for a procedure that takes in a long, a float and a byte and returns a quad.
Now you do:
MyProc.action = @SomeProc()
and you've created a more talented cousin of CallFunctionFast which is able to verify and correctly handle the input and return types of the procedure according to the features described in the prototype. It's just CallFunctionFast done in a more organized and professional way.
Code: Select all
Structure stuff
number.l
float.f
byte.b
EndStructure
var.stuff
and var is a pointer to a memory block set aside and organized according to the stuff structure. You know exactly what you're dealing with and where to find each member. It's a concept you're familiar with as an experienced PB programmer, so you understand it well by now.
A prototype is the same concept applied to procedures. You do something like:
Prototype.q action(number.l, float.f, byte.b)
and you've created a template for a procedure that takes in a long, a float and a byte and returns a quad.
Now you do:
MyProc.action = @SomeProc()
and you've created a more talented cousin of CallFunctionFast which is able to verify and correctly handle the input and return types of the procedure according to the features described in the prototype. It's just CallFunctionFast done in a more organized and professional way.
BERESHEIT
- Psychophanta
- Always Here
- Posts: 5153
- Joined: Wed Jun 11, 2003 9:33 pm
- Location: Anare
- Contact:
Nice explanation the Trond's one.
However the netmaestro's one is awesome, good "maestro"
Another short example using Import and Pseudotypes (short examples help to understand better, at least to me
)
However the netmaestro's one is awesome, good "maestro"

Another short example using Import and Pseudotypes (short examples help to understand better, at least to me

Code: Select all
Import "User32.lib"
MsgB(Window.l,Body.p-unicode,Title.p-unicode,Flags.l=0) As "_MessageBoxW@16"
EndImport
Prototype.l Myfunctiontype(a.l,b.p-unicode,c.p-unicode,d.l=0); <- i like to use a,b,c,d, ... for the parameters when defining a prototype, i think it helps to understand the concept better because we are defining just a template.
*MsgeBox.Myfunctiontype=@MsgB(); <- i like to use '*' because it is indeed a pointer.
*MsgeBox(0,"Hello","World")
-
- User
- Posts: 19
- Joined: Mon Oct 08, 2007 11:25 am
Thanks to this excellent forum
Perfect explanation.netmaestro wrote:A prototype is the same concept applied to procedures. You do something like:
Prototype.q action(number.l, float.f, byte.b)
and you've created a template for a procedure that takes in a long, a float and a byte and returns a quad.
Now you do:
MyProc.action = @SomeProc()
and you've created a more talented cousin of CallFunctionFast which is able to verify and correctly handle the input and return types of the procedure according to the features described in the prototype. It's just CallFunctionFast done in a more organized and professional way.
.