Azzera filtri
Azzera filtri

"Incompatible types" error while loading C function that returns a pointer to array using codegen

31 visualizzazioni (ultimi 30 giorni)
Hello,
I'm new to codegen and trying to load a custom C function to MATLAB in order to create a mex. The C code implements an averaging filter and is already tested that it serves the intended purpose (in C). However, when trying to load the function to MATLAB, I get the following errors:
C:/Users/felrodri/source/repos/averaging_filter_test/Averaging_filter_header.h:7:9: error: conflicting types for 'averaging_filter'
float * averaging_filter(float x[5]);
^~~~~~~~~~~~~~~~
In file included from C:/Users/felrodri/Documents/MATLAB/tutorials/codegen/lib/averaging_filter/averaging_filter1.c:13:0:
C:/Users/felrodri/Documents/MATLAB/tutorials/codegen/lib/averaging_filter/averaging_filter1.h:25:15: note: previous declaration of 'averaging_filter' was here
extern double averaging_filter(double x);
^~~~~~~~~~~~~~~~
C:/Users/felrodri/Documents/MATLAB/tutorials/codegen/lib/averaging_filter/averaging_filter1.c: In function 'averaging_filter':
C:/Users/felrodri/Documents/MATLAB/tutorials/codegen/lib/averaging_filter/averaging_filter1.c:23:27: warning: passing argument 1 of 'averaging_filter' from incompatible pointer type [-Wincompatible-pointer-types]
return averaging_filter(&x);
^
In file included from C:/Users/felrodri/Documents/MATLAB/tutorials/codegen/lib/averaging_filter/averaging_filter1.c:14:0:
C:/Users/felrodri/source/repos/averaging_filter_test/Averaging_filter_header.h:7:9: note: expected 'float *' but argument is of type 'double *'
float * averaging_filter(float x[5]);
^~~~~~~~~~~~~~~~
C:/Users/felrodri/Documents/MATLAB/tutorials/codegen/lib/averaging_filter/averaging_filter1.c:23:10: error: incompatible types when returning type 'float *' but 'double' was expected
return averaging_filter(&x);
^~~~~~~~~~~~~~~~~~~~
gmake: *** [averaging_filter1.obj] Error 1
The make command returned an error of 2
Error(s) encountered while building "averaging_filter"
The header file (.h) of the function is:
#pragma once
#ifndef C_H
#define C_H
#include <stdio.h>
float *averaging_filter(float x[1257]);
#endif
The function implementation (.c) is:
#include <stdio.h>
#include "averaging_filter_header.h"
float * averaging_filter(float x[5]) {
float y[5] = { 0. };
float buffer[3] = { 0. };
for (int i = 0; i < 5; i++) {
memcpy(buffer + 1, buffer, 2 * sizeof(float));
buffer[0] = x[i];
float sum = 0.;
for (int j = 0; j < 3; j++) {
sum += buffer[j];
}
y[i] = sum / 3.;
//printf("%f \n", y[i]);
}
return y;
}
The averaging_filter.m is:
function y = averaging_filter(x) %#codegen
y = zeros(size(x), class(x));
if coder.target('MATLAB')
%Execute interpreted MATLAB code
%persistent buffer;
%if isempty(buffer)
buffer = zeros(10, 1);
%end
%y = zeros(size(x), class(x));
for i = 1:numel(x)
buffer(2:end) = buffer(1:end-1);
buffer(1) = x(i);
y(i) = sum(buffer)/numel(buffer);
end
else
%generate C code using existing C Code:
coder.updateBuildInfo('addIncludePaths', 'C:\Users\felrodri\source\repos\averaging_filter_test');
coder.updateBuildInfo('addSourceFiles', 'Averaging_filter.c');
coder.cinclude('Averaging_filter_header.h');
fprintf("Running the C code...");
y = coder.opaque('pointer', '0', 'Size', 1257);
y = coder.ceval('averaging_filter', coder.ref(x));
end
end
And I'm using the following codegen command:
codegen -config:lib averaging_filter -args {0.} -report
  • To apply coder.ceval to a function that accepts or returns variables that do not exist in MATLAB code, such as pointers, FILE types for file I/O, and C/C++ macros, use the coder.opaque function.
But the examples do not include a pointer array and I'm not sure if the codegen command used is the correct one, so any guidance is appreciated.

Risposte (2)

Rasmita
Rasmita il 13 Apr 2023
Hi,
It is my understanding that, you are trying to load a custom C function to MATLAB to create a ‘mex’ and you are getting an error while loading due to the ‘averaging_filter’ function.
The error messages indicate that there are conflicting declarations of the ‘averaging_filter’ function. In the header file, the function is declared to take an array of float values and return a pointer to float. In the implementation file, the function is defined to take an array of float values and return an array of float.
Additionally, the MATLAB code is passing a double pointer to the ‘averaging_filter’ function, which expects a float pointer. To fix these issues, you can update the header file to match the implementation file and change the MATLAB code to pass a single precision array to the ‘averaging_filter’ function.
Here is the updated header file:
#pragma once
#ifndef C_H
#define C_H
#include <stdio.h>
float *averaging_filter(float x[5]);
#endif
Here is the updated implementation file:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "averaging_filter_header.h"
float * averaging_filter(float x[5]) {
float *y = (float*) malloc(5 * sizeof(float));
float buffer[3] = { 0. };
for (int i = 0; i < 5; i++) {
memcpy(buffer + 1, buffer, 2 * sizeof(float));
buffer[0] = x[i];
float sum = 0.;
for (int j = 0; j < 3; j++) {
sum += buffer[j];
}
y[i] = sum / 3.;
}
return y;
}
And here is the updated MATLAB code:
function y = averaging_filter(x) %#codegen
y = zeros(size(x), 'single');
if coder.target('MATLAB')
buffer = zeros(3, 1, 'single');
for i = 1:numel(x)
buffer(2:end) = buffer(1:end-1);
buffer(1) = x(i);
y(i) = sum(buffer)/numel(buffer);
end
else
coder.updateBuildInfo('addIncludePaths','C:\Users\felrodri\source\repos\averaging_filter_test');
coder.updateBuildInfo('addSourceFiles', 'Averaging_filter.c');
coder.cinclude('Averaging_filter_header.h');
y = coder.opaque('float *', 'NULL');
y = coder.ceval('averaging_filter', coder.ref(single(x)));
y = coder.ceval('reshape', y, [1, numel(x)]);
end
end
For more information, please refer to the below documentation links:
Hope this helps!
Regards,
Rasmita

Ryan Livingston
Ryan Livingston il 13 Apr 2023
I immediately see a few issues you need to solve:
  1. Your C code is broken because it returns a pointer into y which is a locally stack allocated variable. The usual idiom in C to return arrays via by-reference parameters void averaging_filer(float x[5], float y[5]). The caller then allocates space for the output and passes it in. This approach allows the generated code to properly manage the memory in the generated code.
function y = averaging_filter_matlab(x)
...SNIP...
% Allocate space for the output of the C function
y = zeros(size(x),'like',x);
coder.ceval('averaging_filter',coder.ref(x),coder.ref(y));
end
2. Your MATLAB function and C function have the same name so they clash in the generated C code. You should rename one of them like I did in the code snippet above with averaging_filter_matlab.m. That name clash is the source of the compiler error you receive.

Categorie

Scopri di più su Generating Code in Help Center e File Exchange

Prodotti


Release

R2021b

Community Treasure Hunt

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

Start Hunting!

Translated by