Examples

Introduction Example

Example for a simple C function that adds three different parameters and a returns the sum value. The Igor code assumes that a libHandle from a loaded library with FCALL_LoadLibrary was set. First a reusable JSON object for the input parameters of AddValue is created with the utility function FCALL_SetupParameterIn. As the parameter types of the C function stay constant this has to be done only once.

For a function call only the values of the parameters have to be set. When done the JSON object is converted to its string form and used with FCALL_CallFunction.

After the call finished the JSONXOP can be used again for easy parsing of the output.

C Function Declaration
int AddValues(int a, short b, char c);
Setup and call code
// setup once
variable jsonID = FCALL_SetupParameterIn("INT32;INT32;INT16;INT8")

string parameterOut
// for each call set input values, we set here a=1, b=2 and c=3.
JSONXOP_AddValue/O/I=1 jsonID, "/Parameter/0/value"
JSONXOP_AddValue/O/I=2 jsonID, "/Parameter/1/value"
JSONXOP_AddValue/O/I=3 jsonID, "/Parameter/2/value"
// Retrieve json in string form in S_Value
JSONXOP_Dump jsonID
// issue function call
FCALL_CallFunction libHandle, "AddValues", S_Value, parameterOut

// Retrieve result
variable jsonIDOut
JSONXOP_Parse parameterOut; AbortOnRTE
jsonIDOut = V_Value
JSONXOP_GetValue/V jsonIDOut, "/result/value"; AbortOnRTE
printf "a + b + c = %d\r", V_Value
JSONXOP_Release jsonIDOut

PrintFreeDiskSpace

The first real world example shows the usage of the GetDiskFreeSpaceExA function of kernel32.dll that is part of the Windows operating system. At first code block the declaration is shown as present in fileapi.h that is part of the Windows SDK. The second code block shows how the CallFunction XOP is used to retrieve the free disk space. In this example the setup of the JSON object used for input is shown in detail. The function FCALL_GetParameterInJSON creates a skeleton JSON object for four (yet) empty input parameters. Then each type is set with an own call of JSONXOP_AddValue. In the next step all values for the parameters are set. Notably the latter three input parameters are pointers to 64 bit integers where data is returned. For these three single element UINT64 waves are created. The last three parameters are set with type WAVEREF and the path to the waves are set as value.

After the JSON object is fully setup it is dumped to its string form and GetDiskFreeSpaceExA is called. When FCALL_CallFunction returns the output is checked if an error was encountered. If everything went well the GetDiskFreeSpaceExA wrote the returned values directly into the 64 bit integer waves.

C Function Declaration
BOOL GetDiskFreeSpaceExA(
  LPCSTR          lpDirectoryName,
  PULARGE_INTEGER lpFreeBytesAvailableToCaller,
  PULARGE_INTEGER lpTotalNumberOfBytes,
  PULARGE_INTEGER lpTotalNumberOfFreeBytes
);
 1#pragma TextEncoding = "UTF-8"
 2#pragma rtGlobals=3		// Use modern global access method and strict wave access.
 3
 4#include "FCALL_functions"
 5
 6// The function GetDiskFreeSpaceExA is exported by kernel32.dll and declared in Fileapi.h
 7// See also https://docs.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-getdiskfreespaceexa
 8//
 9//BOOL GetDiskFreeSpaceExA(
10//  LPCSTR          lpDirectoryName,
11//  PULARGE_INTEGER lpFreeBytesAvailableToCaller,
12//  PULARGE_INTEGER lpTotalNumberOfBytes,
13//  PULARGE_INTEGER lpTotalNumberOfFreeBytes
14//);
15//
16// For the parameters we use the following types: STRING, WAVEREF, WAVEREF, WAVEREF
17// The waves have one element of type UINT64, that corresponds to ULARGE_INTEGER
18
19static Constant MEGABYTE = 1048576
20
21Function PrintFreeDiskSpace()
22
23	string libHandle
24	string sysRoot, dllPath, functionName
25	string parameterIn
26	string parameterOut = ""
27	string errorMsg
28	variable errorCode, returnCode
29	variable jsonID
30	string diskPath = "C:\\"
31
32	sysRoot = GetEnvironmentVariable("SystemRoot")
33	dllPath = sysRoot + "\\System32\\kernel32.dll"
34	functionName = "GetDiskFreeSpaceExA"
35
36	try
37		jsonID = FCALL_GetParameterInJSON(paramCnt = 4)
38
39		// Set result type and parameter types
40		JSONXOP_AddValue/T="UINT8" jsonID, "/result/type"; AbortOnRTE
41		JSONXOP_AddValue/T="STRING" jsonID, "/Parameter/0/type"; AbortOnRTE
42		JSONXOP_AddValue/T="WAVEREF" jsonID, "/Parameter/1/type"; AbortOnRTE
43		JSONXOP_AddValue/T="WAVEREF" jsonID, "/Parameter/2/type"; AbortOnRTE
44		JSONXOP_AddValue/T="WAVEREF" jsonID, "/Parameter/3/type"; AbortOnRTE
45		// Set parameter values
46		Make/O/N=1/L/U param1, param2, param3
47		JSONXOP_AddValue/T=diskPath jsonID, "/Parameter/0/value"; AbortOnRTE
48		JSONXOP_AddValue/T=GetWavesDataFolder(param1, 2) jsonID, "/Parameter/1/value"; AbortOnRTE
49		JSONXOP_AddValue/T=GetWavesDataFolder(param2, 2) jsonID, "/Parameter/2/value"; AbortOnRTE
50		JSONXOP_AddValue/T=GetWavesDataFolder(param3, 2) jsonID, "/Parameter/3/value"; AbortOnRTE
51
52		JSONXOP_Dump jsonID; AbortOnRTE
53		parameterIn = S_Value
54	catch
55		errorMsg = getRTErrMessage()
56		errorCode = getRTError(1)
57		printf "Building parameterIn failed with code %d : %s\r", errorCode, errorMsg
58	endtry
59	JSONXOP_Release jsonID
60
61	FCALL_LoadLibrary dllPath, libHandle; AbortOnRTE
62
63	try
64		FCALL_CallFunction libHandle, functionName, parameterIn, parameterOut; AbortOnRTE
65	catch
66		errorMsg = getRTErrMessage()
67		errorCode = getRTError(1)
68		printf "CallFunction failed with code %d : %s\r", errorCode, errorMsg
69	endtry
70	FCALL_FreeLibrary libHandle
71
72	errorCode = FCALL_GetCallError(parameterOut, errorMsg)
73	if(errorCode)
74		printf "CallFunction returned error %d : %s\r", errorCode, errorMsg
75		return NaN
76	endif
77
78	JSONXOP_Parse parameterOut; AbortOnRTE
79	jsonID = V_Value
80	JSONXOP_GetValue/V jsonID, "/result/value"; AbortOnRTE
81	if(V_Value != 0)
82		printf "FreeBytesAvailableToCaller : %.1f MB\r", param1[0] / MEGABYTE
83		printf "TotalNumberOfBytes : %.1f MB\r", param2[0] / MEGABYTE
84		printf "TotalNumberOfFreeBytes : %.1f MB\r", param3[0] / MEGABYTE
85	else
86		printf "%s returned with error.\r", functionName
87	endif
88	JSONXOP_Release jsonID
89
90End

GetVersion

The kernel32.dll library of Windows also offers a function to retrieve the detailed Windows version. This example print the output of the GetVersion function. The function takes no input parameters and returns a unsigned 32 bit integer result.

C Function Declaration
DWORD GetVersion();
 1#pragma TextEncoding = "UTF-8"
 2#pragma rtGlobals=3		// Use modern global access method and strict wave access.
 3
 4#include "FCALL_functions"
 5
 6// The function GetVersion is exported by kernel32.dll and declared in sysinfoapi.h
 7// See also https://docs.microsoft.com/en-us/windows/win32/api/sysinfoapi/nf-sysinfoapi-getversion
 8//
 9//DWORD GetVersion();
10//
11// For the parameters we leave the parameter array empty
12
13Function GetVersion()
14	string libHandle
15	string sysRoot, dllPath, functionName
16	string parameterIn
17	string parameterOut = ""
18	string errorMsg
19	variable errorCode
20	variable jsonID
21	variable returnValue, majorVersion, minorVersion, build
22
23	sysRoot = GetEnvironmentVariable("SystemRoot")
24	dllPath = sysRoot + "\\System32\\kernel32.dll"
25	functionName = "GetVersion"
26
27	try
28		jsonID = FCALL_GetParameterInJSON()
29
30		// Set result type for DWORD
31		JSONXOP_AddValue/T="UINT32" jsonID, "/result/type"; AbortOnRTE
32
33		// The GetVersion function has no input parameter, so we leave Parameter as empty array
34		JSONXOP_Dump jsonID; AbortOnRTE
35		parameterIn = S_Value
36	catch
37		errorMsg = getRTErrMessage()
38		errorCode = getRTError(1)
39		printf "Building parameterIn failed with code %d : %s\r", errorCode, errorMsg
40	endtry
41	JSONXOP_Release jsonID
42
43	FCALL_LoadLibrary dllPath, libHandle; AbortOnRTE
44
45	try
46		FCALL_CallFunction libHandle, functionName, parameterIn, parameterOut; AbortOnRTE
47	catch
48		errorMsg = getRTErrMessage()
49		errorCode = getRTError(1)
50		printf "CallFunction failed with code %d : %s\r", errorCode, errorMsg
51	endtry
52	FCALL_FreeLibrary libHandle
53
54	errorCode = FCALL_GetCallError(parameterOut, errorMsg)
55	if(errorCode)
56		printf "CallFunction returned error %d : %s\r", errorCode, errorMsg
57		return NaN
58	endif
59	// No Error, we can check results
60	JSONXOP_Parse parameterOut; AbortOnRTE
61	jsonID = V_Value
62	JSONXOP_GetValue/V jsonID, "/result/value"; AbortOnRTE
63	returnValue = V_Value
64	JSONXOP_Release jsonID
65
66	majorVersion = returnValue & 0xff
67	minorVersion = (returnValue & 0xff00) >> 8
68	if(returnValue < 0x80000000)
69		build = (returnValue & 0xffff0000) >> 16
70	endif
71	printf "Version is %d.%d (%d)\r", majorVersion, minorVersion, build
72End

QueryPerformanceCounter

The QueryPerformanceCounter function of kernel32.dll allows to retrieve the current high-precision performance counter value. In the example an inline array is used to return the value of the first input parameter. When an inline array is used the function parameter is always expected to be a pointer and the parameter type set is the pointers type. Here the parameters type is set to INT64 and the array for the value field contains a single element.

After the call the result is retrieved from the first element of the returned inline array from parameter 0 at “/Parameter/0/value/0”.

C Function Declaration
BOOL QueryPerformanceCounter(
  LARGE_INTEGER *lpPerformanceCount
);
 1#pragma TextEncoding = "UTF-8"
 2#pragma rtGlobals=3		// Use modern global access method and strict wave access.
 3
 4#include "FCALL_functions"
 5
 6// The function used here is exported by kernel32.dll and declared in profileapi.h
 7// See also https://docs.microsoft.com/en-us/windows/win32/api/profileapi/nf-profileapi-queryperformancecounter
 8//
 9//BOOL QueryPerformanceCounter(
10//  LARGE_INTEGER *lpPerformanceCount
11//);
12//
13// For the parameter an inline array is used.
14// It is read afterwards with a wave of type INT64, that corresponds to LARGE_INTEGER
15
16Function QueryPerformanceCounter()
17
18	string libHandle
19	string sysRoot, dllPath, functionName
20	string parameterIn
21	string parameterOut = ""
22	string errorMsg
23	variable errorCode, returnCode
24	variable jsonID
25
26	sysRoot = GetEnvironmentVariable("SystemRoot")
27	dllPath = sysRoot + "\\System32\\kernel32.dll"
28	functionName = "QueryPerformanceCounter"
29
30	try
31		jsonID = FCALL_GetParameterInJSON(paramCnt = 1)
32
33		// Set result type and parameter type
34		JSONXOP_AddValue/T="UINT8" jsonID, "/result/type"; AbortOnRTE
35		JSONXOP_AddValue/T="INT64" jsonID, "/Parameter/0/type"; AbortOnRTE
36		// Set as parameter value an inline array with one element
37		JSONXOP_AddTree/T=(JSON_ARRAY) jsonID, "/Parameter/0/value"; AbortOnRTE
38		JSONXOP_AddValue/I=0 jsonID, "/Parameter/0/value"; AbortOnRTE
39
40		JSONXOP_Dump jsonID; AbortOnRTE
41		parameterIn = S_Value
42	catch
43		errorMsg = getRTErrMessage()
44		errorCode = getRTError(1)
45		printf "Building parameterIn failed with code %d : %s\r", errorCode, errorMsg
46	endtry
47	JSONXOP_Release jsonID
48
49	FCALL_LoadLibrary dllPath, libHandle; AbortOnRTE
50
51	try
52		FCALL_CallFunction libHandle, functionName, parameterIn, parameterOut; AbortOnRTE
53	catch
54		errorMsg = getRTErrMessage()
55		errorCode = getRTError(1)
56		printf "CallFunction failed with code %d : %s\r", errorCode, errorMsg
57	endtry
58	FCALL_FreeLibrary libHandle
59
60	errorCode = FCALL_GetCallError(parameterOut, errorMsg)
61	if(errorCode)
62		printf "CallFunction returned error %d : %s\r", errorCode, errorMsg
63		return NaN
64	endif
65
66	// We don't have to check the returned BOOL as:
67	// quote: "On systems that run Windows XP or later, the function will always succeed and will thus never return zero."
68	JSONXOP_Parse parameterOut; AbortOnRTE
69	jsonID = V_Value
70	Make/FREE/L/N=1 wInt64
71	JSONXOP_GetValue/L=wInt64 jsonID, "/Parameter/0/value/0"
72	printf "PerformanceCount : %d\r", wInt64[0]
73	JSONXOP_Release jsonID
74End

Music Player

This example implements a very basic music player in Igor Pro. It uses the 64-bit version of the BASS library. It shows how the functions are setup once at the beginning and how the created JSON objects are reused on each call. The example can be run through the added Music Player menu entry.

Music Player

_images/music_player.png

Libarchive

Libarchive is a generic library to archive and unpack files and folders. This example uses the libarchive library to unpack a e.g. zip file(s). It shows how the functions are setup once at the beginning and how the created JSON objects are reused on each call. The example can be found in the Examples folder in UncompressFile.ipf. The main function is UncompressFiles(arcFileName, targetPath). To uncompress demo.zip in c:\mydemo to c:\unpacked call UncompressFiles("c:\\mydemo\\demo.zip", "c:\\unpacked"). The files archive.dll and zlib.dll in the Examples folder are used as dynamic libraries.

Monochromator

In this example, an Andor Shamrock monochromator and an Andor Newton detector are controlled within Igor Pro. The live example shows how to set and read-out values from the attached monochromator and camera.

_images/andor-igor.gif

Operating the instruments is under full control of Igor Pro. The debug messages show the return values from function calls to the dll files.

The package requires the AndorSDK and calls functions from the following dlls:

  • C:\Program Files\Andor SOLIS\Drivers\Shamrock64

    • atshamrock.dll

    • ShamrockCIF.dll

  • C:\Program Files\Andor SOLIS\Drivers

    • atmcd64d.dll

_images/andor-igor.png

A spectrum directly generated in Igor Pro, ready for further processing.

It should be visible from this example, that it is possible to control actual scientific hardware with Igor Pro using the CallFunction XOP.