Arrays from c to matlab.

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
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.
Thanks a lot! I'll surely go cheking that function and see if i can understand something. I don't have choice, my teacher wanted me to do a C program that uses mex to graph data. I copied only a bit of the whole code, since i don't want help with the algorithm part. uppercase V,P are defined
#define V prhs[0]
#define P prhs[1]
#define CONNECTIONS plhs[0]
this way. Sorry if the thread wasn't clear.
James Tursa
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).
Thanks James, i am going to post some code right now:
static void generation(double *adjacency,double *v, double *p){//funzione che genera due vettori
srand((unsigned)time(NULL));
array=(double*)malloc((*v)*sizeof(double));
for(int i=0;i<*v;i++){
array[i]=0;
}
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{
matrix[i][j]=0;
matrix[j][i]=0;
}
}
}
I then elaborate matrix and array (sorry if i don't post the entire code, but it's homework and i like to do it myself where i can, the portion that i didn't posted is just some if like the one i posted above.
adjacency=(double*)mxMalloc((*v)*(*v)*sizeof(double));
for (int i=0;i<*v; i++){
for (int j=0;j<*v;j++){
adjacency[i+(int)*v*j] = matrix[i][j];
}
}
return;
}
This is the creation of array and matrix and the data that i should bring back (adjacency), i used this method because i didn't find a way to use directly matrix. Hope this helps more.
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.
Yes, sorry, i just made a mistake while editing the code to post it here. Sorry for that.
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*));
Thanks! i didn't noticed that bad error. But still it doesn't work.

Sign in to comment.

Answers (1)

James Tursa
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

Thank you! Just fixed it. I tried to run the program but the error persist. In some way matlab crashes when I run the mex.
Bruno Luong
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.
I'm sorry but I can't. I just don't know how to pass a matrix created with malloc back from C to Matlab. As I said in the main message: I have to create a function "dostuff" that has 2 input and one output. [A]=dostuff(b,C) has to create a matrix bxb and send it back to Matlab. Is it better if I ask you how to do this?
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.
Stephen23
Stephen23 on 11 Aug 2019
Edited: dpb on 11 Aug 2019
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.
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;
}
First things first, thank you a lot for your help and your patience. Unfortunately, it still return me an error, at least matlab didn't crashed.
Error using mex
C:\Users\rober\AppData\Local\Temp\mex_28873508655564_3724\new2.obj:new2.c:(.text+0x71):
undefined reference to `mxGetDoubles'
C:\Users\rober\AppData\Local\Temp\mex_28873508655564_3724\new2.obj:new2.c:(.text+0x7d):
undefined reference to `mxGetDoubles'
C:\Users\rober\AppData\Local\Temp\mex_28873508655564_3724\new2.obj:new2.c:(.text+0x9d):
undefined reference to `mxGetDoubles'
collect2.exe: error: ld returned 1 exit status
This is the error matlab returned this time. It seems like matab's having a problem with mxGetDoubles
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.
Bruno, Thank you so much, now it all seems to work exactly as i wanted to. Thank you for your time.

Sign in to comment.

Categories

Products

Release

R2018b

Asked:

on 10 Aug 2019

Commented:

on 11 Aug 2019

Community Treasure Hunt

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

Start Hunting!