2013-10-10 10 views
6

Ho cercato di creare un'interfaccia lispy per i collegamenti CFFI (https://gitorious.org/dh-misc/hdf5/source/cb616fd619a387e3cdc927994b9ad12b6b514236 :), ma mi sono imbattuto in una situazione in cui il codice viene eseguito correttamente in SLIME che ha un'istanza SBCL come backend, ma non verrà eseguito ogni volta che eseguirò il codice solo in SBCL.Il codice viene eseguito in SLIME + SBCL ma non è semplice SBCL

Così, ho creato un fascicolo di prova che dimostra l'errore:

(asdf:load-system :cffi) 
;;(asdf:operate 'asdf:load-op :cffi) 

(defpackage :hdf5test 
    (:use :cl :cffi) 
    (:export :test)) 

(in-package :hdf5test) 

(define-foreign-library hdf5 
    (t (:default "libhdf5"))) 

(use-foreign-library hdf5) 

;; hdf types: 

(defctype size-t :uint) 
(defctype hid-t :int) 
(defctype herr-t :int) 
(defctype hsize-t :uint64) 

;; hdf constants: 

;; H5S_UNLIMITED: 2^64-1 
(defconstant +H5S-UNLIMITED+ 18446744073709551615) 

;; H5F_ACC_TRUNC 
(defconstant +H5F-ACC-TRUNC+ 2) ;; we'll see if it works 

;; H5P_DEFAULT 
(defconstant +H5P-DEFAULT+ 0) 

;; H5T types: 

(defconstant +H5P-DATASET-CREATE+ 150994953) 
(defconstant +H5T-NATIVE-INT+ 50331660) 

;; hdf functions: 

;; H5Screate_simple 
(defcfun "H5Screate_simple" hid-t 
    (rank :int) 
    (current-dims :pointer) ; const hsize_t* 
    (maximum-dims :pointer)) ; cons hsize_t* 

;; H5Fcreate 
(defcfun "H5Fcreate" hid-t 
    (filename :string) 
    (flags :uint) 
    (fcpl-id hid-t) 
    (fapl-id hid-t)) 

;; H5Pcreate 
(defcfun "H5Pcreate" hid-t 
    (cls-id hid-t)) 

;; H5Pset_chunk 
(defcfun "H5Pset_chunk" herr-t 
    (plist hid-t) 
    (ndims :int) 
    (dim :pointer)) ;; const hsize_t* 

;; H5Pset_deflate 
(defcfun "H5Pset_deflate" herr-t 
    (plist-id hid-t) 
    (level :uint)) 

;; H5Dcreate1 
(defcfun "H5Dcreate1" hid-t 
    (loc-id hid-t) 
    (name :string) 
    (type-id hid-t) 
    (space-id hid-t) 
    (dcpl-id hid-t)) 

;; H5Dclose 
(defcfun "H5Dclose" herr-t 
    (dataset-id hid-t)) 

;; H5Dwrite 
(defcfun "H5Dwrite" herr-t 
    (datset-id hid-t) 
    (mem-type-id hid-t) 
    (mem-space-id hid-t) 
    (file-space-id hid-t) 
    (xfer-plist-id hid-t) 
    (buf :pointer)) 

;; H5Fclose 
(defcfun "H5Fclose" herr-t 
    (file-id hid-t)) 

;; H5Sclose 
(defcfun "H5Sclose" herr-t 
    (space-id hid-t)) 

(defparameter *rank* 1) 

(defun test (filename) 
    (with-foreign-string (dataset-name "dataset") 
    (with-foreign-objects ((dim :int 1) 
       (dataspace-maxdim :uint64 1) 
       (memspace-maxdim :uint64 1) 
       (chunkdim :int 1) 
       (dataspace 'hid-t) 
       (dataset 'hid-t) 
       (memspace 'hid-t) 
       (cparms 'hid-t)) 
     (setf (mem-aref dim :int 0) 5) 
     (format t "dim: ~a~%" (mem-aref dim :int 0)) 
     ;;(setf (mem-aref maxdim :int 0) -1) 
     (setf (mem-aref dataspace-maxdim :uint64 0) +H5S-UNLIMITED+) 
     (setf (mem-aref memspace-maxdim :uint64 0) 5) 
     (setf (mem-aref chunkdim :int 0) 1) 
     (format t "dataspace-maxdim: ~a~%" (mem-aref dataspace-maxdim :uint64 0)) 
     (format t "memspace-maxdim: ~a~%" (mem-aref memspace-maxdim :uint64 0)) 
     ;;(with-open-hdf-file (file filename :direction :output :if-exists :supersede) 
     (let ((file (h5fcreate filename +H5F-ACC-TRUNC+ +H5P-DEFAULT+ +H5P-DEFAULT+))) 
    (setf cparms (h5pcreate +H5P-DATASET-CREATE+)) 
    (h5pset-chunk cparms *rank* chunkdim) 
    (setf dataspace (h5screate-simple *rank* dim dataspace-maxdim)) 
    (setf dataset (h5dcreate1 
       file 
       dataset-name 
       +H5T-NATIVE-INT+ 
       dataspace 
       cparms)) 
    (format t "dataspace: ~a~%" dataspace) 
    (format t "dataset: ~a~%" dataset) 
    (setf memspace (h5screate-simple *rank* dim memspace-maxdim)) 
    (with-foreign-object (data :int 5) 
     (loop for i from 0 to 4 do (setf (mem-aref data :int i) (* i i))) 
     (h5dwrite dataset +H5T-NATIVE-INT+ memspace dataspace +H5P-DEFAULT+ data)) 
    (h5dclose dataset) 
    (h5sclose memspace) 
    (h5sclose dataspace) 
    (h5fclose file))))) 

L'uscita che ricevo da correre (hdf5test: test "test.h5") di melma + SBCL è

dim: 5 
dataspace-maxdim: 18446744073709551615 
memspace-maxdim: 5 
dataspace: 67108866 
dataset: 83886080 
0 

L'uscita che ricevo da correre (hdf5test: test "test.h5") in soli SBCL è

dim: 5 
dataspace-maxdim: 18446744073709551615 
memspace-maxdim: 5 
dataspace: 67108866 
dataset: 83886080 
HDF5-DIAG: Error detected in HDF5 (1.8.10-patch1) thread 0: 
    #000: H5S.c line 1388 in H5Screate_simple(): maxdims is smaller than dims 
    major: Invalid arguments to routine 
    minor: Bad value 
HDF5-DIAG: Error detected in HDF5 (1.8.10-patch1) thread 0: 
    #000: H5Dio.c line 233 in H5Dwrite(): not a data space 
    major: Invalid arguments to routine 
    minor: Inappropriate type 
HDF5-DIAG: Error detected in HDF5 (1.8.10-patch1) thread 0: 
    #000: H5S.c line 405 in H5Sclose(): not a dataspace 
    major: Invalid arguments to routine 
    minor: Inappropriate type 
0 

Così si può vedere che è Somet ha a che fare con il modo in cui l'array viene passato alle funzioni hdf, ma non ho idea del perché SLIME + SBCL possa gestire questo ma non SBCL.

Ho anche provato lo stesso codice esatto con CLISP e funziona perfettamente, nessun problema, quindi sembra essere un problema SBCL.

Qualche idea su questo?

MODIFICA: ho pensato di aggiungere al post principale che i file risultanti sono veramente diversi in ogni caso. In SLIME + SBCL o CLISP il file contiene un set di dati finito con interi quadrati all'interno (senza motivo, solo un test). Ma con il semplice SBCL il file di dati è incompleto; se si tenta di visualizzare i contenuti con h5dump, si tratta di una prova senza fine di zero (è così che gestisce i set di dati incompleti).

+1

cosa significa 'corre'? come si compila e si esegue il codice sotto SLIME/SBCL e SBCl? –

+1

In SLIME + SBCL, o carico direttamente nel REPL di melma con la funzione (carica ...), oppure uso il collegamento C-c em-lc per caricare il file nell'immagine della lista. Sotto solo SBCL, utilizzo la funzione (carica ...) o eseguo sbcl con l'opzione --load. Per eseguire, faccio solo (hdf5test: test "test.h5") nel REPL. – ghollisjr

+0

BTW questo codice richiede l'installazione di librerie C HDF5 per l'esecuzione. – ghollisjr

risposta

1

Come ha scritto @nixeagle, la melma sembra nascondere i messaggi di errore originati nella libreria hdf5. Lungo queste linee scommetto che passare i risultati da SBCL a emacs in slime è ciò che consente di scrivere il file.

Ora è necessario eseguire alcune operazioni con alcuni granelli di sale, poiché in realtà non so nulla di hdf5 o cffi e ora sto tornando alla lisp comune, ma le cose hanno iniziato a funzionare in modo coerente sia in slime che in sbcl sulla mia x86_64 linux box, una volta sostituiti tutti i tipi :int con :uint64, il che sembra avere senso, poiché le dichiarazioni si risolvono comunque su quel tipo.

il codice in SBCL:

* (load "temp.lisp") 
T 
* (hdf5test:test "test2.h5") 
dim: 5 
dataspace-maxdim: 18446744073709551615 
memspace-maxdim: 5 
dataspace: 67108866 
dataset: 83886080 
HDF5-DIAG: Error detected in HDF5 (1.8.12) thread 0: 
    #000: H5S.c line 1388 in H5Screate_simple(): maxdims is smaller than dims 
    major: Invalid arguments to routine 
    minor: Bad value 
HDF5-DIAG: Error detected in HDF5 (1.8.12) thread 0: 
    #000: H5Dio.c line 231 in H5Dwrite(): can't prepare for writing data 
    major: Dataset 
    minor: Write failed 
    #001: H5Dio.c line 332 in H5D__pre_write(): not a data space 
    major: Invalid arguments to routine 
    minor: Inappropriate type 
HDF5-DIAG: Error detected in HDF5 (1.8.12) thread 0: 
    #000: H5S.c line 405 in H5Sclose(): not a dataspace 
    major: Invalid arguments to routine 
    minor: Inappropriate type 
0 

parte con i cambiamenti:

(with-foreign-objects ((dim :uint64 1) 
       (dataspace-maxdim :uint64 1) 
       (memspace-maxdim :uint64 1) 
       (chunkdim :uint64 1) 
       (dataspace 'hid-t) 
       (dataset 'hid-t) 
       (memspace 'hid-t) 
       (cparms 'hid-t)) 
     (setf (mem-aref dim :uint64 0) 5) 
     (format t "dim: ~a~%" (mem-aref dim :uint64 0)) 
     ;;(setf (mem-aref maxdim :int 0) -1) 
     (setf (mem-aref dataspace-maxdim :uint64 0) +H5S-UNLIMITED+) 
     (setf (mem-aref memspace-maxdim :uint64 0) 5) 
     (setf (mem-aref chunkdim :uint64 0) 1) 
     (format t "dataspace-maxdim: ~a~%" (mem-aref dataspace-maxdim :uint64 0)) 
     (format t "memspace-maxdim: ~a~%" (mem-aref memspace-maxdim :uint64 0)) 

cambiato il codice in SBCL:

* (load "temp.lisp") 
T 
* (hdf5test:test "test2.h5") 
dim: 5 
dataspace-maxdim: 18446744073709551615 
memspace-maxdim: 5 
dataspace: 67108866 
dataset: 83886080 
0 

file dei risultati:

% h5dump test.h5 
HDF5 "test.h5" { 
GROUP "/" { 
    DATASET "dataset" { 
     DATATYPE H5T_STD_I32LE 
     DATASPACE SIMPLE { (5)/(H5S_UNLIMITED) } 
     DATA { 
     (0): 0, 1, 4, 9, 16 
     } 
    } 
} 
} 
% h5dump test2.h5 
HDF5 "test2.h5" { 
GROUP "/" { 
    DATASET "dataset" { 
     DATATYPE H5T_STD_I32LE 
     DATASPACE SIMPLE { (5)/(H5S_UNLIMITED) } 
     DATA { 
     (0): 0, 1, 4, 9, 16 
     } 
    } 
} 
} 
+0

Ho appena controllato la tua soluzione e funziona anche sulla mia macchina! – ghollisjr

+0

Non so perché SBCL ma non SLIME + SBCL e CLISP falliscono, ma posso confermare che le variabili dim essendo: int è in realtà sbagliato, quindi probabilmente non è così importante perché diverse implementazioni gestiscono il codice buggy in modo diverso. – ghollisjr

Problemi correlati