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 commentaires

dpb
dpb le 10 Août 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
Roberto Neri le 10 Août 2019
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 le 10 Août 2019
Modifié(e) : James Tursa le 10 Août 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
Roberto Neri le 11 Août 2019
Modifié(e) : Roberto Neri le 11 Août 2019
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.
Bruno Luong
Bruno Luong le 11 Août 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
Roberto Neri le 11 Août 2019
Yes, sorry, i just made a mistake while editing the code to post it here. Sorry for that.
Bruno Luong
Bruno Luong le 11 Août 2019
Modifié(e) : Bruno Luong le 11 Août 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
Roberto Neri le 11 Août 2019
Thanks! i didn't noticed that bad error. But still it doesn't work.

Connectez-vous pour commenter.

Réponses (1)

James Tursa
James Tursa le 11 Août 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 commentaires

Roberto Neri
Roberto Neri le 11 Août 2019
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 le 11 Août 2019
Modifié(e) : Bruno Luong le 11 Août 2019
If you want to get help to spot the error, you better post the whole code, and not truncated, copy/past.
Roberto Neri
Roberto Neri le 11 Août 2019
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?
Bruno Luong
Bruno Luong le 11 Août 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.
Stephen23
Stephen23 le 11 Août 2019
Modifié(e) : dpb le 11 Août 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.
Bruno Luong
Bruno Luong le 11 Août 2019
Modifié(e) : Bruno Luong le 11 Août 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
Roberto Neri le 11 Août 2019
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
Bruno Luong
Bruno Luong le 11 Août 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
Roberto Neri le 11 Août 2019
Bruno, Thank you so much, now it all seems to work exactly as i wanted to. Thank you for your time.

Connectez-vous pour commenter.

Catégories

En savoir plus sur Write C Functions Callable from MATLAB (MEX Files) dans Centre d'aide et File Exchange

Produits

Version

R2018b

Question posée :

le 10 Août 2019

Commenté :

le 11 Août 2019

Community Treasure Hunt

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

Start Hunting!

Translated by