Using the C Math Library | ![]() ![]() |
Example - Managing Array Memory (ex2.c)
This example program demonstrates how to write functions that use automated memory management. Apply this technique to every function you write.
This section presents an annotated example; Example Without Automated Memory Management shows comparable code that does uses explicit memory management.
Each of the numbered sections of code is explained in more detail below. You can find the code for the example in <matlab>/extern/examples/cmath/ex2.c
where <matlab>
represents the top-level directory of your installation. See Building Stand-Alone C Applications in Chapter 2 for information on building the examples.
The example is split into two parts. (In a working program, both parts would be placed in the same file.) The first part includes header files, declares two file static variables, and defines a routine that demonstrates how the library manages array memory. The second section contains the main program.
/* ex2.c */ #include <stdio.h> #include <stdlib.h> /* used for EXIT_SUCCESS */ #include <string.h> #include "matlab.h" /* 1 */ static double real_data1[] = { 1, 2, 3, 4, 5, 6 }; static double real_data2[] = { 6, 5, 4, 3, 2, 1 }; mxArray *Automated_Mem_Example(mxArray **z_out, mxArray *x_in, mxArray *y_in) /* 2 */ { mxArray *result_local = NULL; /* 3 */ mxArray *q_local = NULL; mlfEnterNewContext(1, 2, z_out, x_in, y_in); /* 4 */ /* In MATLAB: result = sqrt(sin(x) + cos(x)) */ mlfAssign(&result_local, mlfSqrt(mlfPlus(mlfSin(x_in), mlfCos(x_in)))); /* 5 */ /* In MATLAB: q = sqrt(cos(y) - sin(y)) */ mlfAssign(&q_local, mlfSqrt(mlfMinus(mlfCos(y_in), mlfSin(y_in)))); /* 6 */ /* In MATLAB: z = q * result - q^3 */ mlfAssign(z_out, mlfMinus(mlfTimes(q_local, result_local), mlfPower(q_local, mlfScalar(3)))); mxDestroyArray(q_local); /* 7 */ mlfRestorePreviousContext(1, 2, z_out, x_in, y_in); /* 8 */ return mlfReturnValue(result_local); /* 9 */ }
The numbered items in the list below correspond to the numbered comments in the code example:
. matlab.h
declares the mxArray
data structure and the prototypes for all the functions in the MATLAB C Math Library. stdlib.h
contains the definition of EXIT_SUCCESS
.
Automated_Mem_Example()
, takes two inputs and returns two outputs. It has one return value, one output array argument (mxArray **z_out
), and two input array arguments (mxArray *x_in
and mxArray *y_in
). The definition of the function follows the MATLAB C Math Library calling conventions where output arguments precede input arguments. You can write functions that follow these calling conventions or implement your own.
The body of Automated_Mem_Example()
performs three calculations that
illustrate how the library manages the memory allocated for the arrays. The
first two calculations operate on the two input arguments; the third on two
local arrays that store the results from the previous calculations. The
function returns one result in the output argument and the other result as
the return value from the function.
NULL
or to valid arrays. result_local
will be used to store the function's return value. q_local
will be used in a local calculation.
Note
All MATLAB C Math Library functions, including mlfAssign() , require that output arguments are initialized to NULL or point to a valid array.
|
mlfEnterNewContext()
to create a new memory context for your function. mlfEnterNewContext()
is always paired with a call to mlfRestorePreviousContext()
, which appears at the end of the function.
The first integer argument, 1
, specifies the number of output array
arguments (not including the return value) passed to
Automated_Mem_Example()
; the second integer argument, 2
, specifies the
number of input array arguments. The arrays themselves (mxArray**
for
output arguments, mxArray*
for input arguments), z_out
, x_in
, and y_in
,
are passed next, in the same order as they were passed to the function. You
do not need to terminate the list with NULL
. Note that
mlfEnterNewContext()
can take any number of arguments.
mlfEnterNewContext()
changes the state of any temporary input arrays
from temporary to bound enabling them to persist for the duration of the
function. If they are passed as input arguments to other functions, they are
passed as bound arrays.
x_in
to the MATLAB C Math Library functions mlfSin()
and mlfCos()
. These two calls return temporary arrays, which are passed to another library function, mlfPlus()
. The temporary array returned from the call to mlfPlus()
is then passed to the library function mlfSqrt()
.
In this series of nested calls only the return from mlfSqrt()
is assigned to a
variable via the mlfAssign()
function. That array, result_local
, becomes
a bound array. The temporary arrays returned from mlfSin()
and mlfCos()
and passed to mlfPlus()
are automatically deleted by mlfPlus()
;
mlfSqrt()
deletes the temporary array returned from mlfPlus()
.
mlfAssign()
now appear as frequently as the assignment operator (=
). The array on the left-hand side of the assignment (the first argument to mlfAssign()
) becomes a bound array and persists. You must explicitly delete it; the library does not.
These calculations again illustrate the automated memory management provided by the library. If you do not want to keep the array returned from a library function, just nest the call as an argument to a function. The return from the call (a temporary array) will be deleted by the other function.
In these calculations, q_local
and z_out
, are each the targets of an
assignment statement. Both are marked as bound arrays. Since q_local
is
a local variable, it must be explicitly deleted within this function. z_out
is
an output array argument that will be explicitly deleted in the calling
function.
See Assigning Arrays to mxArray* Variables to learn how
mlfAssign()
determines whether to delete the contents of the target
argument and whether to make a shared data copy of the source argument.
mlfAssign()
) a value to any local variable that is an array, you must destroy it by calling mxDestroyArray()
.
Note
The exception is a local, bound array that is the return value from the function. Do not call mxDestroyArray() on your return value.
|
mlfRestorePreviousContext()
to restore the memory context that existed prior to the function call. Supply the same arguments that you passed to mlfEnterNewContext()
.
Before ending your function and returning a value, you must call
mlfRestorePreviousContext()
to reestablish the state (temporary or
bound) of input arguments prior to the function call. Any input argument
that becomes temporary is then deleted by mlfRestorePreviousContext()
.
If you fail to call mlfRestorePreviousContext()
, your program will leak
memory.
If an input array is bound when it is passed to a function, it will never be destroyed automatically by that function or any function that it calls.
mlfReturnValue()
marks its argument as temporary. You must pass any mxArray*
that your function returns to mlfReturnValue()
before passing it to the return
statement. If you forget this step, the automated memory management of the library will be disrupted for the variable that you return, and memory will leak.
The second section of code contains the main program.
int main() { mxArray *mat0 = NULL; /* 1 */ mxArray *output_array = NULL; mxArray *result_array = NULL; mlfEnterNewContext(0, 0); /* 2 */ mlfAssign(&mat0, mlfDoubleMatrix(2, 3, real_data1, NULL)); /* 3 */ mlfAssign(&result_array, /* 4 */ Automated_Mem_Example(&output_array, mat0, mlfDoubleMatrix(2, 3, real_data2, NULL))); mlfPrintf("mat0:\n"); /* 5 */ mlfPrintMatrix(mat0); mlfPrintf("output_array:\n"); mlfPrintMatrix(output_array); mlfPrintf("result_array:\n"); mlfPrintMatrix(result_array); mxDestroyArray(mat0); /* 6 */ mxDestroyArray(result_array); mxDestroyArray(output_array); mlfRestorePreviousContext(0, 0); /* 7 */ return(EXIT_SUCCESS); }
The numbered items in the list below correspond to the numbered comments in the code example:
NULL
. MATLAB C Math Library functions that use automated memory management require that you initialize any output arguments to NULL
or a valid array. For example, before you call mlfAssign()
, you must initialize its first argument, an output argument, to NULL
or a valid array. Note that if you pass a pointer to a valid array, the contents of that array will be deleted before the assignment to the output argument takes place.
0
as the first and second argument to mlfEnterNewContext()
, indicating that the main()
routine does not have any array output or input arguments.
mlfAssign()
to assign the return from the MATLAB C Math Library function mlfDoubleMatrix()
to the array variable mat0
(a pointer to an mxArray
). mlfDoubleMatrix()
returns a 2-by-3 temporary array initialized with the data contained in the static C array, real_data1
. mat0
becomes a bound array and will persist until explicitly deleted.
mlfAssign()
to assign the return from a user-defined function to an array variable. Automated_Mem_Example()
uses the automated memory management provided by the MATLAB C Math Library functions.
mat0
is a bound array when it is passed as an input argument to
Automated_Mem_Example()
. The return value from mlfDoubleMatrix()
is a
temporary array. After the call to Automated_Mem_Example()
, mat0
still
exists; the temporary array has been deleted by Automated_Mem_Example()
.
mlfPrintMatrix()
returns void
rather than an array (mxArray *
). Both mlfPrintMatrix()
and mlfPrintf()
use the installed print handling routine to display their output. Because this example does not register a print handling routine, all output goes through the default print handler. The default print handler uses printf
. See the section Defining a Print Handler in Chapter 8 for details on registering print handlers.
mxDestroyArray()
. Note that mxDestroyArray()
can handle a NULL
argument if you inadvertently pass a pointer to an array that has already been destroyed and set to NULL
.
mlfRestorePreviousContext()
. Pass 0
as the first and second argument to indicate that main()
has no input and output arguments.
When run, the program produces this output.
mat0: 1 3 5 2 4 6 output_array: -0.0714 -0.0331 + 0.2959i -0.9461 + 1.5260i -0.6023 -1.2631 + 1.2030i 0 + 0.6181i result_array: 1.1755 0 + 0.9213i 0 + 0.8217i 0.7022 0 + 1.1876i 0.8251
![]() | Returning an Array | Example Without Automated Memory Management | ![]() |