Topic 3.7


A Quick Review of Functions

About Functions

In this topic we will review what Functions are and how they may differ from Macros. There are two types of functions: user functions and callback functions. User functions will be called manually by using the Call command instruction while Callback functions will be called by the installer when a certain event occurs.


Functions which begin with a period (.) like .OnInit are generally reserved for callback functions. Callback functions are known by their names. The names are unique and the NSIS compiler can recognize them. These functions will be called upon special events, so when that event triggers, they'll execute. As far as I know the only thing that connects Callback functions to PAL is ${Segment.OnInit} and a function called .onInstFailed which just calls the function Unload and quits.

User Functions

Unlike that of macros, functions do not take parameters, although you can do something similar by using the runtime stack along with a compile-time macro. Let's take the following function into consideration.

; Example function using the runtime stack 
; alongside a compile-time macro. Below you'll
; see you may call this either by macro or 
; calling the function itself.
Function OurFunction
	!define OurFunction "!insertmacro _OurFunction"
	!macro _OurFunction _RETURN _P1 _P2 _P3
		Push "${_P1}"
		Push "${_P2}"
		Push "${_P3}"
		Call OurFunction
		Pop "${_RETURN}"
	Exch $R0 ;= Gets _P3
	Exch $R2 ;= Gets _P2
	Exch 2
	Exch $R2 ;= Gets _P1
	Exch 2
	Push $R3 ;= Value of $R3 before function 
	IntOp $R3 $R2 * $R1 ;= 90 9 x 10 
	IntOp $R0 $R3 + $R0 ;= 93 90 + 3
	Pop $R3 ;= Set old value of $R3 back
	Pop $R2
	Pop $R1
	Exch $R0 ;= Return output

; OurSection
; Call using the macro
Section "OurFunction"
	${OurFunction} $0 10 9 3
	MessageBox MB_OK|MB_TOPMOST "$$0 == $0"; $0 == 93

; OurSection Function
; Call using the function
Section "OurFunction"
	Push 10 
	Push 9 
	Push 3
	Call OurFunction
	Pop $0
	MessageBox MB_OK|MB_TOPMOST "$$0 == $0"; $0 == 93

Using a macro to insert the actual code (rather than placing the code inside a function) means that the code will be inserted again for each !insertmacro instruction you use like we had discussed in the pervious topic. However, by placing the code in a function this will mean that the code is only included once and this will decrease the installer overhead in theory, but in practice there is very little change I believe (I have no evidence to support this though