MATLAB Production Server C Client R2025a component: mds_c_client, module directory: deployment_server/client/c/mps, copyright: MathWorks |

Loading...
Searching...
No Matches
MATLAB Production Server C Client

- Overview
- Quick Example
- Configure the Client-Server Connection
- Data Handling
- Error Handling
- Resource Clean-Up

## <a name="overview"></a>Overview

MATLAB Production Server is a client-server framework created by MathWorks for deploying MATLAB code in scalable and robust manner. The server hosts one or more deployable archives, each exporting one or more MATLAB functions. These MATLAB functions can be invoked from a C/C++ application using the MATLAB Production Server C client API. The client sends request with all the information required to invoke the MATLAB function and receives the result in the response. The server instance may be running on the same machine as the client or on a remote machine.

MPS Overview

The following example demonstrates how MATLAB Production Server can be used to create a scalable MATLAB application.

## <a name="quick_example"></a>Quick Example

This example deploys a simple MATLAB function to a MATLAB Production Server instance and creates a C application that accesses it:

1. Write a MATLAB function.
2. Create a deployable archive.
3. Start a MATLAB Production Server instance.
4. Deploy the deployable archive to a MATLAB Production Server instance.
5. Write a C application to call MATLAB function.
6. Build the application.
7. Run the application.

> ‍NOTE

> For the sake of simplicity, we will assume that the client and server are running on the same machine. We will also assume that MATLAB and MATLAB Compiler are installed on this machine.

### <a name="qe1"></a>STEP 1 : Write a MATLAB function

Create a simple MATLAB function, `mymagic`, that takes a single `double` input and returns a magic square as a 2-D `double` array:

    function m = mymagic(in)
      m = magic(in);
    end

### <a name="qe2"></a>STEP 2 : Create a Deployable Archive

Compile the MATLAB function into a deployable archive as follows:

1. Start the Production Server Compiler app from MATLAB.
2. Create a new project with the name `magic` with Deployable Archive as the target.
3. Add the MATLAB function, `mymagic`, to this project.
4. Build the project to create `magic.ctf` in the `magic/for_redistribution_files_only` directory.

### <a name="qe3"></a>STEP 3 : Start a MATLAB Production Server instance

> ‍Note

> For this example the MATLAB Production Server is installed in `$MPS_INSTALL` directory and `$MPS_INSTALL/script` is on the system path. The directory where we want to create the MATLAB Production Server instance is `/tmp/mpsInst1`.

> ‍Note

> The paths used in the instructions are for Linux.

Before you can start a MATLAB Production Server instance, you must create it:

1. If you have not already done so, run `mps-setup` to configure the MATLAB Compiler Runtime the server instance will use.
2. Enter the following command in a terminal window to create a new instance of MATLAB Production Server at `/tmp/mpsInst1`.

   > ‍Note

   > The directory `/tmp/mpsInst1` must not exist before entering the following command.

   > % mps-new /tmp/mpsInst1

   -# Verify the configuration of a MATLAB Production Server instance by editing `/tmp/mpsInst1/config/main.config`.

       This file has the default configuration parameters when a MATLAB Production Server instance is created for the first time.

   Start the server instance:
3. Change the current working directory to the new MATLAB Production Server instance.
4. Start the server with the `mps-start` command.
   % cd /tmp/mpsInst1
   % mps-start
   By default, the MATLAB Production Server instance listens to port number `9910` for client requests. This can be verified in the `/tmp/mpsInst1/endpoint/http` file:
   % cat /tmp/mpsInst1/endpoint/http
   127.0.0.1:9910
5. Check status of MATLAB Production Server instance can be checked using the `mps-status` command:
   % mps-status
   'tmp/mpsInst1' STARTED
   license checked out

### <a name="qe4"></a>STEP 4 : Deploy the Deployable Archive on the MATLAB Production Server instance

Once the MATLAB Production Server instance is started, you need to deploy the deployable archive to it. To deploy the deployable archive, `magic.ctf`, copy it to the `/tmp/mpsInst1/auto_deploy` folder of the server instance.

Now, it is available to the MATLAB Production Server C client API at URL: `http://localhost:9910/magic/mymagic`.

The format of the URL is: <host_name>:<port_number>/<archive_file_name_without_extension>/<function_name>

### <a name="qe5"></a>STEP 5: Write a C application to call MATLAB function.

> ‍Note

> The header files for the MATLAB Production Server C client API are located in the `$MPS_INSTALL/client/c/include/mps` folder where `$MPS_INSTALL` is the root folder which MATLAB Production Server is installed.

Before you can call the method representing the MATLAB function, you must:

1. Initialize the MATLAB Production Server client runtime.
2. Configure the client runtime.
3. Create a client context for managing the connection between the client and the server instance.
4. Populate the input data for the function.

To call the MATLAB function use the `mpsClientRuntime` `feval()` function.

Before you can access the data returned from the MATLAB function, you must:

1. Determine if the function evaluated successfully.
2. Use the `mpsArray` validation API to determine the type of data returned.
3. Use the appropriate accessors for the output data.

#include <iostream>
#include <mps/client.h>
int main ( void )
{
mpsClientRuntime* mpsruntime = mpsInitialize();
mpsClientConfig* config;
mpsStatus status = mpsruntime->createConfig(&config);
mpsClientContext* context;
status = mpsruntime->createContext(&context, config);
int sqrSize = 5;
int numIn = 1;
const mpsArray** const inVal = new const mpsArray* [numIn];
inVal[0] = mpsCreateDoubleScalar(sqrSize);
int numOut = 1;
mpsArray **outVal = new mpsArray* [numOut];
status = mpsruntime->feval(context,"http://localhost:9910/magic/mymagic", numOut, outVal, numIn, inVal);
if (status==MPS_OK)
{
double* magic = mpsGetPr(outVal[0]);
for (int i=0; i<sqrSize; i++)
{
for (int j=0; j<sqrSize; j++)
{
mpsIndex subs[] = {i, j};
mpsIndex id = mpsCalcSingleSubscript(outVal[0], 2, subs);
std::cout << magic[i] << "\t";
}
std::cout << std::endl;
}
for (int i=0; i<numOut; i++)
mpsDestroyArray(outVal[i]);
delete[] outVal;
}
else
{
mpsErrorInfo error;
mpsruntime->getLastErrorInfo(context, &error);
std::cout << "Error: " << error.message << std::endl;
switch(error.type)
{
case MPS_HTTP_ERROR_INFO:
std::cout << "HTTP: " << error.details.http.responseCode << ": " << error.details.http.responseMessage << std::endl;
case MPS_MATLAB_ERROR_INFO:
std::cout << "MATLAB: " << error.details.matlab.identifier << std::endl;
std::cout << error.details.matlab.message << std::endl;
case MPS_GENERIC_ERROR_INFO:
std::cout << "Generic: " << error.details.general.genericErrorMsg << std::endl;
}
mpsruntime->destroyLastErrorInfo(&error);
}
for (int i=0; i<numIn; i++)
mpsDestroyArray(inVal[i]);
delete[] inVal;
mpsruntime->destroyConfig(config);
mpsruntime->destroyContext(context);
mpsTerminate();
}
client.h
MPS_GENERIC_ERROR_INFO
@ MPS_GENERIC_ERROR_INFO
Any error other than MATLAB execution error or a non-200 HTTP response.
Definition client.h:170
MPS_HTTP_ERROR_INFO
@ MPS_HTTP_ERROR_INFO
A non-200 HTTP response when MATLAB function in invoked from the client.
Definition client.h:164
MPS_MATLAB_ERROR_INFO
@ MPS_MATLAB_ERROR_INFO
A MATLAB execution error.
Definition client.h:167
mpsClientContext
struct mpsClientContext mpsClientContext
Establishes a connection between a client and a server.
Definition client.h:69
mpsIndex
uint64 mpsIndex
Type that represents index values, such as indices into arrays.
Definition client.h:51
mpsGetPr
double * mpsGetPr(const mpsArray *mlArr)
Access the real data in an array of doubles.
mpsTerminate
void mpsTerminate(void)
Perform global clean up of resources consumed by MATLAB Production Server client environment.
mpsCreateDoubleScalar
mpsArray * mpsCreateDoubleScalar(double value)
Create a scalar double-precision floating-point array.
mpsCalcSingleSubscript
mpsIndex mpsCalcSingleSubscript(const mpsArray *mlArr, mpsSize nsubs, mpsIndex *subs)
Determine how many elements there are between the beginning of an array and a given element.
mpsStatus
mpsStatus
Error status codes for all methods which are part of the MATLAB Production Server client API.
Definition client.h:257
MPS_OK
@ MPS_OK
Successful invocation of a method.
Definition client.h:260
mpsInitialize
mpsClientRuntime * mpsInitialize(void)
Set up the programming environment for MATLAB Production Server client based on version 1....
mpsDestroyArray
void mpsDestroyArray(mpsArray *mlArr)
Deallocate the memory occupied by an array.
mpsClientConfig
struct mpsClientConfig mpsClientConfig
Structure containing information configuring the connection between the client and a server instance.
Definition client.h:61
mpsArray
struct mpsArray mpsArray
Fundamental type underlying MATLAB data.
Definition client.h:55
mpsClientRuntime
MATLAB Production Server client API container.
Definition client.h:315
mpsClientRuntime::createConfig
mpsStatus(* createConfig)(mpsClientConfig **config)
Initialize pointer to MATLAB Production Server client configuration instance with default values.
Definition client.h:327
mpsClientRuntime::feval
mpsStatus(* feval)(mpsClientContext *context, const char *url, int nlhs, mpsArray *plhs[], int nrhs, const mpsArray *prhs[])
Invoke MATLAB function hosted by a server instance and available at a Url.
Definition client.h:411
mpsClientRuntime::getLastErrorInfo
void(* getLastErrorInfo)(mpsClientContext const *context, mpsErrorInfo *errorInfo)
Access the error thrown while invoking a MATLAB function from the client A MATLAB function invocation...
Definition client.h:383
mpsClientRuntime::createContext
mpsStatus(* createContext)(mpsClientContext **context, const mpsClientConfig *config)
Initialize the MATLAB Production Server client execution context.
Definition client.h:358
mpsClientRuntime::destroyContext
void(* destroyContext)(mpsClientContext *context)
Clean up the memory allocated for the client execution context.
Definition client.h:368
mpsClientRuntime::destroyLastErrorInfo
void(* destroyLastErrorInfo)(mpsErrorInfo *errorInfo)
Cleans up dynamic memory allocated while initializing mpsErrorInfo instance.
Definition client.h:387
mpsClientRuntime::destroyConfig
void(* destroyConfig)(mpsClientConfig *config)
Clean up the memory allocated to the client configuration instance.
Definition client.h:332
mpsErrorInfoGeneric::genericErrorMsg
const char * genericErrorMsg
Error message corresponding to the generic error.
Definition client.h:227
mpsErrorInfoHTTP::responseMessage
const char * responseMessage
HTTP response message.
Definition client.h:183
mpsErrorInfoHTTP::responseCode
unsigned int responseCode
HTTP response code.
Definition client.h:180
mpsErrorInfoMATLAB::message
const char * message
Error message corresponding to the error thrown in MATLAB.
Definition client.h:209
mpsErrorInfoMATLAB::identifier
const char * identifier
Unique error identifier corresponding to the MATLAB error.
Definition client.h:212
mpsErrorInfo
Error thrown when a MATLAB function is invoked by the MATLAB Production Server client context.
Definition client.h:234
mpsErrorInfo::details
union mpsErrorInfo::@0 details
All possible errors that can be thrown when a MATLAB function is invoked from the client.
mpsErrorInfo::type
mpsErrorInfoType type
Type of underlying error.
Definition client.h:237
mpsErrorInfo::general
mpsErrorInfoGeneric general
Error other than MATLAB execution error and non-200 HTTP response.
Definition client.h:251
mpsErrorInfo::message
char const * message
Message regarding the error.
Definition client.h:240
mpsErrorInfo::http
mpsErrorInfoHTTP http
Error caused by a non-200 HTTP response.
Definition client.h:245
mpsErrorInfo::matlab
mpsErrorInfoMATLAB matlab
Error thrown during execution of MATLAB code.
Definition client.h:248

### <a name="qe6"></a>STEP 6: Build the application.

To compile your client code, the compiler needs access to `client.h`. This is stored in `$MPSROOT/client/c/include/mps/`.

To link your application, the linker needs access to:

Windows | UNIX/Linux | Mac OSX
--- | --- | ---
`$C_CLIENT\$arch\lib\mpsclient.lib` | `$C_CLIENT/$arch/lib/libprotobuf.so` | `$C_CLIENT/$arch/lib/libprotobuf.dylib`
| `$C_CLIENT/$arch/lib/libcurl.so` | `$C_CLIENT/$arch/lib/libcurl.dylib`
| `$C_CLIENT/$arch/lib/libmwmpsclient.so` | `$C_CLIENT/$arch/lib/libmwmpsclient.dylib`
| `$C_CLIENT/$arch/lib/libmwcpp11compat.so` |

Where `$C_CLIENT` is `$MPSROOT\client\c\`.

### <a name="qe7"></a>STEP 7: Run the application.

To run your client the following libraries need to be on your system path:

Windows | UNIX/Linux | Mac OSX
--- | --- | ---
`$C_CLIENT/$arch/lib/libprotobuf.dll` | `$C_CLIENT/$arch/lib/libprotobuf.so` | `$C_CLIENT/$arch/lib/libprotobuf.dylib`
`$C_CLIENT/$arch/lib/libcurl.dll` | `$C_CLIENT/$arch/lib/libcurl.so` | `$C_CLIENT/$arch/lib/libcurl.dylib`
`$C_CLIENT/$arch/lib/mpsclient.dll` | `$C_CLIENT/$arch/lib/libmwmpsclient.so` | `$C_CLIENT/$arch/lib/libmwmpsclient.dylib`
| `$C_CLIENT/$arch/lib/libmwcpp11compat.so` |

Where `$C_CLIENT` is `$MPSROOT\client\c\`.

The output should resemble:

17 24 1 8 15
23 5 7 14 16
4 6 13 20 22
10 12 19 21 3
11 18 25 2 9

## <a name="client_config"></a> Configure the Client-Server Connection

You configure the client-server connection using a structure of type `mpsClientConfig`. The structure has these fields:

- `responseTimeOut` - determines the amount of time, in milliseconds, the client waits for a response before timing out.
- `reponseSizeLimit` - determines the maximum size, in bytes, of the response a client accepts.

You can use methods provided by the `mpsClientConfig` structure, to change the values before you create the client context.

### Create a Connection with the Default Configuration

When you create the client configuration using the runtime API `createConfig()` function, it is populated with default values:

- `responseTimeOut` = `120000`
- `reponseSizeLimit` = `64*1024*1024` (64 MB)

mpsClientConfig* config;
mpsStatus status = mpsruntime->createConfig(&config;);

### Change the Response Time Out

To change the amount of time the client waits for a response use the `setTimeOutSec()` function provided by the `mpsClientRuntime` structure.

This code sample creates a client connection with a time out value of 1000 ms:

mpsClientConfig* config;
mpsStatus status = mpsruntime->createConfig(&config;);
mpsruntime->setResponseTimeOutSec(config, 1000);

> ‍Tip

> Setting the response time out to `0` specifies that the client will wait indefinitely for a response.

### Change the Response Size Limit

To change the amount of data a client will accept in a response use the `setResponseSizeLimit()` function provided by the `mpsClientRuntime` structure.

This code sample creates a client connection that accepts a maximum of 4 MB in a response:

mpsClientConfig* config;
mpsStatus status = mpsruntime->createConfig(&config;);
mpsruntime->setResponseSizeLimit(config, 65*1024*1024);

## <a name="data_handling"></a>Data Handling

- Data Storage
- MATLAB Types
- Using Data Types

The MATLAB Runtime works with a single object type: the MATLAB array. All MATLAB variables (including scalars, vectors, matrices, strings, cell arrays, structures, and objects) are stored as MATLAB arrays. In C/C++, the MATLAB array is declared to be of type `mpsArray`. The `mpsArray` structure contains the following information about the array:

- Type
- Dimensions
- Data associated with the array
- If numeric, whether the variable is real or complex
- If sparse, its indices and nonzero maximum elements
- If a structure or object, the number of fields and field names

To access the `mpsArray` structure, use the `mpsArray` API functions. These functions enable you to create, read, and query information about the MATLAB data used by the client. The `mpsArray` API mirrors the `mxArray` API used by MATLAB Compiler and MATLAB external interfaces.

## <a name="data_storage"></a>Data Storage

MATLAB stores data in a column-major (columnwise) numbering scheme. MATLAB internally stores data elements from the first column first, then data elements from the second column second, and so on, through the last column.

For example, given the matrix:

a=['house'; 'floor'; 'porch']
a =
house
floor
porch

its dimensions are:

size(a)
ans =
3 5

and its data is stored as:

If a matrix is N-dimensional, MATLAB represents the data in N-major order. For example, consider a three-dimensional array having dimensions 4-by-2-by-3. Although you can visualize the data as:

MATLAB internally represents the data for this three-dimensional array in the following order:

A | B | C | D | E | F | G | H | I | J | K | L | M | N | O | P | Q | R | S | T | U | V | W | X
--- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | ---
0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23

> ‍Note

> Unlike C indexing, MATLAB indexing starts at 1.

The `mpsCalcSingleSubscript()` function creates the offset from the first element of an array to the desired element, using N-dimensional subscripting.

## <a name="matlab_types"></a>MATLAB Types

- Complex Double-Precision Matrices
- Numeric Matrices
- Logical Matrices
- MATLAB Strings
- Cell Arrays
- Structures
- Multidimensional Arrays
- Empty Arrays
- Sparse Matrices

### <a name="cdpm"></a>Complex Double-Precision Matrices

Complex double-precision, non-sparse matrices are of type `double` and have dimensions `m`-by-`n`, where `m` is the number of rows and `n` is the number of columns. The data is stored as two vectors of double-precision numbers—one contains the real data and one contains the imaginary data. The pointers to this data are referred to as `pr` (pointer to real data) and `pi` (pointer to imaginary data), respectively. A non-complex matrix is one whose `pi` is `NULL`.

### <a name="nm"></a>Numeric Matrices

Numeric matrices are single-precision floating-point integers that can be 8-, 16-, 32-, and 64-bit, both signed and unsigned. The data is stored in two vectors in the same manner as double-precision matrices.

### <a name="lm"></a>Logical Matrices

The `logical` data type represents a logical `true` or `false` state using the numbers `1` and `0`, respectively. Certain MATLAB functions and operators return logical `1` or logical `0` to indicate whether a certain condition was found to be true or not. For example, the statement `(5 * 10) > 40` returns a logical `1` value.

### <a name="ms"></a>MATLAB Strings

MATLAB strings are of type `char` and are stored in a similar manner to unsigned 16-bit integers, except there is no imaginary data component. Unlike C, MATLAB strings are not null terminated.

### <a name="ca"></a>Cell Arrays

Cell arrays are a collection of MATLAB arrays where each `mpsArray` is referred to as a cell, enabling MATLAB arrays of different types to be stored together. Cell arrays are stored in a similar fashion to numeric matrices, except the data portion contains a single vector of pointers to `mpsArrays`. Members of this vector are called cells. Each cell can be of any supported data type, even another cell array.

### <a name="structs"></a>Structures

A 1-by-1 structure is stored in the same manner as a 1-by-`n` cell array where `n` is the number of fields in the structure. Members of the data vector are called fields. Each field is associated with a name stored in the `mpsArray`.

### <a name="mda"></a>Multidimensional Arrays

A multidimensional array is a vector of integers where each element is the size of the corresponding dimension. The storage of the data is the same as matrices. MATLAB arrays of any type can be multidimensional.

### <a name="ea"></a>Empty Arrays

An empty `mpsArray` is one with at least one dimension equal to zero. For example, a double-precision `mpsArray` of type `double`, where `m` and `n` equal `0` and `pr` is `NULL`, is an empty array. MATLAB arrays of any type can be empty.

### <a name="sm"></a>Sparse Matrices

Sparse matrices have a different storage convention from that of full matrices in MATLAB. The parameters `pr` and `pi` are arrays of double-precision numbers, but these arrays contain only nonzero data elements. There are three additional parameters:

- `nzmax` is an integer that contains the length of `ir`, `pr`, and, if it exists, `pi`. It is the maximum number of nonzero elements in the sparse matrix.
- `ir` points to an integer array of length `nzmax` containing the row indices of the corresponding elements in `pr` and `pi`.
- `jc` points to an integer array of length `n+1`, where `n` is the number of columns in the sparse matrix. The `jc` array contains column index information. If the jth column of the sparse matrix has any nonzero elements, `jc[j]` is the index in `ir` and `pr` (and `pi` if it exists) of the first nonzero element in the jth column, and `jc[j+1] - 1` is the index of the last nonzero element in that column. For the jth column of the sparse matrix, `jc[j]` is the total number of nonzero elements in all preceding columns. The last element of the `jc` array, `jc[n]`, is equal to `nnz`, the number of nonzero elements in the entire sparse matrix. If `nnz` is less than `nzmax`, more nonzero entries can be inserted into the array without allocating more storage.

## <a name="using_data_types"></a>Using Data Types

- Declaring Data Structures
- Manipulating Data

You can write MATLAB Production Server client applications in C/C++ that accept any class or data type supported by MATLAB (see Data Types).

> ‍Caution

> The MATLAB Runtime does not check the validity of MATLAB data structures created in C/C++. Using invalid syntax to create a MATLAB data structure can result in unexpected behaviour.

### <a name="declaring_data_structures"></a>Declaring Data Structures

To handle MATLAB arrays, use type `mpsArray`. The following statement declares an `mpsArray` named `myData`:

mpsArray *myData;

To define the values of `myData`, use one of the `mpsCreate*` functions. Some useful array creation routines are `mpsCreateNumericArray()`, `mpsCreateCellArray()`, and `mpsCreateCharArray()`. For example, the following statement allocates an `m`-by-1 floating-point `mpsArray` initialized to 0:

myData = mpsCreateDoubleMatrix(m, 1, mpsREAL);
mpsREAL
@ mpsREAL
Identifies an mpsArray with no imaginary components.
Definition client.h:270
mpsCreateDoubleMatrix
mpsArray * mpsCreateDoubleMatrix(mpsSize m, mpsSize n, mpsComplexity complexFlag)
Create a two-dimensional double-precision floating-point array.

C/C++ programmers should note that data in a MATLAB array is in column-major order. (For an illustration, see Data Storage.) Use the MATLAB `mpsGet*` array access routines to read data from an `mpsArray`.

### <a name="manipulating_data"></a>Manipulating Data

The `mpsGet*` array access routines get references to the data in an `mpsArray`. Use these routines to modify data in your client application. Each function provides access to specific information in the `mpsArray.` Some useful functions are `mpsGetData()`, `mpsGetPr()`, `mpsGetM()`, and `mpsGetString()`.

The following statements read the input string `prhs[0]` into a C-style string `buf`:

char *buf;
int buflen;
int status;
buflen = mpsGetN(prhs[0])*sizeof(mpsChar)+1;
buf = malloc(buflen);
status = mpsGetString(prhs[0], buf, buflen);
mpsGetString
int mpsGetString(const mpsArray *mlArr, char *str, mpsSize len)
Copy the character data of a string array into a C-style string.
mpsGetN
size_t mpsGetN(const mpsArray *mlArr)
Determine the number of columns in an array.
mpsChar
CHAR16_T mpsChar
Definition client.h:141

## <a name="error_handling"></a>Error Handling

To handle errors that occur when processing MATLAB functions:

1. Determine if the function was successfully processed.
2. Get the error information using `getLastErrorInfo()`.
3. Determine the type of error.
4. Process the error information appropriately.
5. Clean-up the resources used by the error information using `destroyLastErrorInfo()`.

### <a name="error_yes_no"></a>Determine if an Error Occurred

Many of the `mpsClientRuntime` functions return a value of type `mpsStatus`.

A return value of `MPS_OK` indicates that the function processed successfully.

A return value of `MPS_FAILURE` indicates that an error occurred.

For example, to check if an error occurred while evaluating a MATLAB function, use an `if-then` statement:

status = mpsruntime->feval(context,funUrl,outArgs,outVal,inArgs,inVal);
if (status==MPS_OK)
{
...
}
else
{
...
}

> ‍Note

> Only the `feval()` function returns more details about the error.

### <a name="get_error"></a>Get the Error Information

If a call to `feval()` returns a value of `MPS_FAILURE`, you can determine the error by calling the `getLastErrorInfo()` function. It returns an `mpsErrorInfo` structure that contains these fields:

- `message` - String containing general information about the error
- `type` - Character identifying the type of error. The type identifier is used to select the correct data type for the detailed error information.
- `details` - Structure containing details, such as the MATLAB stack, about the error and its underlying cause

To get the error information and print the basic error message:

mpsErrorInfo error;
mpsruntime->getLastErrorInfo(context, &error);
std::cout << "Error: " << error.message << std::endl;

### <a name="error_type"></a>Determine the Type of Error

Before you can process the detailed error information, you need to determine what type of error occurred. This is done by interrogating the `type` field of the `mpsErrorInfo` structure. It can have one of three values:

- `MPS_HTTP_ERROR_INFO` - Non-200 HTTP error occurred and the details are stored in an `mpsErrorInfoHTTP` structure
- `MPS_MATLAB_ERROR_INFO` - MATLAB error occurred and the details are stored in an `mpsErrorInfoMATLAB` structure
- `MPS_GENERIC_ERROR_INFO` - Indeterminate error occurred and the details are stored in an `mpsErrorInfoGeneric` structure

Once you determine the type of error, you can process the detailed information.

To determine the error type using a `switch` statement:

mpsErrorInfo error;
mpsruntime->getLastErrorInfo(context, &error);
switch(error.type)
{
case MPS_HTTP_ERROR_INFO:
...
case MPS_MATLAB_ERROR_INFO:
...
case MPS_MATLAB_ERROR_INFO:
...
}

### <a name="error_process"></a>Process an HTTP Error

The details of an HTTP error are stored in an `mpsErrorInfoHTTP` structure. This structure has two fields:

- `responseCode` - HTTP error code
- `responseMessage` - String containing the message returned with the error

For example, if you attempt to access a function using an invalid URL, the client may return an `mpsErrorInfoHTTP` structure with the following values:

- `responseCode` - 404
- `responseMessage` - Not Found

### Process a MATLAB Error

If the error occurred while the MATLAB Runtime was evaluating the function the client returns an `mpsErrorInfoMATLAB` structure. This structure has the following fields:

- `message` - Error message returned by the MATLAB Runtime
- `identifier` - MATLAB error ID
- `matlabStack` - MATLAB Runtime stack
- `matlabStackDepth` - Number of entries in the MATLAB Runtime stack

The entries in the MATLAB Runtime stack have the following fields:

- `file` - Name of the MATLAB file that caused the error
- `function` - Name of the MATLAB function that caused the error
- `line` - Line number in the MATLAB file that caused the error

To print the contents of a MATLAB error:

mpsErrorInfo error;
mpsruntime->getLastErrorInfo(context, &error);
switch(error.type)
{
case MPS_HTTP_ERROR_INFO:
...
case MPS_MATLAB_ERROR_INFO:
std::cout << "MATLAB: " << error.details.matlab.identifier << std::endl;
std::cout << error.details.matlab.message << std::endl;
for (int i=0; i < error.details.matlab.matlabStackDepth; i++)
{
std::cout << "in " << error.details.matlab.matlabStack[i].file << " at "
<< error.details.matlab.matlabStack[i].function << " line number " << error.details.matlab.matlabStack[i].line
<< std::endl;
}
case MPS_MATLAB_ERROR_INFO:
...
}
matlabStackFrame::function
const char * function
Name of the MATLAB function which in most cases is same as the MATLAB file name.
Definition client.h:196
matlabStackFrame::file
const char * file
Name of the MATLAB file that threw the MATLAB error.
Definition client.h:193
matlabStackFrame::line
int line
Line number in the MATLAB file where the error occurred.
Definition client.h:199
mpsErrorInfoMATLAB::matlabStackDepth
size_t matlabStackDepth
Number of entries in the MATLAB stack.
Definition client.h:218
mpsErrorInfoMATLAB::matlabStack
const matlabStackFrame * matlabStack
MATLAB stack associated with the MATLAB error.
Definition client.h:215

### Process a Generic Error

If an error other than a non-200 HTTP response or a MATLAB Runtime exception occurs, the client returns an `mpsErrorInfoGeneric` structure containing a `genericErrorMessage` field.

## <a name="clean_up"></a>Resource Clean up

The following MATLAB Production Server client artefacts have special clean up functions to release the resources when you are finished with them:

- client configuration
- client context
- client runtime
- MATLAB arrays
- error information

### <a name="cu_config"></a>Clean Up Client Configuration

You can clean up the client configuration any time after it is used to create the client context. The context copies the required configuration values when it is created.

To clean up the client configuration, use the `mpsClientRuntime` `destroyConfig()` function with a pointer to the client configuration data.

mpsClientRuntime* mpsruntime = mpsInitialize();
mpsClientConfig* config;
mpsStatus status = mpsruntime->createConfig(&config);
mpsClientContext* context;
status = mpsruntime->createContext(&context, config);
...
mpsruntime->destroyConfig(config);

### <a name="cu_context"></a>Clean Up Client Context

The client context encapsulates the connection framework between the client and a server instance. It is required to evaluate MATLAB functions. The context also performs a number of tasks to optimize the connections to server instances.

The client context should not be cleaned up until the client is done evaluating MATLAB functions using MATLAB Production Server.

To clean up the client context use the `mpsClientRuntime` `destroyContext()` function with a pointer to the client context data.

mpsClientRuntime* mpsruntime = mpsInitialize();
mpsClientConfig* config;
mpsStatus status = mpsruntime->createConfig(&config);
mpsClientContext* context;
status = mpsruntime->createContext(&context, config);
...
mpsruntime->destroyContext(context);

### <a name="cu_runtime"></a>Clean Up Client Runtime

When you are finished using the MATLAB Production Server client API, you clean up the runtime resources using the `mpsTerminate()` function.

> ‍Note

> `mpsTerminate()` does not clean up the client context or the client configuration. They must be cleaned up before calling `mpsTerminate()`.

### <a name="cu_matlab"></a>Clean Up MATLAB Arrays

MATLAB arrays stored in `mpsArray` variables are opaque. They contain a number of fields used to marshal data between your C client code and the MATLAB Runtime. Variables containing MATLAB arrays can be large.

Clean up variables containing MATLAB arrays using the `mpsDestroyArray()` function. `mpsDestroyArray()` takes a pointer to the MATLAB array being cleaned-up. It frees all of the memory used by the array.

> ‍Note

> When cleaning up the arrays used as inputs and outputs of an `feval()` call, you must clean up all of the MATLAB arrays contained in the array before you destroy the MATLAB array pointing to the inputs or outputs.

Clean up the data used in an `feval()` call.

const mpsArray** const inVal = new const mpsArray* [numIn];
...
mpsArray **outVal = new mpsArray* [numOut];
...
status = mpsruntime->feval(context,funUrl, numOut, outVal, numIn, inVal);
if (status==MPS_OK)
{
...
for (int i=0; i<numOut; i++)
mpsDestroyArray(outVal[i]);
delete[] outVal;
}
for (int i=0; i<numIn; i++)
mpsDestroyArray(inVal[i]);
delete[] inVal;

### <a name="cu_errors"></a>Clean up Error Information

The error information created by the MATLAB Production Server client runtime is opaque. Once you have processed the error, clean up the resources used by the error using the `mpsClientRuntime` `destroyLastErrorInfo()` function. It takes a pointer to the error information returned from `getLastErrorInfo()`.

mpsClientRuntime* mpsruntime = mpsInitialize();
mpsErrorInfo error;
mpsruntime->getLastErrorInfo(context, &error);
...
mpsruntime->destroyLastErrorInfo(&error);