2010-02-02 32 views
9

J'essaye d'écrire une fonction matlab mex qui utilise libhdf5; Mon installation Linux fournit des bibliothèques et des en-têtes partagés libhdf5-1.8. Cependant, ma version de Matlab, r2007b, fournit un libhdf5.so de la version 1.6. (Matlab .mat fichiers bootstrap hdf5, évidemment). Quand je compile le mex, ça segmente dans Matlab. Si je rétrograde ma version de libhdf5 à 1,6 (pas une option à long terme), le code compile et fonctionne bien.emplacements de bibliothèque partagés pour les fichiers matlab mex:

question: comment résoudre ce problème? Comment puis-je dire au processus de compilation mex de lier avec /usr/lib64/libhdf5.so.6 au lieu de /opt/matlab/bin/glnxa64/libhdf5.so.0? Lorsque je tente de le faire en utilisant -Wl,-rpath-link,/usr/lib64 dans ma compilation, je reçois des erreurs telles que:

/usr/lib/gcc/x86_64-pc-linux-gnu/4.3.4/../../../../x86_64-pc-linux-gnu/bin/ld: warning: libhdf5.so.0, needed by /opt/matlab/matlab75/bin/glnxa64/libmat.so, may conflict with libhdf5.so.6 
/usr/lib/gcc/x86_64-pc-linux-gnu/4.3.4/../../../../lib64/crt1.o: In function `_start': 
(.text+0x20): undefined reference to `main' 
collect2: ld returned 1 exit status 

    mex: link of 'hdf5_read_strings.mexa64' failed. 

make: *** [hdf5_read_strings.mexa64] Error 1 

ack. le dernier recours consisterait à télécharger une copie locale des en-têtes hdf5-1.6.5 et à en faire usage, mais ce n'est pas une preuve du futur (une mise à jour de la version Matlab est dans mon futur). des idées?

EDIT: par d'excellentes suggestions de Ramashalanka, je

A) appelé mex -v pour obtenir les 3 gcc commandes; le dernier est la commande de l'éditeur de liens; B) a appelé cette commande de liaison avec un -v pour obtenir la commande collect; C) appelé collect2 -v -t et le reste des drapeaux.

Les parties pertinentes de ma sortie:

/usr/bin/ld: mode elf_x86_64 
/usr/lib/gcc/x86_64-pc-linux-gnu/4.3.4/../../../../lib64/crti.o 
/usr/lib/gcc/x86_64-pc-linux-gnu/4.3.4/crtbeginS.o 
hdf5_read_strings.o 
mexversion.o 
-lmx (/opt/matlab/matlab75/bin/glnxa64/libmx.so) 
-lmex (/opt/matlab/matlab75/bin/glnxa64/libmex.so) 
-lhdf5 (/usr/lib/gcc/x86_64-pc-linux-gnu/4.3.4/../../../../lib64/libhdf5.so) 
/lib64/libz.so 
-lm (/usr/lib/gcc/x86_64-pc-linux-gnu/4.3.4/../../../../lib64/libm.so) 
-lstdc++ (/usr/lib/gcc/x86_64-pc-linux-gnu/4.3.4/libstdc++.so) 
-lgcc_s (/usr/lib/gcc/x86_64-pc-linux-gnu/4.3.4/libgcc_s.so) 
/lib64/libpthread.so.0 
/lib64/libc.so.6 
/lib64/ld-linux-x86-64.so.2 
-lgcc_s (/usr/lib/gcc/x86_64-pc-linux-gnu/4.3.4/libgcc_s.so) 
/usr/lib/gcc/x86_64-pc-linux-gnu/4.3.4/crtendS.o 
/usr/lib/gcc/x86_64-pc-linux-gnu/4.3.4/../../../../lib64/crtn.o 

Donc, en fait, est en cours référencent libhdf5.so de /usr/lib64. Cependant, je crois que ceci est remplacé par la variable d'environnement LD_LIBRARY_PATH, que ma version de Matlab définit automagiquement au moment de l'exécution afin qu'elle puisse localiser ses propres versions, par ex. libmex.so, etc.

Je pense que l'exemple crt_file.c fonctionne soit b/c ne pas utiliser les fonctions que je utilise (H5DOpen, qui a eu un changement de signature dans le passage de 1,6 à 1,8 (oui, je me sers -DH5_USE_16_API)), ou, moins probable, b/c il ne frappe pas les parties des internes de Matlab qui ont besoin de hdf5. ack.

+0

Dans votre sortie je vois 'lib64/libhdf5.so' qui est une bibliothèque dynamique. Vous devez spécifier le chemin explicite pour la bibliothèque statique (avec un suffixe .o) et ne pas utiliser '-lhdf5'. Ensuite, publiez une nouvelle sortie de l'éditeur de liens si elle ne fonctionne toujours pas. Si le fichier '.so' est le seul dans la liste alors c'est le seul inclus. 'LD_LIBRARY_PATH' ou n'importe quel autre chemin, comme dans' -L' ne devrait pas avoir d'importance si vous n'avez pas '-lhdf5' en option et vous spécifiez explicitement le chemin vers la bibliothèque statique (voir ci-dessous). Je suis d'accord avec vos commentaires sur 'h5_crtfile.c', mais toutes les informations dont nous avons besoin sont dans la sortie de votre éditeur de liens ci-dessus. – Ramashalanka

+0

Je n'ai pas de fichier 'libhdf5.o'; Le paquetage hdf5 de gentoo fournit 'libhdf5.so',' libhdf5.a', 'libhdf5.la', et quelques fichiers fortran et cpp. Dois-je compiler libhdf5 moi-même? C'est une option ... – shabbychef

+0

Désolé, je voulais dire '.a', pas' .o'. Vous pouvez vérifier que le fichier 'libhdf5.a' que vous avez est la bonne version par exemple. 'chaînes de caractères libhdf5.a'. Je vois «Version HDF5: 1.8.4» dans le mien. Si vous ne pouvez pas obtenir la bonne bibliothèque statique en tant que binaire, il est facile à compiler. Voir mes commentaires à votre autre requête ci-dessous. – Ramashalanka

Répondre

8

Les personnes suivantes ont travaillé sur mon système:

  1. Installer la version HDF5 1.8.4 (vous avez déjà fait ceci: Je l'ai installé la source et en garantir le est compatible avec mon système, que je reçois versions gcc et que je reçois les bibliothèques statiques - par exemple les binaires offerts pour mon système sont icc spécifiques).

  2. Créer un fichier cible. Vous avez déjà votre propre fichier. J'ai utilisé le h5_crtfile.c simple de here (une bonne idée de commencer par ce simple fichier d'abord un coup d'oeil pour les avertissements). J'ai changé main à mexFunction avec les arguments habituels et inclus mex.h.

  3. Spécifiez la bibliothèque statique 1.8.4 que vous voulez charger explicitement (le chemin complet sans -L pour nécessaire) et de ne pas inclure dans le -lhdf5LDFLAGS.Incluez une option -t pour vous assurer qu'il n'y a pas de bibliothèque dynamique hdf5 en cours de chargement. Vous avez également besoin de -lz, avec zlib installé. Pour darwin nous avons aussi besoin d'un -bundle dans LDFLAGS:

    mex CFLAGS='-I/usr/local/hdf5/include' LDFLAGS='-t /usr/local/hdf5/lib/libhdf5.a -lz -bundle' h5_crtfile.c -v 
    

    Pour linux, vous avez besoin d'une position indépendante équivalente appel, par exemple fPIC et peut-être -shared, mais je ne dispose pas d'un système Linux avec une licence de Matlab, donc je ne peux pas vérifier:

    mex CFLAGS='-fPIC -I/usr/local/hdf5/include' LDFLAGS='-t /usr/local/hdf5/lib/libhdf5.a -lz -shared' h5_crtfile.c -v 
    
  4. Exécutez le fichier h5_crtfile MEX. Cela fonctionne sans problèmes sur ma machine. Il fait juste un H5Fcreate et H5Fclose pour créer "file.h5" dans le répertoire courant, et quand j'appelle file file.h5 je reçois file.h5: Hierarchical Data Format (version 5) data.

Notez que si j'inclus un -lhdf5 ci-dessus à l'étape 3, puis Matlab avorte lorsque je tente de lancer l'exécutable (car il utilise alors les bibliothèques dynamiques Matlab qui pour moi sont la version 1.6.5), c'est donc résolvant définitivement le problème sur mon système.

Merci pour la question. Ma solution ci-dessus est définitivement beaucoup plus facile pour moi que ce que je faisais auparavant. Espérons que ce qui précède fonctionne pour vous.

+0

hmmm. quand j'essaye ceci, la compilation échoue b/c 'libmat.so' repose sur' libhdf5.so'. quelque chose d'étrange là-bas. malheureusement, je ne peux pas inclure 'mex.h' sans tirer aussi dans le hdf5 de Mathworks; Malheureusement, les fichiers d'en-tête distribués par Mathworks n'incluent pas 'hdf5.h'. – shabbychef

+0

OK, j'ai réécrit le post, voir comment ça se passe. – Ramashalanka

+0

Je compile en shell avec les commandes gcc crachées par mex. J'ai essayé votre solution, en sautant les étapes 2 & 3; ('-bundle' est spécifique à Darwin, BTW) en utilisant' h5_crtfile.c', je reçois "Attention! Les fichiers d'en-tête HDF5 inclus par cette application ne correspondent pas à la version utilisée par la bibliothèque HDF5 auquel cette application est liée. les données défauts de corruption ou segmentation peut se produire si l'application continue. environnement variable définie, l'application « HDF5_DISABLE_VERSION_CHECK » va continuer . en-têtes sont 1.8.4, 1.6.5" bibliothèque est cependant, 'fichier.h5' est créé! MAIS, avec cette astuce sur mon mex, ça reste des segfaults. – shabbychef

3

J'accepte la réponse de Ramashalanka parce qu'il m'a conduit à la solution exacte que je vais poster ici pour être complet que:

  1. télécharger la bibliothèque hdf5-1.6.5 du site hdf5 et installer les fichiers d'en-tête dans un répertoire local;
  2. dire de chercher MEX « hdf5.h » dans ce répertoire local, plutôt que dans l'emplacement standard (par exemple /usr/include.)
  3. dire de compiler mon MEX le code et la bibliothèque d'objets partagés fourni par Matlab, et faire pas utiliser le drapeau -ldfh5 dans LDFLAGS.

la commande j'est, essentiellement:

/opt/matlab/matlab_default/bin/mex -v CC#gcc CXX#g++ CFLAGS#"-Wall -O3 -fPIC -I./hdf5_1.6.5/src -I/usr/include -I/opt/matlab/matlab_default/extern/include" CXXFLAGS#"-Wall -O3 -fPIC -I./hdf5_1.6.5/src -I/usr/include -I/opt/matlab/matlab_default/extern/include " -O -lmwblas -largeArrayDims -L/usr/lib64 hdf5_read_strings.c /opt/matlab/matlab_default/bin/glnxa64/libhdf5.so.0 

ce se traduit par MEX dans les commandes:

gcc -c -I/opt/matlab/matlab75/extern/include -DMATLAB_MEX_FILE -Wall -O3 -fPIC -I./hdf5_1.6.5/src -I/usr/include -I/opt/matlab/matlab_default/extern/include -O -DNDEBUG hdf5_read_strings.c 
gcc -c -I/opt/matlab/matlab75/extern/include -DMATLAB_MEX_FILE -Wall -O3 -fPIC -I./hdf5_1.6.5/src -I/usr/include -I/opt/matlab/matlab_default/extern/include -O -DNDEBUG /opt/matlab/matlab75/extern/src/mexversion.c 
gcc -O -pthread -shared -Wl,--version-script,/opt/matlab/matlab75/extern/lib/glnxa64/mexFunction.map -Wl,--no-undefined -o hdf5_read_strings.mexa64 hdf5_read_strings.o mexversion.o -lmwblas -L/usr/lib64 /opt/matlab/matlab_default/bin/glnxa64/libhdf5.so.0 -Wl,-rpath-link,/opt/matlab/matlab_default/bin/glnxa64 -L/opt/matlab/matlab_default/bin/glnxa64 -lmx -lmex -lmat -lm -lstdc++ 

cette solution devrait fonctionner sur tous mes différentes machines cibles et au moins jusqu'à ce que je mette à jour vers matlab r2009a, qui je crois utilise hdf5-1.8. merci pour toute l'aide, désolé d'être si dense avec cela - je pense que j'étais trop engagé à l'aide de la version packagée de hdf5, plutôt que d'un ensemble local de fichiers d'en-tête.

RemarqueCet tout aurait été si trivial Mathworks avait fourni un ensemble de fichiers d'en-tête avec la distribution Matlab ...

+0

C'est ainsi que j'ai manipulé des fichiers mex multithread qui devaient lier boost-thread. Mais il DOIT y avoir un moyen de le lier à la bibliothèque du système au lieu de celui de Matlab et d'éviter les segfaults de cette façon. Être coincé avec tout ce qu'il y a de boost à l'intérieur de Matlab n'est pas très agréable. – Chinasaur

+0

En ce qui concerne les suggestions utiles de Ramashalanka, je peux aussi dire qu'avec ma situation de lien boost-thread, j'ai dû faire ce contournement sous Linux mais pas sous Mac; Dans Mac il semble que la commande mex ne lie pas dans les versions internes comme dans Linux. – Chinasaur

+1

Quelque chose comme la réponse ici: http://stackoverflow.com/questions/9927568/compiling-c11-code-as-part-of-a-matlab-mex-file pourrait fonctionner (bien que la question soit pour quelque chose d'un peu différent) . Je rapporterai si je le fais fonctionner. – Chinasaur