"Incompatible types" error while loading C function that returns a pointer to array using codegen
35 visualizzazioni (ultimi 30 giorni)
Mostra commenti meno recenti
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.
0 Commenti
Risposte (2)
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
0 Commenti
Ryan Livingston
il 13 Apr 2023
I immediately see a few issues you need to solve:
- 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.
0 Commenti
Vedere anche
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!