Use C/C + + to read and write mat file (Clion)

Posted by rpmorrow on Sun, 06 Mar 2022 11:39:17 +0100

Use C/C + + to read and write mat file (Clion)

Recently, I need to use C + + to process the data generated by matlab. I refer to some online blogs, but they all use VS. I prefer to use Clion. I also encountered some pits in the process of configuration. Please record.

1, Create project and add test code

Let's not talk about creating a project. Note that the compilation tool chain I use is MinGW. The test code refers to the official program of matlab: Read the MAT file written in C/C + + - matlab & SIMULINK - MathWorks China , the official code has been slightly adjusted.

Replace the path in the program with the full address of your mat file.

#include <cstdio>
#include "mat.h"

const char *path = "D:\\Codes\\MATLAB\\test.mat";

int diagnose(const char *file) {
    MATFile *pmat;
    const char **dir;
    const char *name;
    int ndir;
    int i;
    mxArray *pa;

    printf("Reading file %s...\n\n", file);

    /*
     * Open file to get directory
     */
    pmat = matOpen(file, "r");
    if (pmat == NULL) {
        printf("Error opening file %s\n", file);
        return (1);
    }

    /*
     * get directory of MAT-file
     */
    dir = (const char **) matGetDir(pmat, &ndir);
    if (dir == NULL) {
        printf("Error reading directory of file %s\n", file);
        return (1);
    } else {
        printf("Directory of %s:\n", file);
        for (i = 0; i < ndir; i++)
            printf("%s\n", dir[i]);
    }
    mxFree(dir);

    /* In order to use matGetNextXXX correctly, reopen file to read in headers. */
    if (matClose(pmat) != 0) {
        printf("Error closing file %s\n", file);
        return (1);
    }
    pmat = matOpen(file, "r");
    if (pmat == NULL) {
        printf("Error reopening file %s\n", file);
        return (1);
    }

    /* Get headers of all variables */
    printf("\nExamining the header for each variable:\n");
    for (i = 0; i < ndir; i++) {
        pa = matGetNextVariableInfo(pmat, &name);
        if (pa == NULL) {
            printf("Error reading in file %s\n", file);
            return (1);
        }
        /* Diagnose header pa */
        printf("According to its header, array %s has %d dimensions\n",
               name, mxGetNumberOfDimensions(pa));
        if (mxIsFromGlobalWS(pa))
            printf("  and was a global variable when saved\n");
        else
            printf("  and was a local variable when saved\n");
        mxDestroyArray(pa);
    }

    /* Reopen file to read in actual arrays. */
    if (matClose(pmat) != 0) {
        printf("Error closing file %s\n", file);
        return (1);
    }
    pmat = matOpen(file, "r");
    if (pmat == NULL) {
        printf("Error reopening file %s\n", file);
        return (1);
    }

    /* Read in each array. */
    printf("\nReading in the actual array contents:\n");
    for (i = 0; i < ndir; i++) {
        pa = matGetNextVariable(pmat, &name);
        if (pa == NULL) {
            printf("Error reading in file %s\n", file);
            return (1);
        }
        /*
         * Diagnose array pa
         */
        printf("According to its contents, array %s has %d dimensions\n",
               name, mxGetNumberOfDimensions(pa));
        if (mxIsFromGlobalWS(pa))
            printf("  and was a global variable when saved\n");
        else
            printf("  and was a local variable when saved\n");
        mxDestroyArray(pa);
    }

    if (matClose(pmat) != 0) {
        printf("Error closing file %s\n", file);
        return (1);
    }
    printf("Done\n");
    return (0);
}

int main() {

    int result;

    result = diagnose(path);

    if (!result) {
        printf("SUCCESS!\n");
    } else {
        printf("FALURE!\n");
    }

    return 0;
}

2, Modify CmakeLists file

Set include path (equivalent to adding additional include directory in VS):

set(INC_DIR1 E:\\MATLAB\\R2019b\\extern\\include)
set(INC_DIR2 E:\\MATLAB\\R2019b\\extern\\include\\win64)

# head file path
include_directories(${INC_DIR1}) # Specify the search path of the header file, which is equivalent to specifying the - I parameter of gcc
include_directories(${INC_DIR2}) # Specify the search path of the header file, which is equivalent to specifying the - I parameter of gcc

Set the Library Directory (equivalent to adding additional libraries in VS) and the libraries to be included (equivalent to adding additional dependent libraries in VS):

set(LINK_DIR E:\\MATLAB\\R2019b\\extern\\lib\\win64\\mingw64
link_directories(${LINK_DIR}) # The search path of dynamic link library or static link library is equivalent to the - L parameter of gcc
link_libraries(libmat libmx libmex libeng) # All targets link with the same set of libs

Here is the complete content of my CmakeLists file:

cmake_minimum_required(VERSION 3.21)
# project name: Specifies the name of the project, which generally corresponds to the folder name of the project
project(read_mat)

# Set parameters
set(CMAKE_CXX_STANDARD 14)

set(INC_DIR1 E:\\MATLAB\\R2019b\\extern\\include)
set(INC_DIR2 E:\\MATLAB\\R2019b\\extern\\include\\win64)

set(LINK_DIR E:\\MATLAB\\R2019b\\extern\\lib\\win64\\mingw64)

# head file path
include_directories(${INC_DIR1}) # Specify the search path of the header file, which is equivalent to specifying the - I parameter of gcc
include_directories(${INC_DIR2}) # Specify the search path of the header file, which is equivalent to specifying the - I parameter of gcc

link_directories(${LINK_DIR}) # The search path of dynamic link library or static link library is equivalent to the - L parameter of gcc

link_libraries(libmat libmx libmex libeng) # All targets link with the same set of libs

cmake_minimum_required(VERSION 3.21)

add_executable(read_mat main.cpp)

3, Add environment variable

Add the following environment variables and pay attention to replacing the matlab installation address.

E:\MATLAB\R2019b\bin\win64
E:\MATLAB\R2019b\extern\lib\win64\mingw64

Remember to restart the computer after adding environment variables.

After the restart is completed, for some people, the whole configuration is completed and the program can be run. But some people, such as myself, make the following errors when running:

Process finished with exit code -1073741515 (0xC0000135)

If you encounter such an error, please continue to look below.

4, A bald mistake

For the above error, I tried to search on the Internet, but I couldn't find a solution. Then I used VS to configure it again. The program still failed to run, and the following errors were encountered:

Unable to locate program input point H5Rdereference Apply to dynamic link library libmat.dll upper

Then I found the solution to the problem in a big man's blog. You can see the original text of the blogger, Unable to locate the program input point H5Rdereference in the dynamic link library libmat DLL_ sinat_36156541 blog - CSDN blog , the reason for this problem is the conflict between dll dynamic libraries. I added Anaconda's environment variable and hdf5.0 in anaconda dll file, the program first locates Anaconda's dll file, not matlab's dll file. The way to solve the conflict is to move Anaconda's environment variable to matlab's environment variable.

Remember to restart the computer after modifying the environment variables.

5, Operation results

After solving the previous problems, run the program again and you can see that it is successful. The program output results are as follows:

Directory of D:\Codes\MATLAB\DP-TBD\matlab_code\test.mat:
matrix

Examining the header for each variable:
According to its header, array matrix has 2 dimensions
  and was a local variable when saved

Reading in the actual array contents:
According to its contents, array matrix has 2 dimensions
  and was a local variable when saved
Done
SUCCESS!

Process finished with exit code 0

reference resources

C + + read and write mat file_ Jim Ye's column - CSDN blog_ matopen

[C + +, Matlab] VS2013 C + + reading and writing mat file_ No, sir's blog - CSDN blog_ matopen

Read the MAT file written in C/C + + - matlab & SIMULINK - MathWorks China

Unable to locate the dynamic linker entry point for r5hreference.lib DLL_ sinat_36156541 blog - CSDN blog

Topics: C C++ MATLAB