Arrays from c to matlab.
Show older comments
Hello everyone! This is my first time asking anything. I am trying to create a c file, call it "dostuff". This function dostuff(x,y) has 2 inputs and one output. one of those 2 inputs is the number of points which i need to work with. I have then to create a matrix with x columns and x rows in c and return this matrix (that i have already elaborated in c) back to matlab. I already wrote the code in c, and compiled with minGW from cmd and it works exactly as i wanted to. My problem is that i can't seem to find a way to return a vector or a matrix to matlab without it crashing. I'll send the code (in c) that i am trying to use to elaborate input and outputs:
void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]){
// Create the pointer used in findmax function
double *p;
double *v;
double *connected_to;
// Define the output size (time_spent size)
v=mxGetPr(V);
/* Create a matrix for the return argument */
CONNECTIONS=mxCreateDoubleMatrix(1,(*v)*(*v), mxREAL);
/* Assign pointers to the various parameters */
// mxGetPr(mxArray) get the pointer of an mxArray element
p=mxGetPr(P);
connected_to=mxGetPr(CONNECTIONS);
/* Call the function previously defined */
dostuff(connected_to,v,p);
return;
My matlab code ha to enter v and p wich are the number of points and a probability, and i have to return the adjacency matrix of those given number of points. Matlab crashes everytime i try to run this mex function.
8 Comments
dpb
on 10 Aug 2019
uppercase V,P aren't defined, only lowercase v, p pointers for starters.
My C is exremely rusty but I always start with one of the working examples that does something similar to what want -- in this case return uninitalized array back to ML -- the example mxcreateuninitnumericmatrix does that (albeit with internal #define for the size, but other examples show passing the numeric values...or there may be an actual example that does that as well--they've modified the examples quite a bit since I last looked much...and being mostly Fortran, what mex I do is generally not C.
Roberto Neri
on 10 Aug 2019
James Tursa
on 10 Aug 2019
Edited: James Tursa
on 10 Aug 2019
We need to see the dostuff code. And also a sample of how you are calling this mex routine. I don't see anything wrong with what you have posted, except that it is not robust against improper inputs (and this could be the cause of a crash).
Roberto Neri
on 11 Aug 2019
Edited: Roberto Neri
on 11 Aug 2019
Bruno Luong
on 11 Aug 2019
for(int i=0;i<*v;i++){
matrix[i]=(double*)malloc((*v)*sizeof(double));
}
matrix=(double**)malloc((*v)*sizeof(double));
I think you do in the reverse order.
Roberto Neri
on 11 Aug 2019
Bruno Luong
on 11 Aug 2019
Edited: Bruno Luong
on 11 Aug 2019
And to be correct you should allocate with pointer size (which is incidently sameas sizeof(double) on 64-bit platform
matrix=(double**)malloc((*v)*sizeof(double*));
Roberto Neri
on 11 Aug 2019
Answers (1)
James Tursa
on 11 Aug 2019
0 votes
v is pointer-to-double, *v is double. Everywhere inside generation() that you use v it needs to be *v instead.
9 Comments
Roberto Neri
on 11 Aug 2019
Bruno Luong
on 11 Aug 2019
Edited: Bruno Luong
on 11 Aug 2019
If you want to get help to spot the error, you better post the whole code, and not truncated, copy/past.
Roberto Neri
on 11 Aug 2019
Bruno Luong
on 11 Aug 2019
But why you do malloc and complicate your life? Just fill directly the Pr pointer of the mxArray you have created.
Idem for create and filling 2D C array MATRIX. You just make your life more complicated.
If you want to ask, you have to post have you call dostuff, what is the input argument what is the output, etc...
Don't hide us the details, it is just wasting time for anyone to guess.
Roberto Neri's "Answer" moved here:
Here is the full code:
#include <math.h>
#include <time.h>
#include <stdlib.h>
#include <stdio.h>
#include "mex.h"
#include "matrix.h"
#define V prhs[0]
#define P prhs[1]
#define CONNECTIONS plhs[0]
double rand_double(){
return (double)rand()/RAND_MAX;
}
static void generation(double *connected_to,double *v, double *p){
srand((unsigned)time(NULL));
array=(double*)malloc((*v)*sizeof(double));
matrix=(double**)malloc((*v)*sizeof(double*));
for(int i=0;i<*v;i++){
matrix[i]=(double*)malloc((*v)*sizeof(double));
}
for(int i=0;i<*v;i++){
for(int j=i;j<*v;j++){
if(i==0||j==0){
matrix[i][j]=1;
matrix[j][i]=1;
}else if(i==j){
matrix[i][j]=1;
}else if(rand_double()<*p){
matrix[i][j]=1;
}else{
matrix[i][j]=0;
matrix[j][i]=0;
}
}
}
for(int i=0;i<*v;i++){
array[i]=0;
}
connected_to=(double*)mxMalloc((*v)*(*v)*sizeof(double));
for (int i=0;i<*v; i++){
for (int j=0;j<*v;j++){
connected_to[i+((int)*v)*j] = matrix[i][j];
}
}
return;
}
void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]){
double *p;
double*v;
double*connect;
v=mxGetDouble(V);
p=mxGetDouble(P);
CONNECTIONS=mxCreateDoubleMatrix((int)*v,(int)*v, mxREAL);
connected_to=mxGetDouble(CONNECTIONS);
generation(connect,v,p);
return;
}
as i said, [a]=dostuff(b,c) needs to create a square matrix bxb and fill it with ones or zeros if the condition signed above is correct. It's just homework for a student. Main problem is that the matrix do[es]n't have a standard size, it could be any number (because b has to be a positive integer) and i didn't [k]no[w] other way than malloc to create matrix of variable sizes in C. Yes i had to do it this way, like i said it's homework. The algorithm functions well, i have tried it in C and it does exactly what i wanted it to. I don't know how to connect the C algorithm to Matlab returning a matrix.
Bruno Luong
on 11 Aug 2019
Edited: Bruno Luong
on 11 Aug 2019
Correction of your code. I put the change where there is my name in the comments.
#include <math.h>
#include <time.h>
#include <stdlib.h>
#include <stdio.h>
#include "mex.h"
#include "matrix.h"
#define V prhs[0]
#define P prhs[1]
#define CONNECTIONS plhs[0]
double rand_double(){
return (double)rand()/RAND_MAX;
}
static void generation(double *connected_to,double *v, double *p){
double *array, **matrix;
srand((unsigned)time(NULL));
array=(double*)malloc((*v)*sizeof(double));
matrix=(double**)malloc((*v)*sizeof(double*));
for(int i=0;i<*v;i++){
matrix[i]=(double*)malloc((*v)*sizeof(double));
}
for(int i=0;i<*v;i++){
for(int j=i;j<*v;j++){
if(i==0||j==0){
matrix[i][j]=1;
matrix[j][i]=1;
}else if(i==j){
matrix[i][j]=1;
}else if(rand_double()<*p){
matrix[i][j]=1;
matrix[j][i]=1; /* Add by Bruno Luong */
}else{
matrix[i][j]=0;
matrix[j][i]=0;
}
}
}
for(int i=0;i<*v;i++){
array[i]=0;
}
/*connected_to=(double*)mxMalloc((*v)*(*v)*sizeof(double));*/ /* Remove by Bruno Luong */
for (int i=0;i<*v; i++){
for (int j=0;j<*v;j++){
connected_to[i+((int)*v)*j] = matrix[i][j];
}
}
for(int i=0;i<*v;i++){
free(matrix[i]);/* Add by Bruno Luong */
}
free(matrix);/* Add by Bruno Luong */
free(array);/* Add by Bruno Luong */
return;
}
void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]){
double *p;
double*v;
double*connected_to;
v=mxGetDoubles(V);
p=mxGetDoubles(P);
CONNECTIONS=mxCreateDoubleMatrix((int)*v,(int)*v, mxREAL);
connected_to=mxGetDoubles(CONNECTIONS);
generation(connected_to,v,p); /* Change to connected_to connected_to */
return;
}
Roberto Neri
on 11 Aug 2019
Bruno Luong
on 11 Aug 2019
Replace it with mxGetPr
In your original code there is mxGetDouble (without "s"), this is unknown to me so I suppose there is a typo.
Roberto Neri
on 11 Aug 2019
Categories
Find more on Write C Functions Callable from MATLAB (MEX Files) in Help Center and File Exchange
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!