Extending the NCL function and procedure set

NCL has been designed to allow users the ability to extend the built-in default function set. Although this functionality is available a far amount of C and FORTRAN knowledge. In addition if you intend to call a FORTRAN function some specific knowledge of how to call FORTRAN from C is needed.

The general approach for extending the NCL function set is as follows:

The NCL binaries installed on your system should contain a library called "libncl.a". To determine if this library has been installed on your system run NCL and enter the following command: If libncl.a is not one of the libraries listed by the above command contact your site administrator.

This section uses an example to demonstrate how to extend the function set. In this example we will write a function that evaluates a polynomials given a value and arrays of polynomial coefficients. The intended NCL function interface is:

function poly(
        a[*]:float,
        b[*]:float,
        c[*]:float,
        x[1]:float
)

Writing the function in C or FORTRAN

There are only a few restrictions necessary for C and FORTRAN function. First and most important the C function, FORTRAN function or FORTRAN subroutine name must not conflict with an function names in the NCL library. Use the UNIX function "nm" to accomplish this. Second, for C none of the data passed in from the wrapper can be freed. Finally, for FORTRAN if I/O is being done you must make sure that the unit number being used is not already in use. It is also important to follow good programming practice by freeing any memory allocated by the function unless it is being passed back as a return value, and closing all files opened by the function. Also only the internal functions mentioned on this page should be used.

The following is the C source the function poly in a file called poly.c :

void poly_C(float *outval, float *a, float *b, float *c, float x, int n) {
        int i;

        for(i = 0; i < n ; i++) {
                outval[i] = (a[i] * x * x) + (b[i] * x) + c[i];
        }
}

Writing the wrapper function

The wrapper function must be written in C and use the function NclGetArgValue to retrieve the values of the parameters from NCL. The interface for the NclGetArgValue provides information as to the number of dimensions, dimension sizes, the missing values if any, the type. The prototype for NclGetArgValues is located in "NclBuiltInSupport.h". The interface for NclGetArgValue follows:

The input argument arg_num is the number of the argument requested. The arguments are numbered from left to right (as they appear in NCL) starting at 0 through n-1 where n is the total number of arguments to the function. The input argument n_args is the total number of arguments for the NCL function. The final input parameter is access_type. Access_type tells NCL whether or not the parameter being accessed will be modified or not. This is necessary to support NCL's pass-by-value parameter passing scheme.

The actual data associated with the parameter is returned as a void pointer by the NclGetArgValue function which must be cast to the appropriate type. The parameters n_dims and dimsizes represent the rank of the parameter. The type parameter is set to one of the following basic data types. NclBasicDataTypes is defined in "NclDataDefs.h".

The contents of the has_missing parameter is set to 1 if the parameter possibly contains missing values. There are some situations where it is possible to have has_missing set and not actually have a missing value in the data. This occurs when a subsection of a variable, which has missing values, is subscripted and the portion subscripted does not actually contain missing values. However, if the has_missing parameter is set to 0 then there are no missing values. The value of the missing value is returned in the union NclScalar. NclScalar is defined in "NclDataDefs.h". It is a union of all the primitive types in NCL.

Finally return values are passed back to the NCL environment via the NclReturnValue. NclReturnValue provides and interface for passing back data. It currently does not support passing back coordinates arrays or attributes, with the exception of missing values.

The prototype for the NclReturnValues function is:

One major goal of designing the wrapper function should be to establish a scheme for handling missing values, if the function you are adding does not already handle them. In the following example missing values are filtered out and propagated through to the output.

The source for the wrapper function follows:

Writing NclAddUserFuncs to register the function with NCL

The next step in extending the NCL function set is to write a function called NclAddUserFuncs. This function takes no arguments and does not return anything. Its purpose is to allow the user to call NclRegisterFunc and NclRegisterProc to tell NCL the NCL string name of the function, what the function pointer to call is, how many parameters the function takes and what the type and dimensionality of the parameters are.

There are three C functions that must be called to register a C wrapper function as as an NCL built-in function. For each function being registered in NclAddUserFuncs the function NewArgs must be called to initialize an private array that will hold the descriptions of each parameter. NewArgs takes a single integer argument that is the number of arguments for the function to be registered. It returns a void pointer which must be used in subsequent calls to SetArgTemplate and NclRegisterFunc. The next function called is SetArgTemplate. It must be called for each parameter to the function. SetArgTemplate takes the pointer returned by NewArgs, the current parameter number, the parameters type, number of dimensions and dimension sizes as input. SetArgTemplate does not return a value it simply modifies the private array returned by NewArgs. Once each parameter has defined by SetArgTemplate then either the function NclRegisterFunc or NclRegisterProc can be called depending on whether the C function being added is meant to be an NCL function or procedure. The prototypes for these four functions are located in the include file NclBuiltIns.h which should be located in ${NCARG_ROOT}/include/ncarg/ncl:

The following is the source for the function NclAddUserFuncs. More that one user function can be registered from with-in this function.

Compiling and linking files

The final step is to compile and link the source files created with libncl.a and the other ncar graphics libraries. The simplest way to compile these functions into an executable is to use the nhlcc script from the UNIX prompt. nhlcc should be located in ${NCARG_ROOT}/bin. Nhlcc is a script that will link in the appropriate HLU, LLU, and other support libraries. The compile line for this example using the nhlcc command is: AddUserFuncs.c contains the function NclAddUserFuncs and the function stubs NclAddUserFileFormats and NclAddUserHLUObjs, poly_w.c contains the wrapper function and poly.c contains the actual function source. The extra libraries on the end are for netcdf, HDF and lex respectively which are used by ncl. The following is a list of all libraries need in the order they should linked in to compile line: