1

I need help initialising and using custom C structs in MATLAB. My goal is to write MATLAB code utilising external C structures and functions. The resulting MATLAB code with these C structures will be automatically converted into C by MATLAB Coder. I'm following this example (Please see the section entitled "Integrate External Code that Uses Custom Data Types"), but unfortunately the Coder gives me the following error:

Non-constant expression or empty matrix.
This expression must be constant because its value determines the size or class of some expression.
Error in ==> calc_length_c Line: 23 Column: 35

I believe my problem lies in the incorrect usage of coder.cstructname, struct and coder.opaque. To (auto)generate the C code with MATLAB Coder I use the following command:

codegen calc_length_c -args {0.1, 0.2, 0.3, 1.5, 1.7, 1.9} -report vector.c

MATLAB code, file calc_length_c.m:

function [l] = calc_length_c(p0x, p0y, p0z, p1x, p1y, p1z) %#coder
%CALC_LENGTH Calculates vector length
%   Calculates vector length. Vector is given by two points in Cartesian 3D space.

% include statements
coder.cinclude('vector.h');

% declare custom C datatypes
coder.cstructname(p0, 'point', 'extern', 'HeaderFile', 'vector.h');
coder.cstructname(p1, 'point', 'extern', 'HeaderFile', 'vector.h');
coder.cstructname(v, 'vector', 'extern', 'HeaderFile', 'vector.h');

% initialise points
p0 = struct('x', 0.0, 'y', 0.0, 'z', 0.0);
p1 = struct('x', 0.0, 'y', 0.0, 'z', 0.0);
v  = struct('p0', p0, 'p1', p1);

% initialise points
p0 = coder.ceval('create_point', p0x, p0y, p0z);
p1 = coder.ceval('create_point', p1x, p1y, p1z);

% initialise vector
v = coder.opaque('create_vector', p0, p1);  % <- error occurs here!

% calculate vector length
l = 0.0;
l = coder.opaque('calc_length', v);
end

C code, file vector.c:

#include <math.h>
#include "vector.h"

// Creates point in 3D Cartesian space
struct point create_point(double x, double y, double z) {
    
    struct point p;

    p.x = x;
    p.y = y;
    p.z = z;

    return p;
}

// Creates vector in 3D Cartesian space, defines origin and end points
struct vector create_vector(struct point p0, struct point p1) {

    struct vector v;

    v.p0 = p0;
    v.p1 = p1;

    return v;
}

// Calculates length of vector in 3D Cartesian space
double calc_length(struct vector v) {
    return sqrt( pow(v.p1.x-v.p0.x, 2.0) +
                 pow(v.p1.y-v.p0.y, 2.0) +
                 pow(v.p1.z-v.p0.z, 2.0) );
}

C code, file vector.h:

// Definition of point in 3D Cartesian space
struct point {
    double x;
    double y;
    double z;
};

// Definition of vector in 3D Cartesian space
struct vector {
    struct point p0;
    struct point p1;
};

// Routine signatures
struct point create_point(double x, double y, double z);
struct vector create_vector(struct point p0, struct point p1);
double calc_length(struct vector u);

1 Answer 1

1

If create_vector is a function, you want to call that with coder.ceval. The function coder.opaque can be thought of as being used just for type declarations.

Based on your code, you've already pre-initialized v as a struct and used coder.cstructname on it. So just switch that coder.opaque to a coder.ceval and you should be in business. The same goes for the later reference to calc_length.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.