web-dev-qa-db-fra.com

Utilisation de GCC (MinGW) comme compilateur MEX de MATLAB

On m'a confié un projet à exécuter sur MATLAB R2011a. Comme il y a plusieurs fichiers .c - j'ai besoin de configurer GCC comme compilateur MEX pour ce projet. Cependant, je n'arrive pas à trouver d'explication sur la façon de le configurer. J'ai essayé un programme de script appelé gnumex - mais il a échoué (probablement configuré pour une ancienne version de MATLAB).

Une idée de comment le configurer?

20
Menyh

Dans Matlab 2011b, il suffit de compiler et de lier directement dans un environnement mingw64 ou cygwin.

MINGWPATH=c:/MinGW64
CYGPATH=c:/cygwin

MATLABROOT=c:/Progra~1/MATLAB/R2011b
CC=$(MINGWPATH)/bin/x86_64-w64-mingw32-gcc 
CFLAG= -Wall -m64 -O3 -I$(MATLABROOT)/extern/include $(SRC) $(LIBS) -o $(EXE)
MEXFLAG=-m64 -shared -DMATLAB_MEX_FILE -I$(MATLABROOT)/extern/include -Wl,--export-all-symbols $(LIBS) $(MEXSRC) -o $(MEXTGT).mexw64

LIBS= -L$(MATLABROOT)/bin/win64 -L$(MATLABROOT)/extern/lib/win64/Microsoft -lmex -lmx -lmwlapack -lmwblas -leng
EXE=../bin/engwindemo.exe
MEXTGT=
SRC=engwindemo.c
MEXSRC=
all:$(EXE)

$(EXE):  $(SRC)
    $(CC) $(CFLAG) -ladvapi32 -luser32 -lgdi32 -lkernel32 -lmingwex -o $(EXE)
    @rm -f *.o*

$(MEXTGT):  $(MEXSRC)
    $(CC) $(MEXFLAG) -ladvapi32 -luser32 -lgdi32 -lkernel32 -lmingwex 
    @rm -f *.o*

Placez ce makefile dans le répertoire du code source et make. Aucune conversion de fichiers dll nécessaire.

14
Richard Dualmann

Pourquoi ne pas ajuster le fichier mexopts.bat dans votre répertoire? De cette façon, vous pouvez utiliser la commande "mex" de manière transparente pour compiler n'importe quoi, comme d'habitude dans MATLAB, comme s'il avait été configuré par MATLAB en utilisant mex -setup. Je suis surpris que personne ne l'ait fait auparavant.

Le fichier ci-dessous est pour la version x64 de Matlab et Mingw. J'utilise la distribution TDM Mingw64 , que j'ai installée dans p:\mingw64-tdm. J'ai Matlab installé dans p:\matlab\R2012a - modifiez-les en conséquence.

Ceci est le fichier mexopts.bat que j'utilise, copiez-collez-le dans %USERPROFILE%\AppData\Roaming\MathWorks\MATLAB\R2012a\mexopts.bat:

@echo off

set MINGWPATH=p:\mingw64-tdm
set PATH=%MINGWPATH%\bin;%PATH%

set COMPILER=gcc
set COMPFLAGS=-c -m64 -I"%MATLAB%\extern\include" -DMATLAB_MEX_FILE -Wall -std=c99
set OPTIMFLAGS=-O3 -DNDEBUG
set DEBUGFLAGS=-g
set NAME_OBJECT=-o

set LINKER=gcc
set LINKFLAGS=-shared -L"%MATLAB%\bin\win64" -L"%MATLAB%\extern\lib\win64\Microsoft" -lmex -lmx -leng -lmat -lmwlapack -lmwblas
set NAME_OUTPUT=-o "%OUTDIR%%MEX_NAME%%MEX_EXT%"

Ensuite, vous pouvez simplement essayer de faire cela dans Matlab:

mex -v p:\matlab\R2012a\extern\examples\mex\yprime.c
which yprime

Devrait céder b:\code\m\yprime.mexw64 (ou quel que soit le dossier actuel). Alors si vous le faites:

yprime(1,1:4)

Tu devrais voir:

ans =
    2.0000    8.9685    4.0000   -1.0947

Ce qui signifie que vous êtes en affaires. Bonne chance!

EDIT Oct 2014: J'utilise maintenant un fichier mexopts.bat amélioré que le précédent avec un MinGW64 différent (donne un code binaire légèrement plus rapide que celui de TDM). Voir ma page d'accueil pour les détails et les téléchargements.

13
Bogdan

Depuis MATLAB R2015b, MinGW est officiellement pris en charge!

Il est maintenant en haut de la liste des compilateurs pris en charge .

Voir ici pour les instructions officielles pour télécharger MinGW (ils recommandent TDB-GCC).

Il y a plusieurs limitations et mises en garde répertoriées (par exemple, ne liez pas avec les bibliothèques compilées avec d'autres compilateurs, vous devez intercepter vos exceptions dans le fichier MEX, etc.).

Vous trouverez ci-dessous mon ancienne façon de créer un fichier XML pour faire la même chose.


Les années ont passé et MATLAB (à partir de R2014a) est passé à un nouveau système basé sur XML pour configurer les fichiers MEX. MATLAB prend toujours en charge temporairement les fichiers .bat hérités, pour l'instant, mais cela vous dérange . Un autre changement est que ce sont des configurations C et C++ distinctes (plus tard).

Ce qui est resté le même, c'est qu'il vous suffit de télécharger et d'extraire une distribution MinGW et de pointer MATLAB dessus. Il n'y a encore pas besoin de MSYS, cygwin ou gnumex. La seule partie délicate pointe MATLAB dessus, mais voici une solution.

Version courte

  • Téléchargez et extrayez une distribution MinGW. Choisissez-en un, comme MinGW-w64 (64 bits) ou TDM-GCC (options 32 bits et 64 bits).
  • Personnalisez le fichier de configuration XML, en utilisant celui-ci comme modèle (détails dans la version longue ci-dessous).
  • Définissez la variable d'environnement MINGWROOT.
  • Courir mex -setup:[xmlfile] [C|C++].

Version longue

Pour MinGW-w64, je fais ce qui suit pour le configurer:

  1. Prenez la dernière révision pour w64 de Sourceforge (ou utilisez l'installateur pour choisir la chaîne d'outils que vous voulez, en choisissant une version de thread pthread ou Win32 selon vos besoins).
  2. Extrayez-le pour avoir un chemin vers le compilateur comme C:\mingw-w64\x86_64-4.9.2-release-posix-seh-rt_v3-rev1\bin\x86_64-w64-mingw32-g++.exe. Il n'est pas nécessaire d'utiliser MSYS, cygwin ou tout autre environnement si vous prévoyez de compiler dans MATLAB avec la commande mex. Vérifiez votre variable d'environnement PATH pour vous assurer que vous n'avez pas plusieurs compilateurs (g++) sur votre chemin, de préférence aucun. Vérifiez avec une nouvelle invite de commande.
  3. Configurez-le avec un fichier de configuration XML personnalisé. Sur mon référentiel GitHub, j'ai publié des configurations C++ pour MinGW-w64 dans les deux types de fichiers: mex_C++ _ mingw-w64.xml et hérité mingw_mexopts.bat . Commencez avec cela comme modèle et (facultativement) éditez le fichier XML avec un nom descriptif et une version de la distribution MinGW que vous avez téléchargée et extraite .
  4. Définissez (ou créez) la variable d'environnement MINGWROOT. C'est ce qui permet à la commande mex de localiser le compilateur. Vous pouvez le faire dans MATLAB (et à chaque fois MATLAB commence par un startup.m script dans userpath) avec setenv , ou une seule fois avec boîte de dialogue des propriétés Windows ou Windows 7 natif commande setx.exe .
  5. Courir mex -setup:C:\actual\configFilePath.xml C++. Par exemple, en utilisant le fichier .xml pour configurer la compilation du fichier MEX C++:

    setenv('MINGWROOT','H:\mingw-w64\x86_64-4.9.2-release-posix-seh-rt_v3-rev1')
    mex -setup:H:\building\GitHub\MATLAB\MinGW\mex_C++_mingw-w64.xml C++
    

    La sortie devrait ressembler à ceci:

    MEX configuré pour utiliser 'MinGW-w64 GCC 4.9.2 posixthreads seh' pour la compilation du langage C++.

Si nécessaire, configurez le compilateur C de manière similaire avec un nouveau fichier de configuration XML spécifiant le langage C, l'interface du compilateur C (par exemple "x86_64-w64-mingw32-gcc.exe" qui ne liera pas automatiquement la bibliothèque standard C++ ), ajustez les bibliothèques de liens selon vos besoins, les drapeaux du compilateur (par exemple, changez -std=c++11 à -std=c99), etc.


Remarque sur la liaison statique et dynamique des bibliothèques d'exécution

Les bibliothèques telles qu'un fichier MEX créé avec MinGW-w64 comme ci-dessus peuvent dépendre de quelques DLL (au moment de l'exécution): LIBGCC_S_SEH-1.DLL (pour les distributions d'exceptions seh) et LIBSTDC++ - 6.DLL, et peut-être libwinpthread-1.dll si vous avez choisi une distribution pthreads au lieu de threads Win32. Si vous ne souhaitez pas copier ces fichiers, vous pouvez lier statiquement les bibliothèques d'exécution dans votre fichier MEX en ajoutant les commutateurs suivants:

-static-libgcc -static-libstdc++

Il y a un commentaire dans le modèle XML à ce sujet. Voir ici pour plus d'informations sur libpthread-1.dll.

Avec TDM-GCC, l'inverse est vrai : les temps d'exécution (y compris pthread) sont automatiquement liés statiquement. Pour créer un lien dynamique, qui nécessitera les DLL mais réduira la taille de votre fichier MEX, vous avez besoin de:

-shared-libgcc -shared-libstdc++
8
chappjc

EDIT: Il semble y avoir un bien meilleur moyen avec MinGW; voir mon autre réponse.

Vous pouvez compiler un fichier .mex En utilisant gcc si vous avez Matlab installé, à partir de la ligne de commande. Certains pourraient dire que c'est un peu fastidieux la première fois.

Tout d'abord - quel Matlab utilisez-vous? si c'est 64 bits, MinGW ne vous aidera pas, car c'est 32 bits. Je vais donc montrer comment utiliser MinGW-w64 à la place. Comprendre comment faire cela avec MinGW 32 bits devrait être simple.

  1. Ajoutez C:\MinGW-64\bin\ À votre chemin. Vous ne le regretterez pas :)
  2. Compilez vos fichiers .c En utilisant gcc:

    x86_64-w64-mingw32-c++ -m64 -shared -I"C:\Program Files\MATLAB\R2010b\extern\include" -o bla.mexw64 -DMATLAB_MEX_FILE -Wl,--export-all-symbols *.cpp
    
  3. Cela entraînera un tas d'erreurs de l'éditeur de liens, telles que

    undefined reference to `mexErrMsgTxt'
    

    Pour résoudre ce problème, vous devrez créer une bibliothèque d'importation qui se connecte avec libmex.dll, libmx.dll, libmat.dll Et libeng.dll (Vous pourriez en avoir d'autres, mais ce sont les principaux)

  4. Énumérez les fonctions qui vous manquent et, bien, devinez de quelle dll elles proviennent. Astuce: mexErrMsgTxt vient de libmex.dll, Car il commence par "mex" ...

  5. Pour chaque dll que vous devez exporter, créez un fichier .def Contenant

    EXPORTS
    ... relevant function names go here, such as mexErrMsgTxt, matOpen, etc.
    
  6. Exécutez la commande suivante pour créer des bibliothèques d'importation:

    x86_64-w64-mingw32-dlltool -d libmx.def --dllname libmx.dll -l libmx.a
    

    (Idem pour le reste des fichiers .def)

  7. Vous êtes maintenant prêt à partir!

    x86_64-w64-mingw32-c++ -m64 -shared -I"C:\..." -DMATLAB_MEX_FILE -o bla.mexw64 -Wl,--export-all-symbols *.cpp libmex.a libmx.a libmat.a libeng.a
    

Ce qui peut être mieux fait - au lieu de --export-all-symbol, Exportez uniquement mexFunction (nécessite la création d'un autre fichier .def, Ou l'ajout de "__declspec(dllexport)" avant void mexFunction(...)).

6
user1071136

MinGW est capable de liaison directe d'un DLL ; c'est-à-dire qu'il créera une sorte de bibliothèque d'importation à la volée lors de la liaison.

Cela signifie que la compilation peut être effectuée en une seule étape:

x86_64-w64-mingw32-c++ -m64 -shared -I"%MATLAB%/extern/include" -DMATLAB_MEX_FILE -o bla.mexw64 -Wl,--export-all-symbols *.cpp -L"%MATLAB%/bin/win64" -lmex -lmx -leng -lmat
3
user1071136

Pourquoi tant d'étapes? Si vous avez Matlab 2016 ou supérieur , faites simplement:

  1. Téléchargez mingw et installez-le dans un dossier sans espaces (c'est-à-dire pas dans "Program Files")
  2. Ajouter le MW_MINGW64_LOC variable d'environnement pointant vers le dossier d'installation (exactement la même chose que vous avez tapée dans le programme d'installation)
  3. Redémarrez votre PC
  4. Ouvrez MATLAB et tapez mex -setup dans la console. Il devrait indiquer "configuré pour utiliser MinGW"
  5. Exécutez/compilez votre programme MATLAB

Je les ai testés sur un nouveau PC Windows 10 et ça marche!

1
Robinicks

Liens Matlab vers du code externe (C++, Fortran, Java etc) en utilisant des fichiers MEX. ( http://gnumex.sourceforge.net/ )

Configuration du compilateur:

  1. Installer TDM-GCC (compilateur C++ "C:\MinGW32\bin;") À partir de http://tdm-gcc.tdragon.net/download
  2. Installez Cygwin (la boîte à outils fournit des outils Unix sur la plate-forme Windows) à partir de ( http://ptolemy.eecs.berkeley.edu/ptolemyII/ ptII4.0/cygwin.htm ).
    Téléchargez et installez cygwingDevel.exe
  3. Obtenez l'archive gnumex via ( https://sourceforge.net/projects/gnumex ) et extrayez le gnumex dans ([$MATLABHOME\gnumex).
    $MATLABHOME Serait par exemple (C:\Program Files\MATLAB\R2010a)
  4. Ajoutez ce répertoire ($MATLABHOME\gnumex) Au chemin Matlab (File->Set Path Dans Matlab).
    Remarque: Exécutez Matlab avec les privilèges d'administrateur.
  5. Dans Matlab, tapez gnumex à l'invite. Remplissez les chemins appropriés comme;

    MinGW_Root = C:\MinGW32, Cygwin_Root = C:\cygwin

  6. Faites 'File->Save Config', Puis cliquez sur 'Make Options file'. Quittez la fenêtre de configuration de gnumex.

Essai:

Copiez mexopts.bat (%AppData%\MathWorks\MATLAB\R2010a\mexopts.bat) Dans le répertoire de travail (%UserProfile%\Documents\MATLAB) Pour ce test.

  1. Dans matlab, exécutez ce qui suit à l'invite;

    mex -f mexopts.bat "C:\Program Files\MATLAB\R2010a\extern\examples\mex\yprime.c"

  2. Vous obtenez (%UserProfile%\Documents\MATLAB\yprime.mexw32) Lorsque vous tapez;

    quel yprime

  3. Exécutez-le en tapant à Matlab Prompt >> yprime(1,1:4) et voyez si vous obtenez 2.0000 8.9685 4.0000 -1.0947.

  4. Maintenant, copiez simplement mexopts.bat dans $MATLABHOME\bin Et cela devrait fonctionner de n'importe où.

Matlab sur la plate-forme Linux:

  1. À l'invite Linux, installez les éléments suivants;

    Sudo apt-get install gcc g ++ gfortran

  2. Dans Matlab, exécutez ce qui suit à l'invite;

    mex -setup

  3. Les fichiers d'options disponibles pour mex sont: **1**: /usr/local/MATLAB/R2012b/bin/mexopts.sh: Sélectionnez l'option 1 . Pour tester le fonctionnement, exécutez ce qui suit à Matlab Prompt;

    mex "/usr/local/MATLAB/R2012b/extern/examples/mex/yprime.c"

    yprime (1,1: 4)

Au cas où vous recevez l'avertissement;

Warning: You are using gcc version "4.6.3-1ubuntu5)".  The version
         currently supported with MEX is "4.4.6".
         For a list of currently supported compilers see: 
         http://www.mathworks.com/support/compilers/current_release/

À l'invite Linux:

  1. Sudo apt-get install gcc-4.4 g++-4.4 gfortran-4.4
  2. Sudo gedit /usr/local/MATLAB/R2012b/bin/mexopts.sh
  3. Remplacez 'gcc' Par 'gcc-4.4', 'g++' Par 'g++-4.4', 'gfortran' Par 'gfortran-4.4' À toutes les instances de CC = 'gcc', CXX = 'g++' Et FC = 'gfortran'.
  4. Enregistrez le fichier et quittez.
1
Faheem

Ceci est un guide détaillé de cette réponse . Par conséquent, tout le crédit devrait aller à cette réponse .

1 Installez MinGW-w64:

1.1 Téléchargez cette version de MinGW64-w64 et sa mise à jour:

( http://sourceforge.net/projects/mingw-w64/files/Toolchains%20targetting%20Win64/Personal%20Builds/sezero_4.5_20111101/mingw-w64-bin_x86_64-mingw_20111101_sezero.Zip/download )

( http://sourceforge.net/projects/mingw-w64/files/Toolchains%20targetting%20Win64/Personal%20Builds/sezero_4.5_20111101/sezero_20111101-w64-update-rev.5747.Zip/download =)

( http://sourceforge.net/projects/mingw-w64/files/Toolchains%20targetting%20Win64/Personal%20Builds/sezero_4.5_20111101/README-mingw-w64-20111101_sezero.txt/download )

1.2 Installez (décompressez) les archives téléchargées:

1.2.1 Décompressez le fichier de construction et déplacez le mingw64\ dossier dans c:\

1.2.2 Décompressez et copiez (écrasez) le fichier de mise à jour sur c:\mingw64

1.3 Ajouter C:\mingw64\bin à la variable Path:

set PATH=C:\mingw64\bin;%PATH%

2 Sur une ligne de commande (en dehors de l'environnement Matlab), compilez vos fichiers * .c: Par exemple, CCODEFILE.c (En supposant que Matlab 2012b est installé dans C:\Program Files\MATLAB\R2012b\ dossier):

"c:\mingw64\bin\x86_64-w64-mingw32-g++.exe" -m64 -shared -I"C:/Program Files/MATLAB/R2012b/extern/include" -DMATLAB_MEX_FILE -o CCODEFILE.mexw64 -Wl,--export-all-symbols CCODEFILE.c -L"C:/Program Files/MATLAB/R2012b/bin/win64" -lmex -lmx -leng -lmat

3 Ensuite, tout code Matlab devrait fonctionner correctement lorsqu'il appelle la fonction CCODEFILE.

1
imriss

Si vous n'avez pas pu installer Mingw-w64 à l'aide de la barre d'outils des modules complémentaires de Matlab2016b sous Windows , vous pouvez utiliser cette solution de contournement. N'oubliez pas que vous devez modifier les chemins d'accès en fonction de vos chemins d'installation.

  1. Le site officiel Mingw-w64 vous redirige vers le projet Win-builds qui est un gestionnaire de packages pour un ensemble d'outils de développement open source. Donc, vous devez d'abord installer les versions Win.
  2. Lors de l'installation de Win-builds, assurez-vous d'entrer un chemin qui ne contient aucun espace par ex. C:\Win-builds.
  3. Après avoir installé Win-builds, appuyez simplement sur le bouton Process pour installer tous les packages où Mingw-w64 est parmi eux.
  4. Maintenant que vous avez installé Mingw-w64, vous devez définir la variable d'environnement MW_MINGW64_LOC Qui Matlab l'utilise pour détecter Mingw-w64 .
  5. Pour définir la variable d'environnement, procédez comme suit:

    Panneau de configuration\Système\Paramètres système avancés\Avancé\Variable d'environnement\Variables utilisateur pour $ YOUR_USER_NAME\Nouveau

  6. Mettez Variable name = MW_MINGW64_LOC Et Variable value = C:\Win-builds. Notez que les builds Win placent tous les exécutables dans C:\Win-builds\bin Et en définissant cette variable, Matlab analysera automatiquement le dossier bin du chemin à la recherche de gcc.exe.
  7. Maintenant que vous avez installé le Mingw-w64 et défini la variable d'environnement MW_MINGW64_LOC, Il est temps de construire et de tester exemple yprime . Lancez donc Matlab et tapez la commande suivante (N'oubliez pas de modifier le chemin en conséquence):

    mex -v 'C:\Program Files\MATLAB\R2016b\extern\examples\mex\yprime.c'

  8. Une installation réussie affichera le message suivant:

    MEX s'est terminé avec succès.

  9. Enfin, vous pouvez tester votre installation en tapant yprime(1,1:4). La réponse serait:

    ans = 2.0000 8.9685 4.0000 -1.0947

1
hmofrad

Dans Windows 64 bits avec R2011a, cela fonctionnait avec http://tdm-gcc.tdragon.net/ et http://gnumex.sourceforge.net/ mais je dois changement maxopt.bat entrée de ligne GM_ADD_LIBS comme suit:

rem Add path to where dlls are:

set DLL_PATH="C:\Program Files\MATLAB\R2011a\bin\win64"

rem Add every dll needed:

set GM_ADD_LIBS=%DLL_PATH%\libmx.dll %DLL_PATH%\libmex.dll %DLL_PATH%\libmat.dll 

Il m'a fallu beaucoup de temps pour en arriver là, bonne chance.

0
rarias

Au départ, je pensais que cela ressemblait à une forme de torture, mais sur la base de la réponse ci-dessus de @ user10171136, je l'ai trouvé assez simple pour effectuer une compilation croisée pour Windows mex à partir de Fedora Linux. Fedora propose des packages mingw et mingw64, donc:

  1. Sudo yum install mingw64-gcc mingw64-gcc-c++
  2. Copiez à partir d'un Windows Matlab installez à la fois le extern/include et bin/win64 répertoires (en fait, vous n'avez probablement besoin que d'un sous-ensemble des en-têtes et d'un petit sous-ensemble des DLL; libmat.dll libmex.dll libmx.dll pourrait être tout ce dont vous avez besoin. J'ai mis ces deux répertoires dans un nouveau R2010a-w64 répertoire sous mon répertoire Linux MATLAB existant; modifiez les commandes ci-dessous en fonction de l'endroit où vous avez caché les en-têtes et les bibliothèques Windows.
  3. J'ai rencontré un problème, c'est que char16_t était nécessaire dans matrix.h et n'a pas été défini. Je suppose matrix.h oublié d'inclure uchar.h? J'ai travaillé avec un -include directive; voir ci-dessous.
  4. x86_64-w64-mingw32-gcc -m64 -shared -include uchar.h -I/opt/MATLAB/R2010a-w64/extern/include -DMATLAB_MEX_FILE -L/opt/MATLAB/R2010a-w64/bin/win64 -o bla.mexw64 bla.c -lmx -lmex
  5. (Vous pouvez avoir besoin de bibliothèques supplémentaires pour la liaison, par exemple -lmat -leng -lm, etc.)
  6. Cela génère avec succès un fichier mex qui est exécutable sous Windows Matlab pour ma configuration. Jusqu'à présent, je n'ai testé cela qu'avec des programmes C assez simples.

Intéressé d'entendre si cela semble raisonnable; Je n'ai pas beaucoup d'expérience avec la compilation croisée.

0
Chinasaur

Celui-ci fonctionne sur Matlab 2012b sous Windows 8:

https://github.com/DynareTeam/dynare/blob/master/windows/mexopts-win64.bat

Modifiez le répertoire cgwin ou remplacez-le par le répertoire mingw s'il est utilisé. Vous pouvez également échanger le compilateur-exe si vous passez à une version 64 bits.

0
pete