MATLAB Answers

how to call a custom C-mex from an Embedded MATLAB Function block in a Simulink model?

7 views (last 30 days)
I have been using cvxgen to generate a csolve.mexw32 file. If we have a matlab mfile(there-in-after) in which I call the mexw32 file, the operation of the program can be realized well, but failed in Embedded MATLAB Function block. Many errors have been made. How should I modify ?For more please see annex. Thanks, Xiwen
%if true
% code
%end
params.eta=.98;
params.kappac=.98;
params.kappad=.98;
params.Cmax=10;
params.Dmax=10;
params.C=50;
params.gamma=.02;
params.q_0=0;
params.p_0=1;
params.Q_t=ones(20);
params.b_t=ones(20,1);
params.q_t=ones(20,1);
params.s_t=ones(20,1);
params.x_t=ones(20,1);
for i=1:50, params.p{i}=rand(1)*10;
end
[vars, status]=csolve(params);

  0 Comments

Sign in to comment.

Accepted Answer

Alexander Bottema
Alexander Bottema on 8 Jul 2014
Hi yuan,
There are multiple problems in your example, so I'll enumerate the changes I've made.
First it is odd to call a MEX function from MATLAB Coder (formerly Embedded MATLAB). Normally you can call C functions directly using coder.ceval (formerly eml.ceval). However, it looks that the code you're calling is auto generated and someone has made an infrastructure to automatically generate MEX functions for MATLAB.
Using your function block code I rewrote it like this:
function [vars_u_t, vars_z_t, optval, gap, steps, converged]=myfcn(eta)
%#eml
params.eta=eta;
params.kappac=.98;
params.kappad=.98;
params.Cmax=10;
params.Dmax=10;
params.C=50;
params.gamma=.02;
params.q_0=0;
params.p_0=1;
params.Q_t=ones(20);
params.b_t=ones(20,1);
params.q_t=ones(20,1);
params.s_t=ones(20,1);
params.x_t=ones(20,1);
% MATLAB Coder don't support growing matrices through iteration
% (only by complete assignment). That's why we preallocate here.
params.p = zeros(50,1);
for i=1:50
params.p(i)=rand(1)*10;
end
% It's no longer called eml. (they are now all renamed to coder.)
% I don't touch this, becuase I don't know which version you're
% using.
eml.extrinsic('csolve_mex');
% We need to initialize these variables, because inference can
% not figure out the output types on extrinsic function calls.
status.optval = 0;
status.gap = 0;
status.steps = 0;
status.converged = 0;
vars.u_t = zeros(20, 1);
vars.z_t = zeros(20, 1);
[vars, status]=csolve_mex(params);
% To avoid Simulink bus types I extracted all elements in parts
vars_u_t = vars.u_t;
vars_z_t = vars.z_t;
optval = status.optval;
gap = status.gap;
steps = status.steps;
converged = status.converged;
Look at the comments and you'll see the changes I've made. To summarize:
1) I renamed the MEX function to csolve_mex because otherwise you get shadowing of csolve.m. MATLAB Coder in Simulink always use source files as precedence. Normally, you never call MEX functions in MATLAB Coder. You usually call C functions directly through coder.ceval and directly on native types (never through mxArrays and MEX API). Note that eml.extrinsic has been changed to csolve_mex, and I renamed the file csolve.mexw32 to csolve_mex.mexw32. (Actually mexw64 on my machine, but you get my point).
2) params.p(i) = ... You can see that I preinitialized that field. MATLAB Coder doesn't support growing except through complete assignment. To avoid this problem I preallocated the matrix before filling it.
3) If you use eml.extrinsic, then we don't analyze the function it calls, so it becomes impossible for us to figure out the MATLAB types. That's why you need to preinitialize the outputs before calling the extrinsic function (status.optval = 0; ...)
4) To avoid using Simulink buses I just ripped apart the structures into their parts. Then I just connected 5 scopes (one for each output).
I got this running on my machine after those changes. Whether the results are correct or not is beyond my knowledge.

  4 Comments

Show 1 older comment
Kai Wu
Kai Wu on 6 Mar 2018
Dear Alexander, I tried your method and encountered the current issue:
------------------------------------------------------------------------ Access violation detected at Tue Mar 06 00:40:37 2018 ------------------------------------------------------------------------
Configuration: Crash Decoding : Disabled - No sandbox or build area path Crash Mode : continue (default) Current Graphics Driver: Unknown hardware Default Encoding : windows-1252 Deployed : false Graphics card 1 : NVIDIA ( 0x10de ) NVIDIA Quadro K620 Version 21.21.13.7735 Host Name : NAME-2UA4301PKL MATLAB Architecture : win64 MATLAB Entitlement ID: 1837456 MATLAB Root : C:\Program Files\MATLAB\R2017a MATLAB Version : 9.2.0.538062 (R2017a) OpenGL : hardware Operating System : Microsoft Windows 10 Enterprise Processor ID : x86 Family 6 Model 60 Stepping 3, GenuineIntel Virtual Machine : Java 1.7.0_60-b19 with Oracle Corporation Java HotSpot™ 64-Bit Server VM mixed mode Window System : Version 10.0 (Build 16299)
Fault Count: 1
Abnormal termination: Access violation
I searched online and somebody said, "The reason for this error is that the current user doesn't have permission to access the XML file needed to use the Login Named User (LNU) feature." Any comments on this?
Thanks,
Kai
Kai Wu
Kai Wu on 6 Mar 2018
Dear Alexander, I found that the error is due to the use of array instead of cell array on p(i), but if i use cell array, Matlab says Code generation does not support cell arrays in structure fields
Alexander Bottema
Alexander Bottema on 7 Mar 2018
Hi Kai,
Can you provide a code excerpt, and what version are you running? Cell arrarys inside structures worked fine in R2017b (I even tried in R2016a.)
Thanks, Alexander

Sign in to comment.

More Answers (0)

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!