Page 1 of 2

Prototypes used to speed up calling Procedures

Posted: Thu Feb 20, 2014 4:46 pm
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

Re: Prototypes used to speed up calling Procedures

Posted: Thu Feb 20, 2014 4:55 pm
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.

Re: Prototypes used to speed up calling Procedures

Posted: Thu Feb 20, 2014 4:58 pm
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())

Re: Prototypes used to speed up calling Procedures

Posted: Thu Feb 20, 2014 5:25 pm
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)

Re: Prototypes used to speed up calling Procedures

Posted: Thu Feb 20, 2014 5:28 pm
by Fred
You should really use the "p-bstr" prototype then :)

Re: Prototypes used to speed up calling Procedures

Posted: Thu Feb 20, 2014 5:34 pm
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)

Re: Prototypes used to speed up calling Procedures

Posted: Thu Feb 20, 2014 5:46 pm
by Fred
:lol:

Re: Prototypes used to speed up calling Procedures

Posted: Fri Feb 21, 2014 11:09 pm
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

Re: Prototypes used to speed up calling Procedures

Posted: Sat Feb 22, 2014 8:20 am
by davido
Very nice explanatory examples. Thank you, all.

Perhaps these could be linked to the manual; would make these functions more easily understandable.

Re: Prototypes used to speed up calling Procedures

Posted: Mon Feb 24, 2014 8:47 pm
by blueznl

Re: Prototypes used to speed up calling Procedures

Posted: Mon Feb 24, 2014 10:34 pm
by davido
@blueznl

Interesting, thanks.

Re: Prototypes used to speed up calling Procedures

Posted: Tue Feb 25, 2014 2:56 am
by Amundo
Thanks for all the examples, guys, I've never understood them 100% (I'm slow :oops: ).

Now I have no excuse :)

Re: Prototypes used to speed up calling Procedures

Posted: Tue Feb 25, 2014 7:42 am
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:

Re: Prototypes used to speed up calling Procedures

Posted: Mon Sep 28, 2015 2:12 pm
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 ?

Re: Prototypes used to speed up calling Procedures

Posted: Mon Sep 28, 2015 2:24 pm
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).