what's wrong with my mex-file? - c

I'm trying to learn about matlab and mex files and wrote the following very simple code written in C to be called by matlab:
#include "mex.h"
void aplusb(int x, int y, int *z)
{
z=x+y;
}
void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
{
int *x;
int *y;
int *z;
if(nrhs<2)
{
mexErrMsgIdAndTxt( "MATLAB:aplusb:invalidNumInputs", "Need 2 values to sum");
}
else if(nlhs>2)
{
mexErrMsgIdAndTxt( "MATLAB:aplusb:invalidNumInputs", "Need one value to return.");
}
z = mxGetPr(plhs[0]);
x = mxGetPr(prhs[0]);
y = mxGetPr(prhs[1]);
aplusb(x,y,z);
}
Problem
I can compile correctly the code with mex aplusb.c. Just some warnings are returned:
aplusb.c:5:4: warning: assignment makes pointer from integer without a cast
aplusb.c: in function ‘mexFunction’:
aplusb.c:25:5: warning: assignment from incompatible pointer type
aplusb.c:26:5: warning: assignment from incompatible pointer type
aplusb.c:27:5: warning: assignment from incompatible pointer type
but when i run the .m file which calls the .c file matlab crashes with segmentation violation.
What is wrong with my code if it compiled OK?

There are several problems :
in aplusb, it should be *z=x+y;
do not pass pointers when calling the method : aplusb(*x,*y,z);
change the signature of aplusb to this : void aplusb(double x, double y, double *z) - after all you are passing pointer to double, and the compiler can not convert double* to int*
change x, y and y to be double* - not int*. mxGetPr returns double* and the compiler can not convert double* to int*

What's wrong
In aplusb you assign the sum of two ints to a pointer z, rather than *z.
You cannot access an output argument mxGetPr(plhs[0]) without allocating it first.
mxGetPr returns pointers to double and not int. You cannot cast a pointer to double to a pointer to int: you can only cast doubles to ints.
Fixing it
The function mxGetPr returns a pointer to the underlying double array represented by mxArray.
Therefore,
int * x = mxGetPr( prhs[0] );
is WRONG: x points to a 64bits in memroy that represent a floating point number,
but when you access it as *x you are telling the compiler to "read" these 64bits as 32bits integer.
One more thing: you have to create the output argument plhs[0]!
The correct way is
double * x = mxGetPr(prhs[0]);
double * y = mxGetPr(prhs[1]);
int z;
aplusb( *x /* cast double to int*/, *y /* cast double to int*/, &z ); // pass double and not poiners to double!
// allocate output
plhs[0] = mxCreateDoubleMatrix(1, 1, mxREAL);
double *out = mxGetPr( plhs[0] );
out[0] = z; // cast int to double
What can you do?
In order to use this example for learning, you should debug the mex file.
How to do that? Just follow the instructions here.
See if you can spot all the troubles by yourself using the debuger - this is the best way to learn.

Here is an example implementation:
myadd.c
#include "mex.h"
void myadd(double x, double y, double *z)
{
*z = x + y;
}
void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
{
double x, y, z;
/* Check for proper number of arguments. */
if(nrhs!=2) {
mexErrMsgIdAndTxt("mex:invalidNumInputs", "Two inputs required.");
} else if(nlhs>1) {
mexErrMsgIdAndTxt("mex:maxlhs", "Too many output arguments.");
}
/* Check for correct inputs. */
if( !mxIsDouble(prhs[0]) || !mxIsDouble(prhs[1]) ||
mxIsComplex(prhs[0]) || mxIsComplex(prhs[1]) ||
mxGetNumberOfElements(prhs[0])!=1 ||
mxGetNumberOfElements(prhs[1])!=1) {
mexErrMsgIdAndTxt("mex:inputNotRealScalarDouble",
"Inputs must be noncomplex scalar doubles.");
}
/* extract input */
x = mxGetScalar(prhs[0]);
y = mxGetScalar(prhs[1]);
/* call subroutine */
myadd(x, y, &z);
/* assign output */
plhs[0] = mxCreateDoubleScalar(z);
}
MATLAB
>> mex myadd.c
>> myadd(10,20)
ans =
30
Note that I added proper checks on the type of the input arguments (scalar non-complex doubles). This avoids crashing MATLAB if the input is otherwise.
Also I showed how to simplify the code by using "scalar" version of the MX functions, which bypasses the pointers.

Related

Passing a function with array parameter as a parameter to another function

I am trying to calculate the Jacobian matrix (numerical, at a given point) of a given equation. Now, I don't know the dimension of the equation beforehand, so I can't just do something like
static double f(double x1, x2)
{
return x1 * x1 - 2 * x1 * x2;
}
so instead, I am getting the input values as an array like so
static double f(double xArray[])
{
return xArray[0] * xArray[0] - 2 * xArray[1] * xArray[0];
}
void jacobian(double xArray[], double jacob_matrix, size_t size,
double f(double xArray[], size_t))
{
// calculations
}
However, when I try to call the function from main like
int main(void)
{
double x_input[4] = {1., 1., 3., 4.};
double jacob_matrix[4];
jacobian(x_input, jacob_matrix, 4, f(x_input, 4));
return 0;
}
I get incompatible type for argument 4 of 'jacobian' I imagine this has to do with my array being casted into a pointer, but I can't figure out how to fix this.
You need to pass the function pointer to f, not the result of calling f.
Try:
jacobian(x_input, jacob_matrix, 4, f);
For the function signature:
void jacobian(double xArray[], double jacob_matrix, size_t size,
double f(double xArray[], size_t))
For the second argument, if you're going to pass an array you need the argument to be a pointer, double* jacob_matrix or double jacob_matrix[].
For the 4th argument, the passed function arguments should match the caller signature, so in your case you are passing a function which is of type double (*)(double *), but the caller expects a function of type double (*)(double *, size_t), so one of them should be changed to match, either add a second argument to the called function, or remove the second argument of the caller function signature.
#include <stdio.h>
static double f(double xArray[])
{
return xArray[0] * xArray[0] - 2 * xArray[1] * xArray[0];
}
void jacobian(double xArray[], double* jacob_matrix, size_t size,
double f(double xArray[]))
{
printf("%f", f(xArray)); // for example
}
int main(void)
{
double x_input[4] = {1., 1., 3., 4.};
double jacob_matrix[4];
jacobian(x_input, jacob_matrix, 4, f);
return 0;
}
Note that my approach only addresses the code correctness and not the mathematical part, i.e. the jacobian calculation.

Passing another type to a function that takes a void pointer argument

I'm using the GNU Scientific Library which has functions that use void pointers as input. Example:
struct my_f_params { double a; double b; double c; };
double
my_f (double x[], size_t dim, void * p) {
struct my_f_params * fp = (struct my_f_params *)p;
if (dim != 2)
{
fprintf (stderr, "error: dim != 2");
abort ();
}
return fp->a * x[0] * x[0]
+ fp->b * x[0] * x[1]
+ fp->c * x[1] * x[1];
}
gsl_monte_function F;
struct my_f_params params = { 3.0, 2.0, 1.0 };
F.f = &my_f;
F.dim = 2;
F.params = &params;
I understand this to be defining my_f as a function that takes three arguments, one of which is the void pointer *p. My problem is instead of *p, I want to use a single variable which ranges from -5 to +5. The obvious thing to do is to use a for loop, but the following doesn't run:
float phi;
for (phi = -5.0; phi < 4.5; phi += 0.5) {
gsl_monte_function G = { &integrator, dim, phi };
[some code to tell the integrator to integrate]
}
The compiler complains that phi isn't a void pointer. The closest I got to fixing this was to try to convert the type, e.g. with *(float*)phi instead of phi, but it doesn't work - it returns an error saying "invalid cast from type ‘float’ to type ‘float*’". I tried Googling for this but nobody seems to have had this exact problem. What can I do other than repeat the code one time for each value of phi (which works but is very inelegant)?
I understand this to be defining my_f as a function that takes three arguments, one of which is the void pointer *p. My problem is instead of *p , I want to use a single variable which ranges from -5 to +5.
You must realize one thing: What *p is is a struct of 3 doubles, regardless of what you send. Look at your function definition. It is treated as a struct holding 3 doubles. This would be similar to something like this: double m[3]; as it would get casted properly to what you need.
So obviously just sending in phi as a float isn't going to cut it. The way to send it in as a parameter properly with casting is the following: (void *)&phi.
Here's a little example code to help you understand: Sample

expected ‘double (*)(double)’ but argument is of type ‘double’ in C

I need help, am trying to calculate the integral of a function using trapezoidal rule in C.
I am trying to use a function as a variable in another function but I am having issues compiling, it gives the same message as the title.
Here's then Code
#include <stdio.h>
#include <math.h>
double test(double x){
return pow(x,2);
}
double tarpez(double a,double b, int n, double (*test)(double )){
/*x[n] represents the parameter
y[n] respresents the parameter ,a initial x,
h is the length of divided spaces*/
double h,x[n],y[n],So,Se;//So-- sum of odd, Se- ...even
h = (b-a)/n;
if (n%2==1){
n+=1;
}
for (int i ; i<=n;i++){
x[i]= a+i*h;
y[i] = test(x[i]);
printf("%lf\n",y[i] );
}
}
int main(void){
double x,a,b,fn;
int n;
fn =
tarpez(a,b,n,test(x));
}
Primo, double (*test)(double ) is type name like int or float. So you need declare double (*test)(double ) foo where foo is variable name (like int n).
Sceundo, name of type can't be name of function. Pointer of function need return tupe, args types and no-reserved name. So try double (*custom_name)(double ).
Tertio, in main function no tarpez(a,b,n,test(x)). Use tarpez(a,b,n,test); You use only name in this space.
PS
Try use typedef.

Function Arguments in C

I'm totally new to C. Here's the question:
Write the function
fzero(double f(double),double x1, double x2)
as we did in class and use it to find all the solutions of
sin( pi*x / (1+x^2) ) = 0.25.
Now, I don't want you to solve the this. I'd missed this lecture and only want to understand what means
double f(double);
In that context, it means that f is a function pointer to a function to that takes one double argument, and returns a double.
As an example:
void foo(double f(double))
{
double y = f(3.0); // Call function through function pointer
printf("Output = %f\n", y); // Prints "Output = 9.0000"
}
double square(double x)
{
return x*x;
}
int main(void)
{
foo(&square); // Pass the address of square()
}
Note that there are two syntaxes for function pointers:
void foo(double f(double))
void foo(double (*f)(double))
These are equivalent.

how to pass element of array as argument to function for it to modify, in ANSI C program?

I understand how to pass an array to a function and let that function update the value of the array. I'm having a tough time understanding how to pass an ELEMENT of an array to a function and have that function update that element. My guess is as below, but produces the following from gcc: "warning: conflicting types for 'CDivide'".
The main() function defines the arrays in question, and passes them (as reference) to fn_v1p0 as complex_real and complex_imag, where they're declared as pointers in the function definition for fn_v1p0. The main() includes prototypes for these functions, as follows.
void fn_v1p0(double *, double *, char *, double *, unsigned int, double *);
void CDivide(double *, double *, double, double, double, double);
However, the main() sits in one file and the other two functions sit in a different file. Only the main file includes these prototypes.
I need to perform complex division (not supported in ANSI C), which is the purpose of function CDivide. There's more to the fn_v1p0 function, but I reduced it to only what's necessary to show for this question.
I've treated complex_real[ii] as simply a double value, hoping that if I put an & in front of it then CDivide could be written as shown. But my guess isn't working. Not sure what's the best way to tackle this.
void fn_v1p0(
double *complex_real, double *complex_imag,
char *selected_form,
double *freq,
unsigned int len_freq,
double *Hparams)
{
int ii = 0;
double a0, b0;
for (ii = 0; ii <= len_freq; ii++) {
CDivide( &complex_real[ii], &complex_imag[ii], b0, 0, a0, freq[ii] );
}
}
where
void CDivide(
double *z_real, double *z_imag, double a, double b, double c, double d)
{
double divisor = c*c + d*d;
*z_real = (a*c + b*d) / divisor;
*z_imag = (b*c - a*d) / divisor;
}
The problem was the prototype for the CDivide function needs to reside in the file containing the CDivide and fn_v1p0 definitions, and not the file containing the main() function. Moving the prototype for CDivide to the file containing CDivide clears the error. Thanks to Adam Rosenfield for flushing out the issue with his comments in the question above.
Take 2 functions double CDivide_real(a,b,c,d) and CDivide_imag(a,b,c,d) or pass a double-pointer-array to CDivide like CDivide(double *x[2],a,b,c,d), and then
for (ii = 0; ii <= len_freq; ii++) {
double *a[]={&complex_real[ii],&complex_imag[ii]};
CDivide( a, b0, 0, a0, freq[ii] );
}
and in CDivide
void CDivide(
double *x[2], double a, double b, double c, double d)
{
double divisor = c*c + d*d;
*x[0] = (a*c + b*d) / divisor;
*x[1] = (b*c - a*d) / divisor;
}

Resources