2013-10-10 29 views
6

我一直在嘗試構建一個lispi接口到CFFI綁定(https://gitorious.org/dh-misc/hdf5/source/cb616fd619a387e3cdc927994b9ad12b6b514236 :),但是我遇到了代碼在SLIME中正確運行的情況,它有一個SBCL實例作爲後端,但只要我在SBCL中運行代碼,就不會運行。代碼在SLIME + SBCL中運行,但不是純SBCL

所以,我創建這表明該錯誤的測試用例文件:

(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))))) 

我運行得到的輸出:煤泥+ SBCL(hdf5test測試 「test.h5」)是

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

我運行得到的輸出:在短短SBCL(hdf5test測試「test.h5」)是

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 

所以,你可以看到它的舒美特與數組如何傳遞給hdf函數有關,但我不知道爲什麼SLIME + SBCL會處理這個問題,而不是SBCL。

我也嘗試了與CLISP完全相同的代碼,它工作正常,沒有問題,所以它似乎是一個SBCL問題。

對此有何看法?

編輯:我想我應該添加到主要帖子,結果文件真正在每種情況下不同。在SLIME + SBCL或CLISP中,文件包含一個內部有平方整數的有限數據集(沒有理由,只是一個測試)。但是,對於普通的SBCL,數據文件不完整;如果您嘗試使用h5dump查看內容,這是一個無休止的零試驗(這是它處理不完整的數據集的方式)。

+1

這是什麼意思'運行'?你如何在SLIME/SBCL和SBCl下編譯和運行代碼? –

+1

在SLIME + SBCL中,我使用(load ...)函數直接加載粘液REPL,或者使用C-c C-l emacs快捷方式將文件加載到列表圖像中。在SBCL下,我使用(load ...)函數或使用--load選項運行sbcl。運行我只是在REPL中執行(hdf5test:test「test.h5」)。 – ghollisjr

+0

順便說一下,此代碼確實需要安裝HDF5 C庫才能運行。 – ghollisjr

回答

1

就像@nixeagle說的,史萊姆似乎隱藏了起源於hdf5庫的錯誤信息。沿着這些路線,我願意將SBCL的結果傳給emacs,這是允許文件寫入的東西。

現在需要用幾粒鹽來做下面的事情,因爲我對hdf5或cffi一無所知,而現在我只是回到普通的lisp中,但是事情在sile和sbcl都開始工作在我的x86_64 linux機器上,一旦我用:uint64替換了所有那些:int類型,這似乎是有意義的,因爲聲明無論如何都解析爲該類型。

你的代碼在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 

部分變化在於:

(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)) 

在SBCL改變代碼:

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

結果文件:

% 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

剛剛檢查過你的解決方案,它也適用於我的機器! – ghollisjr

+0

我不知道爲什麼SBCL而不是SLIME + SBCL和CLISP失敗,但我可以確認dim變量是:int實際上是錯誤的,所以它可能不是那麼重要,爲什麼不同的實現處理錯誤代碼的方式不同。 – ghollisjr