FindMATLAB: Support for R2018a complex-interleaved APIs
This is related to #17971 (closed). That issue didn't fully address the changes introduced in MATLAB R2018a.
R2018a had a major internal change in the way that complex arrays are stored. Before, they were stored as two data segments (one for the real component, one for the imaginary component). Since R2018a, they are stored "interleaved", i.e. in the way that all other software stores them.
This obviously has a huge impact on any MEX-file that uses complex arrays.
R2018a introduced two ways to compile MEX-files:
- A compatibility mode, which is enabled by default, but is ensured by adding the
-R2017b
argument to themex
command, in which old MEX-files continue working as before, but at the expense of an extra copy of any complex-valued array. - A new mode, enabled by adding the
-R2018a
argument to themex
command, in which the new interleaved-complex APIs are enabled. There are new functions in the C API, some other functions were retired, and some functions changed what they do.
These mex
arguments translate to defining a compiler macro as follows:
-
-R2017b
argument:MATLAB_DEFAULT_RELEASE=R2017b
-
-R2018a
argument:MATLAB_DEFAULT_RELEASE=R2018a
Furthermore, since R2016b, it is necessary to add one of the following source files to each MEX-file compiled. CMake currently doesn't do this.
-
matlabroot/extern/version/c_mexapi_version.c
- for C -
matlabroot/extern/version/cpp_mexapi_version.cpp
- for C++ -
matlabroot/extern/version/fortran_mexapi_version.F
- for FORTRAN
Source: https://www.mathworks.com/matlabcentral/answers/377799-compiling-mex-files-without-the-mex-command
I'm currently using the current CMake code to build MEX-files:
find_package(Matlab REQUIRED MX_LIBRARY MAIN_PROGRAM)
# Fix some stuff, CMake currently doesn't properly include the version source file, and doesn't work with R2018a and later.
set(MEX_VERSION_FILE "")
if(NOT ${Matlab_VERSION_STRING} VERSION_LESS "9.1") # For 9.1 (R2016b) and newer, add version source file
set(MEX_VERSION_FILE "${Matlab_ROOT_DIR}/extern/version/cpp_mexapi_version.cpp")
endif()
set(MEX_API_MACRO "")
if(NOT ${Matlab_VERSION_STRING} VERSION_LESS "9.4") # For 9.4 (R2018a) and newer, add API macro
set(MEX_API_MACRO "MATLAB_DEFAULT_RELEASE=R2017b")
#set(MEX_API_MACRO "MATLAB_DEFAULT_RELEASE=R2018a")
endif()
matlab_add_mex(NAME MEX_${target} SRC ${file} ${MEX_VERSION_FILE} OUTPUT_NAME ${target} LINK_TO DIP)
target_compile_definitions(MEX_${target} PRIVATE ${MEX_API_MACRO})
Note that the set(MEX_API_MACRO ...)
command to use could be selected through a user-settable variable. If R2018a is required, use set(MEX_API_MACRO "MATLAB_DEFAULT_RELEASE=R2018a")
, and ensure that the version of MATLAB used actually 9.4 or later. If R2017b is required, only use set(MEX_API_MACRO "MATLAB_DEFAULT_RELEASE=R2017b")
for R2018a or newer.