MATLAB Answers

1

Compile a C code on a Raspberry Pi with a library generated with Matlab C Coder

Asked by Mathias Blandeau on 17 Jul 2019
Latest activity Edited by Ryan Livingston on 27 Aug 2019
Hello,
I have trouble using the Matlab C coder app from a PC (windows 10) to my Raspberry Pi3 B V1.2
First a contextual explanation :
  1. I used to make measurements on the RPi then analyse it with matlab and now I want to do everything on the RPi
  2. My algorithm is not completely finished yet (eg: some thresholds needs to be tuned a bit) in the analyse code, so I wanted to keep a C code I could modify later on the Pi and not an executable that I had to change on matlab everytime I wish to make a change (I do not have regular access to this PC).
What was my goal before I had issues :
  1. Generating all the .c and .h files with matlab
  2. Compiling them in a static library in my RPi (eg: "libmylib.a" in Linux)
  3. Compiling the main.c file with the new library
So I used the Matlab C code generator with the following settings (I downloaded the addon from RaspberryPi harware):
Capture.PNG
I then I tranferred the created folder to my RPi to generate the library, I used the soft Code::Bocks (open source IDE) and this is where I met my first problem: 4 header files were missing to compile the static library : emlrt.h, matrix.h, mex.h and twmtypes.h
I managed to find them on my Matlab program folder but it is weird that they were not included in the first place in the folder generated my the C coder app.
Anyway after adding those 4 files in my library folder, I managed to compile the static library which gave me two important files, the library "libmylib.a" and the "main.o" which I tried to compile using the following bash commande
gcc main.o -Ldirmylib -lmylib -o myoutput
This command resulted in an error with undefined references to several functions and amongst them "sin", "cos", "floor", "ceil"...
So it seemed to me that the mathematic library ("libm.a") was not included (once again this is very surprising to me), I corrected this point by changing the command to
gcc main.o -Ldirmylib -lmylib -lm -o myoutput
Now the classic math functions are well-defined, but their is still and error and I cannot find the following functions :
In function« emlrt_marshallOut » :
« emlrtCreateNumericArray »
« emlrtMxSetData »
« emlrtSetDimensions »
« emlrtAssign »
In function« emxFree_real_T » :
« emlrtFreeMex »
In function« emxInit_real_T » :
emlrtMallocMex »
« emlrtPushHeapReferenceStackR2012b »
In function« myalgo_api » :
« emlrtHeapReferenceStackEnterFcnR2012b »
« emlrtHeapReferenceStackLeaveFcnR2012b »
In function« myalgo_atexit » :
« emlrtEnterRtStackR2012b »
« emlrtLeaveRtStackR2012b »
« emlrtDestroyRootTLS »
« mylib_xil_terminate »
« mylib_xil_shutdown »
« emlrtExitTimeCleanup »
In function« myalgo_initialize » :
« emlrtClearAllocCountR2012b »
« emlrtEnterRtStackR2012b »
« emlrtFirstTimeR2012b »
In function« myalgo_terminate » :
« emlrtLeaveRtStackR2012b »
« emlrtDestroyRootTLS »
In function« myalgo_mexFunction » :
« emlrtErrMsgIdAndTxt »
« emlrtErrMsgIdAndTxt »
« emlrtReturnArrays »
In function« mexFunction » :
« mexAtExit_800 »
In function« mexFunctionCreateRootTLS » :
« emlrtCreateRootTLS »
« makeComplexCXSparseMatrix » :
« cs_ci_spalloc »
In function« solve_from_lu_ci » :
« cs_ci_malloc »
« cs_ci_ipvec »
« cs_ci_lsolve »
« cs_ci_usolve »
« cs_ci_ipvec »
« cs_ci_free »
In function« solve_from_qr_ci » :
« cs_ci_calloc »
« cs_ci_ipvec »
« cs_ci_happly »
« cs_ci_usolve »
« cs_ci_ipvec »
« cs_ci_pvec »
« cs_ci_utsolve »
« cs_ci_happly »
« cs_ci_pvec »
« cs_ci_free »
collect2: error: ld returned 1 exit status
Does anyone know what to do in this situation ? I have a feeling that the Matlab C coder app does not do all the job (dur to the header files and math library missing)...
Thanks in advance
Mathias

  0 Comments

Sign in to comment.

1 Answer

Answer by Ryan Livingston on 19 Jul 2019
Edited by Ryan Livingston on 27 Aug 2019
 Accepted Answer

The generated code should not be depending on the headers emlrt.h, matrix.h etc. Those are only available when running in MATLAB not in standalone environments. What has likely happened is that you also copied the interface or sil subdirectory of the codegen directory. You don't need those directories, they are just used for MEX/SIL/PIL testing from MATLAB.
A simple way to package everything you need to deploy is to use the packNGo function or the Package button on the final step of the MATLAB Coder App:
Those package the generated code and all dependencies into a ZIP file that you can move to your other environment.
You can also check out this example:
that shows how to package code and move it to the Raspberry Pi using either packNGo or the Raspberry Pi support package.
Summary of comment section on compiling the generated sparse solver code
The generated code for this example uses a sparse matrix library to solve sparse systems and requires some flags to compile.
For GCC use the compiler flags:
gcc -DCS_COMPLEX -fopenmp *.c -o MyFunction -lm
to build the generated code for this example. -DCS_COMPLEX is needed by the sparse solver library. -fopenmp is needed when the generated code uses OpenMP for threading. Depending on your compiler, you may need to substitue a different OpenMP flag.

  7 Comments

Hi Mathia,
Yes, those are openmp functions. There are several toolbox functions using openmp. And those are default on when generate code.
Disable openmp is one solution, another will be add openmp flag to your build command.
gcc -DCS_COMPLEX -fopenmp *.c -o MyFunction -lm
DCS_COMPLEX defines CS_COMPLEX macro required by our sparse library.
Ok for the openmp function and the DCS_COMPLEX, thanks !
Do you think it is better to disable the openmp or add the flag in the build command ? Could it make a difference knowing that I did not intended the code to run in parallel ?
That really depends on your pi model and the code. Most pis have more than 1 core I think.
Anyway, my suggestion is do some simple tic toc benchmarks.
You can disable openmp through "More Settings"->"All Settings", search openmp, set it to No, and regenerate code.

Sign in to comment.