To finish off, we’ll show how to a write a pretty generic Cicada wrapper for our C function. This will let us run our C code by typing something like
z = f(x, y)
rather than
$myFunctionInC(x, y, z)
The wrapper will also allocate data storage for our function, and prevent us from crashing the C code by passing in bad arguments. Don’t ask me what this function does.
myFunctionWrapper.cicada
f :: {
x :: char
y :: double
answer :: string
calc_table :: [] int
error_code :: int
params :: {
calcSize :: int
doRecalc :: bool }
code
params = { 100, true }
if trap(
{ x, y } = args | mandatory arguments
(params << args)() | optional arguments
) /= passed then (
print("usage: [string] = f(char, double [; calcSize/doRecalc = ...])\n")
return )
calc_table[^params.calcSize]
error_code = $myFunctionInC(params.doRecalc, x, calc_table, y, answer)
if error_code == 0 then return new(answer)
else (
print("Error ", error_code, " in function f()\n")
return * )
}
We load our wrapper by going to Cicada’s command prompt and typing:
> run("myFunctionWrapper.cicada")
Here are some examples of function calls we can make once we’ve loaded our wrapper:
result := f('a', 5)
print( f('z', 5.78; doRecalc = false) )
result := f('a', 5; calcSize = that*2, doRecalc = false)
We’ll quickly go through the different parts of our wrapper function. First, everything before the code command just defines the variables used by our function. These include the input and output arguments, optional parameters and even a calculation table used internally by our C code. Importantly, by explicitly defining variables that we pass to the C code we ensure that our function call will communicate with C properly. For example, when we write f('a', 5) the integer argument 5 will be converted to a floating-point number before handing it off to C, because the input variable x is defined to be of type double.
The executable part of f() begins after the code marker. The first bit of code reads the arguments of the function. (We enclose the actual reading commands in a trap() statement so that we can fail gracefully with an error message if the function wasn’t called properly.) Notice the two sorts of argument that the user passes. The mandatory arguments x and y are copied straightforwardly from the predefined args variable. The optional arguments, stored in params with the default values of 100 and true, can be changed using a very peculiar Cicada trick: f() runs its own arguments , as a function, inside of its own params variable. We’ll go into that later. For now, just know that when you call f() you should separate the mandatory and optional parameters using a semicolon, and use ordinary scripting commands separated by commas to change the optional parameters.
Last update: May 8, 2024