Build MEX Functions Without Using MATLAB

MEX functions are generally built using MATLAB’s “mex” command. However, we can also build MEX functions using open source toolchains. Cross-compilation is also possible. That is, we can build MEX functions for Windows using a Linux host. An example is given herein.

Extract Proprietary Files

Some proprietary files in MATLAB are required for building MEX functions. The required files (for Windows) include:

bin/win64/libmat.dll
bin/win64/libmex.dll
bin/win64/libmx.dll
extern/include/*

These files can be found in the installation directory of MATLAB. Copy them to the project folder.

Write MEX Functions

Create a simple MEX function:

#include "mat.h"
#include "matrix.h"
#include "mex.h"

DLL_EXPORT_SYM void mexFunction(int nlhs, mxArray* plhs[], int nrhs, const mxArray* prhs[])
{
	mexPrintf("helloworld\n");
}

Save it as “main.c”.

Compile

Compiled MEX functions are actually shared libraries with specific entry points. So we can compile MEX functions using any C/C++ toolchains.

Herein we use the Mingw-w64 toolchain. On Debian it can be installed with the following command:

sudo apt install mingw-w64

The executable is named “x86_64-w64-mingw32-gcc”.

We can compile the MEX Function using the following command:

x86_64-w64-mingw32-gcc                                        \
	-shared -fPIC -fno-omit-frame-pointer -fvisibility=hidden \
	-D'DLL_EXPORT_SYM=__attribute__((visibility("default")))' \
	-I./extern/include/                                       \
	-L./bin/win64 -lm -lmat -lmex -lmx                        \
	-DMATLAB_MEX_FILE                                         \
	main.c -o main.mexw64

Test that the compiled MEX function can be run (in Windows/MATLAB):

>> main
helloworld

Makefile for Larger Projects

If you have GNU make and GNU findutils, you can use the following Makefile to build MEX functions:

TARGET := output.mexw64

CC := x86_64-w64-mingw32-gcc

SRCS := $(shell find -name '*.c')
OBJS := $(addsuffix .o, $(basename $(SRCS)))
LIBS := $(shell find -name '*.dll' -printf '%h\n' | sort | uniq)

CFLAGS := -Wall -O3 -flto -ffunction-sections -fdata-sections
CFLAGS += -fPIC -fno-omit-frame-pointer -fvisibility=hidden
CFLAGS += -D'DLL_EXPORT_SYM=__attribute__((visibility("default")))'
CFLAGS += $(shell find -name '*.h' -printf '-I%h\n' | sort | uniq)
CFLAGS += -DMATLAB_MEX_FILE

LDFLAGS := -shared -s -Wl,-gc-sections -Wl,--as-needed
LDFLAGS += -L$(LIBS) -lm -lmat -lmex -lmx

all: $(TARGET)

%.o: %.c
	@echo 'CC $<'
	@SOURCE_DATE_EPOCH=0 $(CC) -c $< -o $@ $(CFLAGS)

$(TARGET): $(OBJS)
	@echo 'CC $@'
	@SOURCE_DATE_EPOCH=0 $(CC) $^ -o $@ $(LDFLAGS)

clean:
	@rm -f $(TARGET)
	@find -name '*.o' -delete

Reference

Compiling MEX Files without the mex Command