2010-02-02 16 views
9

Ich versuche, eine Matlab Mex-Funktion zu schreiben, die libhdf5 verwendet; Meine Linux-Installation bietet libhdf5-1.8 shared libraries und headers. Allerdings bietet meine Version von Matlab, r2007b, eine libhdf5.so von der Version 1.6. (Matlab .mat Dateien bootstrap hdf5, offenbar). Wenn ich das mex kompiliere, segregiert es in Matlab. Wenn ich meine Version von libhdf5 auf 1.6 heruntersetze (keine langfristige Option), kompiliert der Code und läuft gut.shared Bibliothek Standorte für Matlab Mex-Dateien:

frage: wie löse ich dieses problem? Wie kann ich den Mex-Kompilierungsprozess so erklären, dass er gegen /usr/lib64/libhdf5.so.6 anstelle von /opt/matlab/bin/glnxa64/libhdf5.so.0 verlinkt? Wenn ich versuche, dies mit -Wl,-rpath-link,/usr/lib64 in meiner Sammlung zu tun, erhalte ich Fehler wie:

/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. Der letzte Ausweg wäre, eine lokale Kopie der hdf5-1.6.5-Header herunterzuladen und damit fertig zu werden, aber das ist nicht zukunftssicher (ein Matlab-Versions-Upgrade ist in meiner Zukunft.). irgendwelche Ideen?

EDIT: pro Ramashalanka ausgezeichneten Vorschläge, ich

A) genannt mex -v die 3 gcc Befehle zu erhalten; der letzte ist der Linker-Befehl;

B) diesen Linker-Befehl mit einer -v aufgerufen, um den Befehl collect zu erhalten;

C) genannt collect2 -v -t und der Rest der Flags.

Die relevanten Teile meiner Ausgabe:

/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 

in der Tat so, die libhdf5.so von /usr/lib64 verwiesen wird. Dies wird jedoch, glaube ich, durch die Umgebungsvariable LD_LIBRARY_PATH überschrieben, die meine Version von Matlab automatisch zur Laufzeit festlegt, so dass sie ihre eigenen Versionen von z. libmex.so usw.

Ich denke, dass das crt_file.c Beispiel funktioniert entweder b/c es Ich benutze nicht die Funktionen (H5DOpen, die 1,6 bis 1,8 (ja in der Bewegung eine Signatur Änderung hatte, ich benutze -DH5_USE_16_API)), oder, weniger wahrscheinlich, b/c trifft es nicht die Teile von Matlab Interna, die hdf5 benötigen. ack.

+0

In Ihrer Ausgabe Ich sehe 'lib64/libhdf5.so', die eine dynamische Bibliothek ist. Sie müssen den expliziten Pfad für die statische Bibliothek angeben (mit einem Suffix .o) und nicht -lhdf5 verwenden. Dann post neu Linker-Ausgabe, wenn es immer noch nicht funktioniert. Wenn die '.so' Datei die einzige in der Liste ist, dann ist das die einzige. 'LD_LIBRARY_PATH' oder ein anderer Pfad, wie in' -L', sollte keine Rolle spielen, wenn Sie nicht '-lhdf5' als Option haben und Sie den Pfad zur statischen Bibliothek explizit angeben (siehe unten). Ich stimme Ihren Kommentaren zu 'h5_crtfile.c' zu, aber alle Informationen, die wir benötigen, finden Sie oben in Ihrer Linker-Ausgabe. – Ramashalanka

+0

Ich habe keine 'libhdf5.o' Datei; Das hdf5-Paket von gentoo bietet 'libhdf5.so',' libhdf5.a', 'libhdf5.la' und einige Fortran- und CPP-Dateien. Muss ich libhdf5 selbst kompilieren? das ist eine Option ... – shabbychef

+0

Entschuldigung, ich meinte '.a', nicht' .o'. Sie können überprüfen, ob die Datei "libhdf5.a", die Sie haben, die richtige Version ist, z. 'strings libhdf5.a'. Ich sehe "HDF5 Version: 1.8.4" in meinem. Wenn Sie die richtige statische Bibliothek nicht als Binärdatei erhalten können, ist es einfach zu kompilieren. Siehe meine Kommentare zu Ihrer anderen Abfrage unten. – Ramashalanka

Antwort

8

Das auf meinem System arbeitet folgende:

  1. hdf5 Version 1.8.4 (Sie dies bereits getan haben, zu installieren: Ich habe die Quelle installiert und kompilierten es mit meinem System kompatibel, um sicherzustellen, dass ich gcc-Versionen und dass ich die statischen Bibliotheken bekomme - zB sind die für mein System angebotenen Binärdateien icc spezifisch.

  2. Erstellen Sie eine Zieldatei. Sie haben bereits eine eigene Datei. Ich habe die einfache h5_crtfile.c von here (eine gute Idee, mit dieser einfachen Datei zuerst einen Blick für Warnungen zu starten). Ich änderte main zu mexFunction mit den üblichen Argumenten und schloss mex.h ein.

  3. Geben Sie die statische 1.8.4 Bibliothek Sie explizit laden wollen (den vollständigen Pfad ohne -L dafür notwendig) und enthalten keine -lhdf5 im LDFLAGS.Fügen Sie eine Option -t hinzu, damit Sie sicherstellen können, dass keine dynamische hdf5-Bibliothek geladen wird. Sie benötigen auch -lz, mit zlib installiert. Für Darwin brauchen wir auch einen -bundle in LDFLAGS:

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

    für Linux, müssen Sie einen gleichwertigen Position unabhängige Anruf, zum Beispiel fPIC und vielleicht -shared, aber ich weiß nicht ein Linux-System mit einer Matlab-Lizenz haben, so kann ich nicht überprüfen:

    mex CFLAGS='-fPIC -I/usr/local/hdf5/include' LDFLAGS='-t /usr/local/hdf5/lib/libhdf5.a -lz -shared' h5_crtfile.c -v 
    
  4. Führen Sie die h5_crtfile mex-Datei. Dies läuft ohne Probleme auf meinem Rechner. Es macht nur ein H5Fcreate und H5Fclose, um "file.h5" im aktuellen Verzeichnis zu erstellen, und wenn ich file file.h5aufrufe, erhalte ich file.h5: Hierarchical Data Format (version 5) data.

Beachten Sie, dass, wenn ich einen -lhdf5 oben in Schritt 3 sind, dann bricht Matlab, wenn ich versuche, die Datei auszuführen (weil es dann Matlab dynamischen Bibliotheken, die für mich Version 1.6.5 verwendet), so ist dies Definitiv das Problem auf meinem System zu lösen.

Danke für die Frage. Meine obige Lösung ist definitiv viel einfacher für mich als das, was ich vorher gemacht habe. Hoffentlich funktioniert das oben genannte für Sie.

+0

hmmm. wenn ich das versuche, schlägt die Kompilierung fehl b/c 'libmat.so' basiert auf' libhdf5.so'. etwas Seltsames dort. Leider kann ich "mex.h" nicht mit einschließen, ohne auch Mathworks 'hdf5 einzubinden; Leider enthalten die von Mathworks verteilten Header-Dateien nicht "hdf5.h". – shabbychef

+0

OK, ich habe die Post neu geschrieben, sehen Sie, wie das geht. – Ramashalanka

+0

Ich kompiliere in der Shell mit GCC-Befehlen von Mex gespuckt. Also habe ich Ihre Lösung ausprobiert, überspringe die Schritte 2 & 3; ('-bundle' ist Darwin-spezifisch, BTW) benutze 'h5_crtfile.c', bekomme ich" Warnung! Die HDF5-Header-Dateien, die von dieser Anwendung enthalten sind, stimmen nicht mit der -Version überein die HDF5 Bibliothek, auf die diese Anwendung verknüpft ist. die Daten Korruption oder Zugriffsfehler auftreten können, wenn die Anwendung weiter. ‚HDF5_DISABLE_VERSION_CHECK‘ Umgebungsvariable gesetzt, Anwendung weiter. Headers sind 1.8.4, Bibliothek 1.6.5" 'file.h5' wird jedoch erstellt! ABER, mit diesem Trick auf meinem Mex, es immer noch segfaults. – shabbychef

3

ich Ramashalanka Antwort bin zu akzeptieren, weil es mich an die exakte Lösung geführt, die ich hier nur der Vollständigkeit halber wird Post:

  1. Download hdf5-1.6.5 Bibliothek aus der hdf5 Website, und installieren Sie die Header-Dateien in einem lokalen Verzeichnis;
  2. sagen mex für „hdf5.h“ in diesem lokalen Verzeichnis zu suchen, anstatt im Standardverzeichnis (zB /usr/include.)
  3. sagt mex meinen Code und die gemeinsame Objekt-Bibliothek mit Matlab, zur Verfügung gestellt zu kompilieren und zu Do nicht Verwenden Sie die -ldfh5 Flagge in LDFLAGS.

der Befehl, den ich verwendete, im Wesentlichen:

/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 

dies durch mex in die Befehle übersetzt wird:

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++ 

diese Lösung sollte auf alle meine verschiedenen Ziel Maschinen arbeiten und mindestens bis ich auf Matlab r2009a aufrüste, was ich glaube, verwendet hdf5-1.8. Vielen Dank für all die Hilfe, sorry dafür, dass ich so dicht damit bin - ich glaube, ich war zu sehr auf die Verwendung der gepackten Version von hdf5 festgelegt, anstatt auf einen lokalen Satz von Header-Dateien.

Hinweis wäre dies alles andere als trivial gewesen, wenn Mathworks einen Satz der Header-Dateien mit der Matlab Verteilung zur Verfügung gestellt hatte ...

+0

So behandelte ich Multithread-Mex-Dateien, die Boost-Thread verknüpfen mussten. Aber es muss einen Weg geben, um es mit der Systembibliothek statt mit der in Matlab zu verknüpfen und die Segfaults auf diese Weise zu vermeiden. Es ist nicht sehr nett, in Matlab stecken zu bleiben. – Chinasaur

+0

In Bezug auf Ramashalankas hilfreiche Vorschläge kann ich auch sagen, dass ich mit meiner Boost-Thread-Verknüpfungssituation diese Problemumgehung in Linux, aber nicht in Mac machen musste; In Mac scheint es, dass der Befehl mex in den internen Versionen nicht wie in Linux verlinkt ist. – Chinasaur

+1

Etwas wie die Antwort hier: http://stackoverflow.com/questions/9927568/compiling-c11-code-as-part-of-a-matlab-mex-file könnte funktionieren (obwohl die Frage etwas anderes ist) . Ich melde mich zurück, wenn es funktioniert. – Chinasaur