Prototypes used to speed up calling Procedures

Just starting out? Need help? Post your questions and find answers here.
hgcoon
New User
New User
Posts: 9
Joined: Wed Feb 19, 2014 11:09 pm

Prototypes used to speed up calling Procedures

Post by hgcoon »

A Nubie Question: I know how to call procedures using pointers but I have been advised that for maximum speed I should use prototypes. I don't know how to do that. Can someone point me to info on prototypes/pseudotypes in this way? Perhaps a simple program fragment that does this would be a good away to start? My reading of the PB docs that I have read has left me clueless (i am a refugee from Power Basic which doesn't have prototypes.
Thank you for any suggestions. HGC
srod
PureBasic Expert
PureBasic Expert
Posts: 10589
Joined: Wed Oct 29, 2003 4:35 pm
Location: Beyond the pale...

Re: Prototypes used to speed up calling Procedures

Post by srod »

Here's a quick example.

Code: Select all

Procedure.i Function1(intParam)
  Debug "Hello from 'Function1' - intParam = " + intParam
  ProcedureReturn 1
EndProcedure

Procedure.i Function2(intParam)
  Debug "Hello from 'Function2' - intParam = " + intParam
  ProcedureReturn  2
EndProcedure

;Declare a prototype which is a template for a new kind of variable (just like .l, .i, .s etc.)
;The following line simply says : 'We are interested in calling some functions which take a single integer parameter and returns an integer'.
  Prototype.i simpleProtoType(param)
  
;We can now declare a variable whose type matches our prototype. Just like defining any regular variable.
  ptr.simpleProtoType

;Our variable 'ptr' has been declared as a pointer to a function whose prototype happens to match both functions above.
;However, this  variable is currently null. Let us point it at Function1().
  ptr = @Function1() ;In words : 'Assign the variable ptr the address of Function1'.
  
;We can now call Function1 through the 'ptr' variable.
;We see that the prototype definition requires that we pass a single integer parameter.
  returnValue = ptr(10)
  Debug "Our function call returned the value : " + returnValue
  Debug "===="

;Let us now call Function2 through the 'ptr' variable.
;We just need to alter ptr so that it points at Function2.
  ptr = @Function2()
  returnValue = ptr(20)
  Debug "Our function call returned the value : " + returnValue
  Debug "===="
Hope it helps.
Last edited by srod on Thu Feb 20, 2014 4:59 pm, edited 1 time in total.
I may look like a mule, but I'm not a complete ass.
User avatar
skywalk
Addict
Addict
Posts: 4223
Joined: Wed Dec 23, 2009 10:14 pm
Location: Boston, MA

Re: Prototypes used to speed up calling Procedures

Post by skywalk »

Code: Select all

; Callback example using prototype.
Prototype.i Fn1_CB(cb_trigger.i)

Procedure Fn1_CB(cb_trigger.i)
  Debug cb_trigger
EndProcedure

Procedure Fn1(nPts.i, delay_ms.i, CB.Fn1_CB=0)
  Protected.i i
  For i = 1 To nPts
    If CB <> 0  ; callback exists
      CB(i)
    EndIf
    Delay(delay_ms)
  Next i
EndProcedure

Fn1(32, 100, @Fn1_CB())
Fn1(32, 100);, @Fn1_CB())
The nice thing about standards is there are so many to choose from. ~ Andrew Tanenbaum
User avatar
netmaestro
PureBasic Bullfrog
PureBasic Bullfrog
Posts: 8451
Joined: Wed Jul 06, 2005 5:42 am
Location: Fort Nelson, BC, Canada

Re: Prototypes used to speed up calling Procedures

Post by netmaestro »

Here's a practical example of prototypes and pseudotypes in action. In the first snippet, we have to use the StringToBstr() procedure we created in order to pass a unicode filename to the GdipLoadImageFromFile function (if we don't have our compiler options set to unicode executable). In the days before Purebasic got pseudotypes this was always necessary:

Code: Select all

Procedure StringToBStr (string$) ; By Zapman Inspired by Fr34k 
  Protected Unicode$ = Space(Len(String$)* 2 + 2) 
  Protected bstr_string.l 
  PokeS(@Unicode$, String$, -1, #PB_Unicode) 
  bstr_string = SysAllocString_(@Unicode$) 
  ProcedureReturn bstr_string 
EndProcedure 

Structure GdiplusStartupInput 
  GdiPlusVersion.l 
  *DebugEventCallback.Debug_Event
  SuppressBackgroundThread.l 
  SuppressExternalCodecs.l 
EndStructure 

Prototype GdipLoadImageFromFile( *filename, *image )
Prototype GdiplusStartup( *token, *input, mode ) 
Prototype GdiplusShutdown( *token )
Prototype GdipDisposeImage( *image )

OpenLibrary(gdipluslib, "gdiplus.dll")

Global GdipLoadImageFromFile.GdipLoadImageFromFile = GetFunction(gdipluslib, "GdipLoadImageFromFile")
Global GdiplusStartup.GdiplusStartup               = GetFunction( 0, "GdiplusStartup" )  
Global GdiplusShutdown.GdiplusShutdown             = GetFunction( 0, "GdiplusShutdown" )  
Global GdipDisposeImage.GdipDisposeImage           = GetFunction( 0, "GdipDisposeImage" )

input.GdiplusStartupInput
input\GdiPlusVersion = 1
GdiplusStartup( @*token, @input, #Null)

file$ = #PB_Compiler_Home + "examples\sources\data\world.png"

GdipLoadImageFromFile( StringToBStr(file$), @*image )

Debug *image ; non-zero here means it worked

If *image
  GdipDisposeImage(*image)
EndIf

GdiplusShutdown(*token)
Here is the same code but in the GdipLoadImageFromFile prototype we give the filename parameter a pseudotype of p-unicode. Now the extra procedure is not necessary any more and the code is smaller, cleaner and more self-documenting:

Code: Select all

Structure GdiplusStartupInput 
  GdiPlusVersion.l 
  *DebugEventCallback.Debug_Event
  SuppressBackgroundThread.l 
  SuppressExternalCodecs.l 
EndStructure 

Prototype GdipLoadImageFromFile( filename.p-unicode, *image )
Prototype GdiplusStartup( *token, *input, mode ) 
Prototype GdiplusShutdown( *token )
Prototype GdipDisposeImage( *image )

OpenLibrary(gdipluslib, "gdiplus.dll")

Global GdipLoadImageFromFile.GdipLoadImageFromFile = GetFunction(gdipluslib, "GdipLoadImageFromFile")
Global GdiplusStartup.GdiplusStartup               = GetFunction( 0, "GdiplusStartup" )  
Global GdiplusShutdown.GdiplusShutdown             = GetFunction( 0, "GdiplusShutdown" )  
Global GdipDisposeImage.GdipDisposeImage           = GetFunction( 0, "GdipDisposeImage" )

input.GdiplusStartupInput
input\GdiPlusVersion = 1
GdiplusStartup( @*token, @input, #Null)

file$ = #PB_Compiler_Home + "examples\sources\data\world.png"

GdipLoadImageFromFile( file$, @*image )

Debug *image ; non-zero here means it worked

If *image
  GdipDisposeImage(*image)
EndIf

GdiplusShutdown(*token)
BERESHEIT
Fred
Administrator
Administrator
Posts: 18254
Joined: Fri May 17, 2002 4:39 pm
Location: France
Contact:

Re: Prototypes used to speed up calling Procedures

Post by Fred »

You should really use the "p-bstr" prototype then :)
User avatar
netmaestro
PureBasic Bullfrog
PureBasic Bullfrog
Posts: 8451
Joined: Wed Jul 06, 2005 5:42 am
Location: Fort Nelson, BC, Canada

Re: Prototypes used to speed up calling Procedures

Post by netmaestro »

:shock: I was so proud of my brilliant post! Shot down in flames... I'm going to go play with spider now :cry:

(hehe)
BERESHEIT
Fred
Administrator
Administrator
Posts: 18254
Joined: Fri May 17, 2002 4:39 pm
Location: France
Contact:

Re: Prototypes used to speed up calling Procedures

Post by Fred »

:lol:
hgcoon
New User
New User
Posts: 9
Joined: Wed Feb 19, 2014 11:09 pm

Re: Prototypes used to speed up calling Procedures

Post by hgcoon »

Wow! Thank you all. I am impressed with the speed and relevance of the answers. I am starting out with the first by "srod" who seems to have considerable experience teaching. When I can get to it, I'll post timing results. I am very pleased with these responses and am very happy to have a chance to join the PB family. Thank you all very much indeed. HGC
davido
Addict
Addict
Posts: 1890
Joined: Fri Nov 09, 2012 11:04 pm
Location: Uttoxeter, UK

Re: Prototypes used to speed up calling Procedures

Post by davido »

Very nice explanatory examples. Thank you, all.

Perhaps these could be linked to the manual; would make these functions more easily understandable.
DE AA EB
User avatar
blueznl
PureBasic Expert
PureBasic Expert
Posts: 6166
Joined: Sat May 17, 2003 11:31 am
Contact:

Re: Prototypes used to speed up calling Procedures

Post by blueznl »

( PB6.00 LTS Win11 x64 Asrock AB350 Pro4 Ryzen 5 3600 32GB GTX1060 6GB)
( The path to enlightenment and the PureBasic Survival Guide right here... )
davido
Addict
Addict
Posts: 1890
Joined: Fri Nov 09, 2012 11:04 pm
Location: Uttoxeter, UK

Re: Prototypes used to speed up calling Procedures

Post by davido »

@blueznl

Interesting, thanks.
DE AA EB
Amundo
Enthusiast
Enthusiast
Posts: 200
Joined: Thu Feb 16, 2006 1:41 am
Location: New Zealand

Re: Prototypes used to speed up calling Procedures

Post by Amundo »

Thanks for all the examples, guys, I've never understood them 100% (I'm slow :oops: ).

Now I have no excuse :)
Win10, PB6.x, okayish CPU, onboard video card, fuzzy monitor (or is that my eyesight?)
"When the facts change, I change my mind" - John Maynard Keynes
User avatar
flaith
Enthusiast
Enthusiast
Posts: 704
Joined: Mon Apr 25, 2005 9:28 pm
Location: $300:20 58 FC 60 - Rennes
Contact:

Re: Prototypes used to speed up calling Procedures

Post by flaith »

netmaestro wrote::shock: I was so proud of my brilliant post! Shot down in flames... I'm going to go play with spider now :cry:

(hehe)
http://www.youtube.com/watch?v=UKwVvSleM6w :mrgreen:
“Fear is a reaction. Courage is a decision.” - WC
Denis
Enthusiast
Enthusiast
Posts: 778
Joined: Fri Apr 25, 2003 5:10 pm
Location: Doubs - France

Re: Prototypes used to speed up calling Procedures

Post by Denis »

Fred wrote:You should really use the "p-bstr" prototype then :)
Fred, when you tell that, it means what ?
That all 'p-unicode' could be change by 'p-bstr' ?

According MS here, we can use bstr type for typedef WCHAR OLECHAR.

As it's explain, unicode is different from BSTR (no prefix for example).
GdipLoadImageFromFile_() is declared like this in gdiplusflat.h file (from last SKD version).
GdipLoadImageFromFile(GDIPCONST WCHAR* filename, GpImage **image);
I've readen that OLECHAR is a string of wchar_t and WCHAR is declared in WinNT.h as follows: typedef wchar_t WCHAR;

Is that right if i tell that p-unicode can be changed by p-bstr all the times ?
A+
Denis
Fred
Administrator
Administrator
Posts: 18254
Joined: Fri May 17, 2002 4:39 pm
Location: France
Contact:

Re: Prototypes used to speed up calling Procedures

Post by Fred »

No, you should use p-bstr only when it's really a necessity, as it does allocate and free a SYSString at every call. I think than p-unicode is enough for most of cases, unless PBSTR is specified in the API (sometimes an API can modify the string and return a new one).
Post Reply