Bonjour à tous,
Je souhaiterai savoir si c'est possible d'utiliser des librairies C tel la SDL, GTK ou OpenGL avec Matlab ?
Version imprimable
Bonjour à tous,
Je souhaiterai savoir si c'est possible d'utiliser des librairies C tel la SDL, GTK ou OpenGL avec Matlab ?
Oui c'est possible via un fichier Mex.
Sur quel(s) système(s) d'exploitation le code doit-il fonctionner ?
Le code doit fonctionner sur Linux Ubuntu la dernière version.
J'ai pas encore créé le Mex-File, j'ai simplement fait un simple code C de test
dans lequel j'utilise la librairie SDL.
Pour la SDL :
Vérifie que les deux paquets suivants sont installés :
- libsdl1.2debian
- libsdl1.2-dev
Ajoute #include "SDL/SDL.h" au début du fichier MEX
Compile comme ceci (au chemin de la bibliothèque près) :
Pour OpenGL :Code:mex -I/usr/include -L/usr/lib/x86_64-linux-gnu -lSDL mexavecSDL.c
Vérifie que les deux paquets suivants sont installés :
- libgl1_mesa-dev
- mesa-common-dev
Ajoute #include "gl/GL.h" au début du fichier MEX
Compile comme ceci (au chemin de la bibliothèque près) :
Pour SDL + OpenGLCode:mex -I/usr/include -L/usr/lib/x86_64-linux-gnu -lGL mexavecOpenGL.c
Ajoute #include "SDL/SDL.h" et #include "gl/GL.h" et au début du fichier MEX
Compile comme ceci (au chemin des bibliothèques près) :
PS : tu trouveras le Mex exemple SDLgears (tiré du site http://www.libsdl.org/opengl/index.php) en pièce jointe :Code:mex -I/usr/include -L/usr/lib/x86_64-linux-gnu -lSDL -lGL mexavecSDLetOpenGL.c
Code:mex -I/usr/include -L/usr/lib/x86_64-linux-gnu -lSDL -lGL SDLgears.c
Je vous remercie pour votre aide.
Pour GTK+ :
Vérifie que le paquet libgtk2.0-dev est bien installé.
Ajoute #include "gtk/gtk.h" au début du fichier Mex.
Pour compiler, il est plus facile de créer un fichier spécifique mexopts-gtk.sh à partir du fichier mexopts.sh par défaut en ajoutant les lignes suivantes dans le bloc correspondant à ton architecture :
etCode:CFLAGS="$CFLAGS `pkg-config --cflags gtk+-2.0`"
Tu places ce fichier au même niveau que le fichier Mex et tu compiles comme ceci :Code:CLIBS="$CLIBS `pkg-config --libs gtk+-2.0`
Je joins un fichier test issu du livre Foundations of GTK+ DevelopmentCode:mex -f ./mexopts-gtk.sh mexavecGTK.c
Ok cool.
Une question me vient à l'esprit, si on peut utilisé GTK avec matlab est t'il intéressant de toujours utilisé le GUI de matlab ?
Pour faciliter la création du fichier Mex peut on aussi faire des makefiles ?
C'est une question de connaissance et de maitrise de langages différents.
Java et C/C++ sont différents. C'est tout.
Je pense néanmoins que la plupart des utilisateurs de MATLAB se contente très bien des interfaces en Java.
Après on peut aussi être dans le cas où l'interface existe déjà sous GTK+ par exemple.
Il peut être plus simple de légèrement modifier le main plutôt que de refaire l'interface sous MATLAB
Je n'ai jamais essayé mais je pense que c'est possible.
Ah ok, je comprends.
J'ai écrit un petit mex file qui permet d'utilisé la SDL pour lire une image en niveau de gris qui prend ses valeurs dans l'ensemble [|0,255|].
Cependant j'ai un problème, après avoir ouvert la fenêtre avec l'image à l'intérieur je ne peux plus avoir la main dans MATLAB sans fermer ma fenêtre.
Pouvez vous m'aidez svp ?
Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164 #include "mex.h" #include<stdio.h> #include<stdlib.h> #include <SDL/SDL.h> #include <SDL/SDL_rotozoom.h> /* creation de la surface associee a l'image*/ SDL_Surface *createImage(double **image,int height,int width) { int i,j; SDL_Surface *simage= NULL; SDL_Rect position; simage=SDL_CreateRGBSurface(SDL_HWSURFACE,width,height,32,0,0,0,0); position.w=position.h=1; for (i = 0 ; i < height; ++i){ for(j=0;j<width;++j){ position.x = j; position.y = i; SDL_FillRect(simage,&position,SDL_MapRGB(simage->format,image[i][j],image[i][j],image[i][j])); }} return(simage); } /* affichage de l'image suivant sa taille*/ void displayImage(SDL_Surface **ecran,SDL_Surface *simage,int height,int width) { SDL_Surface *newSurf=NULL; SDL_Rect position; position.x = 0; position.y = 0; if(*ecran!=NULL) SDL_FreeSurface(*ecran); /*on efface l'ecran si c'est la premiere fois qu'il est utilise*/ if(simage->w!=width || simage->h!=height) /*si le redimensionement change la taille de l'image on cree une nouvelle surface */ newSurf=rotozoomSurfaceXY(simage,0.,(double)width/(double)simage->w,(double)height/(double)simage->h,1); else newSurf=simage; *ecran=SDL_SetVideoMode(newSurf->w,newSurf->h,32,SDL_HWSURFACE|SDL_DOUBLEBUF|SDL_RESIZABLE); SDL_BlitSurface(newSurf,NULL,*ecran,&position); SDL_Flip(*ecran); if(newSurf!=simage) SDL_FreeSurface(newSurf); } /* Traitement des evenements */ void treatEvent(SDL_Surface **ecran,SDL_Surface *simage,int height,int width) { int done; SDL_Event event; done=0; while(!done) { SDL_WaitEvent(&event); switch(event.type) { case SDL_QUIT: done=1; break; case SDL_KEYDOWN: switch(event.key.keysym.sym) { case SDLK_ESCAPE: done=1; break; case SDLK_1: case SDLK_KP1: displayImage(ecran,simage,height,width); break; case SDLK_2: case SDLK_KP2: if(event.key.keysym.mod&KMOD_CTRL) displayImage(ecran,simage,height*2,width*2); else displayImage(ecran,simage,height/2,width/2); break; default: break; } break; case SDL_VIDEORESIZE: displayImage(ecran,simage,event.resize.h,event.resize.w); break; } } } void affiche(double **image,int nrow,int ncol,int largeur_max,int hauteur_max) { SDL_Surface *ecran,*imgSurf; ecran=NULL; imgSurf=createImage(image,nrow,ncol); /*creation de la surface associee à l'image*/ while(largeur_max<ncol || hauteur_max<nrow){nrow=nrow/2;ncol=ncol/2;} displayImage(&ecran,imgSurf,nrow,ncol); /*creation de l'image a l'ecran*/ SDL_WM_SetCaption("My Picture SDL !", NULL); /*mettre un titre a la fenetre*/ treatEvent(&ecran,imgSurf,nrow,ncol); /* gestion des evenements(clavier,redimensionement, ect...)*/ /* liberation de la memoire */ SDL_FreeSurface(imgSurf); SDL_FreeSurface(ecran); return; } void mexFunction( int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[] ) { double *x=NULL, **I=NULL; mwSize nrow, ncol; mwIndex i,j; const SDL_VideoInfo *videoInfo; int largeur_max,hauteur_max; nrow = mxGetM(prhs[0]); ncol = mxGetN(prhs[0]); /* changement de representation en memoire des matrices*/ x=mxGetPr(prhs[0]); I=mxMalloc(nrow*sizeof(double *)); I[0]=mxMalloc(nrow*ncol*sizeof(double)); for (i=1;i<nrow;++i){ I[i]=I[i-1]+ncol;} for(i=0;i<nrow;++i){ for(j=0;j<ncol;++j){I[i][j]=x[j*nrow+i];}} /*############## affichage des resultats en fenetre ############*/ SDL_Init(SDL_INIT_VIDEO); videoInfo=SDL_GetVideoInfo(); /*determination de la taille de l'ecran*/ largeur_max=videoInfo->current_w; hauteur_max=videoInfo->current_h; affiche(I,nrow,ncol,largeur_max,hauteur_max); SDL_Quit(); /* supression en memoire des tableaux */ mxFree(I[0]); mxFree(I); return ; }
Pour compiler il faut installé SDL_gfx et compilé avec (en m'inspirant de ce que tu as mentionné plus haut) :
Code:mex -I/usr/include -L/usr/lib/x86_64-linux-gnu -lSDL -lSDL_gfx affiche.c
Peux-tu nous expliquer plus précisément ce que tu cherches à faire ?
Tu peux toujours utiliser les fonctions comme mexCallMATLAB pour appeler du code MATLAB.
En fait mon souci est le suivant :
Mon programme sert à afficher une image en niveau de gris dans une fenêtre. Pour se faire il prend en paramètre la matrice de pixel de l'image.
Pour que la fenêtre puisse rester visible à l'utilisateur je fais une boucle infinie et gère les événements à l'aide de la SDL. Le problème c'est qu'en faisant cela je ne peux plus rien taper dans matlab à cause de la boucle infinie.
Comment puis je faire pour que ma fenêtre reste afficher et que je puisse accéder à matlab comme lors de l'utilisation de imshow par exemple.
Je pense que ce que tu cherches à faire est impossible.
Ceci est dû à la gestion des événements par la SDL (le Mex tourne en boucle)
hum je vois.
Peut être qu'il faudrait que la partie qui concerne l'affichage s'effectue dans une autre console. Comme cela la SDL fait une boucle infini dans cette console et la suite du programme contenu dans le Mex s'effectue (une exécution en arrière plan).
Le problème c'est que je ne sais pas comment faire ceci.
Je ne te suis pas... As-tu regardé la fonction mexCallMATLAB ?
j'ai regardé la fonction mexCallMATLAB mais il me semble qu'elle permet d'appeler une fonction matlab dans un code C. Ce n'est pas exactement ce que je veux faire si je me trompe pas.
En fait je veux que la fenêtre s’exécute en arrière plan pour que le mexfile puisse arriver jusqu'à son return sans fermer cette dernière.
Il existe vraiment aucun moyen de récupérer le prompt pendant l'exécution d'un programme ?
Sachant que le mex contient une boucle "infinie", je ne vois pas comment tu pourrais récupérer la main sous MATLAB.
De toute façon, quel serait l'intérêt ?
Une interface graphique sert justement à se passer d'une console, non ?
Oui c'est vrai.
Je voulais juste utilisé ma petite fonction affiche en remplacement de imshow, juste pour faire de l'affichage.
Je me demande comment ils font dans imshow pour avoir le prompt en même temps que l'image reste affichée
J'ai vu que les trheads me permettraient de réaliser l'idée que j'ai eu précédemment. Mais lorsque le return du mex se réalisera je ne pense pas que la fenêtre va rester afficher sans qu'il y ait des messages d'erreurs.
Il faut que je trouve comment ils font mdr.
Comme MATLAB est lancé avec Java, les objets Figure font parties de la "même boucle" que les fenêtre du MATLAB Desktop. On peut donc facilement passer d'une fenêtre à une autre.
Pour schématiser, dans une utilisation normale, c'est Java qui "englobe" MATLAB alors que dans ton cas, c'est MATLAB qui "englobe" la SDL (et qui doit donc attendre que le Mex se termine pour reprendre la main).
Ah ok ! je vois.
Mais est ce que Matlab gère le threading ? est ce qu'on peut faire du threading avec des fonctions .m ?
Si c'est le cas on peut créé une fonction .m et y inclure le mex-files et
on fait un thread. Vous en pensez quoi ?