# How to Use MEX API Compatibility for Porting MATLAB Code to Nelson

> Effortlessly port MATLAB code to Nelson using the MEX C API Compatibility layer. Compile and run existing MATLAB MEX-files without source code changes.

- Repository: [The Nelson Programming Language/nelson](https://github.com/nelson-lang/nelson)
- Tags: how-to-guide
- Published: 2026-03-08

---

**Nelson provides a MEX C API Compatibility layer that allows you to compile and run existing MATLAB MEX-files without modifying the C/C++ source code.**

The `nelson-lang/nelson` repository implements a complete **MEX API compatibility** system that mirrors MATLAB's [`mex.h`](https://github.com/nelson-lang/nelson/blob/main/mex.h), [`matrix.h`](https://github.com/nelson-lang/nelson/blob/main/matrix.h), and [`engine.h`](https://github.com/nelson-lang/nelson/blob/main/engine.h) headers. This compatibility layer enables seamless porting of MATLAB extensions by providing identical function signatures, memory management routines, and runtime behaviors.

## Understanding the MEX API Compatibility Architecture

The compatibility layer consists of several interconnected components that replicate MATLAB's MEX environment.

### Header Compatibility Layer

The core headers declare the same structs, types, and functions that MATLAB code expects. In [`modules/mex/src/include/mex.h`](https://github.com/nelson-lang/nelson/blob/main/modules/mex/src/include/mex.h), Nelson defines `mexFunction`, `mxArray` helpers, `mexPrintf`, `mexLock`, and other runtime functions. The [`modules/mex/src/include/matrix.h`](https://github.com/nelson-lang/nelson/blob/main/modules/mex/src/include/matrix.h) file declares the matrix API including `mxCreateDoubleMatrix`, `mxGetPr`, and `mxIsDouble`. These headers are designed to be **bit-for-bit compatible** with MATLAB's originals.

### Runtime Gateway and Symbol Export

The [`modules/mex/src/include/nlsMex_exports.h`](https://github.com/nelson-lang/nelson/blob/main/modules/mex/src/include/nlsMex_exports.h) file handles symbol export macros (`NLSMEX_IMPEXP`) for Windows, ensuring generated shared libraries load correctly. The runtime gateway in `modules/mex/functions/dlgeneratemexgateway.m` generates the bridge code that compiles C sources, creates the shared library (`.dll`, `.so`, or `.dylib`), and forwards calls to your `mexFunction` with standard `nlhs`, `plhs`, `nrhs`, `prhs` arguments.

## Compiling MEX Files in Nelson

Porting existing MATLAB MEX code requires no source modifications—only a different compilation command.

Place your C source file (e.g., [`myfunc.c`](https://github.com/nelson-lang/nelson/blob/main/myfunc.c)) in your Nelson workspace. Invoke the built-in `mex` function:

```matlab
mex('myfunc.c')

```

Nelson automatically includes the compatibility headers from `modules/mex/src/include/`. The command compiles the source, links against the Nelson runtime, and produces `myfunc.<ext>` (platform-specific shared library). Call the function exactly as you would in MATLAB:

```matlab
result = myfunc(arg1, arg2);

```

All `mxArray` handling, memory management, and error reporting function transparently through the compatibility layer.

## Practical Code Examples

The following examples demonstrate key MEX API compatibility features using actual Nelson-supported functions.

### Hello World MEX Function

This minimal example uses `mexPrintf` from the compatibility layer:

```c
/* hello.c – a minimal MEX function */
#include "mex.h"

void mexFunction(int nlhs, mxArray *plhs[],
                 int nrhs, const mxArray *prhs[])
{
    mexPrintf("Hello from Nelson's MEX compatibility layer!\n");
}

```

```matlab
% In Nelson interpreter
mex('hello.c');          % Compile
hello();                 % → prints the message

```

### Creating and Returning Numeric Matrices

This example demonstrates `mxGetPr`, `mxCreateDoubleScalar`, and error handling:

```c
/* square.c – returns the square of a scalar input */
#include "mex.h"

void mexFunction(int nlhs, mxArray *plhs[],
                 int nrhs, const mxArray *prhs[])
{
    double *in, *out;
    if (nrhs != 1 || !mxIsDouble(prhs[0])) {
        mexErrMsgTxt("One double scalar input required.");
    }
    in = mxGetPr(prhs[0]);
    plhs[0] = mxCreateDoubleScalar((*in) * (*in));
}

```

```matlab
mex('square.c');           % Compile
y = square(3.5);           % y = 12.25

```

### Persistent State with mexLock and mexUnlock

Use `mexLock` to prevent the shared library from being cleared between calls:

```c
/* counter.c – a persistent counter that survives clearing */
#include "mex.h"

static int count = 0;

void mexFunction(int nlhs, mxArray *plhs[],
                 int nrhs, const mxArray *prhs[])
{
    if (nrhs == 0) {
        count = 0;                /* reset */
        mexUnlock();              /* allow clearing */
        return;
    }
    ++count;
    mexLock();                    /* prevent clearing */
    plhs[0] = mxCreateDoubleScalar((double)count);
}

```

```matlab
mex('counter.c');
counter()   % → 1
counter()   % → 2
clear counter   % fails because mexLock keeps the library loaded
counter(0)      % reset and unlock
clear counter   % now succeeds

```

### Callbacks to the Interpreter with mexEvalString

Execute Nelson commands from within C code:

```c
/* eval_demo.c – evaluates a Nelson command from C */
#include "mex.h"

void mexFunction(int nlhs, mxArray *plhs[],
                 int nrhs, const mxArray *prhs[])
{
    mexEvalString("disp('Evaluated from C!')");
}

```

```matlab
mex('eval_demo.c');
eval_demo();   % Displays "Evaluated from C!"

```

## Key Source Files and Implementation Details

The MEX API compatibility layer is implemented across these critical paths in the Nelson repository:

| Path | Description |
|------|-------------|
| [`modules/mex/src/include/mex.h`](https://github.com/nelson-lang/nelson/blob/main/modules/mex/src/include/mex.h) | Primary header mirroring MATLAB's [`mex.h`](https://github.com/nelson-lang/nelson/blob/main/mex.h). Defines `mexFunction` signature, `mexPrintf`, `mexLock`, `mexUnlock`, `mexAtExit`, and `mexEvalString`. |
| [`modules/mex/src/include/matrix.h`](https://github.com/nelson-lang/nelson/blob/main/modules/mex/src/include/matrix.h) | Matrix API declarations including `mxArray` struct, `mxCreateDoubleMatrix`, `mxGetPr`, `mxIsDouble`, and memory management routines. |
| [`modules/mex/src/include/engine.h`](https://github.com/nelson-lang/nelson/blob/main/modules/mex/src/include/engine.h) | Engine API for `mexCallMATLAB`-style functionality. |
| [`modules/mex/src/include/nlsMex_exports.h`](https://github.com/nelson-lang/nelson/blob/main/modules/mex/src/include/nlsMex_exports.h) | Platform abstraction for symbol visibility macros (`NLSMEX_IMPEXP`). |
| `modules/mex/functions/dlgeneratemexgateway.m` | Runtime gateway generator that handles compilation, linking, and dynamic loading of MEX shared libraries. |
| `modules/mex/tests/` | Comprehensive test suite including `test_mexLock.m`, `test_mexPrintf.m`, and other validation scripts ensuring API parity with MATLAB. |

These files collectively ensure that the `mex` built-in command in Nelson provides identical semantics to MATLAB's MEX compiler, including argument passing, memory management, and runtime services.

## Summary

- **Nelson's MEX API compatibility layer** re-implements MATLAB's [`mex.h`](https://github.com/nelson-lang/nelson/blob/main/mex.h), [`matrix.h`](https://github.com/nelson-lang/nelson/blob/main/matrix.h), and [`engine.h`](https://github.com/nelson-lang/nelson/blob/main/engine.h) headers to enable unmodified compilation of existing MEX source code.
- The **`mex`** built-in command handles compilation, linking, and dynamic loading automatically, producing platform-specific shared libraries (`.dll`, `.so`, `.dylib`).
- Key functions like **`mexLock`**, **`mexUnlock`**, **`mexEvalString`**, and **`mexPrintf`** provide identical semantics to MATLAB, including persistent state management and interpreter callbacks.
- Source files in `modules/mex/src/include/` and the runtime gateway in `modules/mex/functions/dlgeneratemexgateway.m` implement the full compatibility stack.

## Frequently Asked Questions

### What is MEX API compatibility in Nelson?

MEX API compatibility in Nelson is a complete re-implementation of MATLAB's C/C++ MEX interface that allows existing MATLAB MEX source files to compile and execute without modification. It includes header files ([`mex.h`](https://github.com/nelson-lang/nelson/blob/main/mex.h), [`matrix.h`](https://github.com/nelson-lang/nelson/blob/main/matrix.h)) that mirror MATLAB's API and a runtime system that handles compilation, linking, and execution of the resulting shared libraries.

### Do I need to modify my MATLAB MEX source code to run it in Nelson?

No. Nelson's compatibility layer is designed to work with unmodified MATLAB MEX source code. The headers in `modules/mex/src/include/` provide identical function signatures, macros, and type definitions (such as `mxArray` and `mxComplexity`) that your code already uses. Simply place your `.c` or `.cpp` file in the Nelson workspace and call `mex('filename.c')`.

### Which MATLAB functions are supported by Nelson's MEX compatibility layer?

Nelson supports the essential MEX API functions including `mexFunction` (the required entry point), `mxCreateDoubleMatrix`, `mxGetPr`, `mxIsDouble`, `mexPrintf`, `mexErrMsgTxt`, `mexLock`, `mexUnlock`, `mexAtExit`, and `mexEvalString`. However, optional MATLAB-only functions related to graphics engines or specialized toolboxes are not implemented, as Nelson maintains its own graphics and computational subsystems.

### How does Nelson handle mexLock and persistent variables in MEX files?

Nelson implements `mexLock` and `mexUnlock` to match MATLAB's behavior exactly. When your MEX function calls `mexLock()`, Nelson increments an internal lock counter that prevents the shared library from being cleared from memory, even if the user attempts `clear` or `clear all`. The library persists until `mexUnlock()` is called enough times to balance the locks, allowing static variables inside your C code to maintain state across multiple function calls.