6

我尝试使用数据库 API C 函数(例如,)将 BLOB 逐块写入数据库db-write-chunk。此函数将指向外部内存(放置块的位置)的指针作为参数。所以,我为一个块做缓冲区:foreign-buffer。我将从文件(或二进制流)中获取块read-sequence数据stream-buffer

(let ((foreign-buffer (foreign-alloc :uchar 1024)))
      (stream-buffer ((make-array 1024 :element-type '(unsigned-byte 8))))
    (loop
        for cnt = (read-sequence stream-buffer MY-STREAM)
        while (> cnt 0)
        do
          ;; copy cnt bytes from stream-buffer into foreign-buffer 
          ;; call db-write-chunk with foreign-buffer

L在 BLOB 中是大的,循环可能会迭代很多次。除此之外,所有这些代码都可能被外部循环(例如批量插入)包装。所以,我想尽量减少循环体中的步骤数。

要做到这一点,我需要:

  • 能够不将序列读入流缓冲区,而是直接读入外部缓冲区,如下所示:

    (read-sequence (coerce foreign-buffer '(vector/array ...)) MY-STREAM)
    
  • 或者能够将流缓冲区解释为外部内存,如下所示:

    (db-write-chunk (mem-aptr stream-buffer :uchar 0))
    

是否可以仅使用单个缓冲区(本机或外部缓冲区)来解决我的问题,而无需在它们之间复制内存?

4

1 回答 1

1

像其他任何 ffi 一样,这是依赖于实现的,但 cffi 具有cffi:make-shareable-byte-vector,这是一个 CL(unsigned-byte 8)数组,您可以使用它cffi:with-pointer-to-vector-data

(cffi:defcfun memset :pointer
  (ptr :pointer)
  (val :int)
  (size :int))

(let ((vec (cffi:make-shareable-byte-vector 256)))
  (cffi:with-pointer-to-vector-data (ptr vec)
    (memset ptr 0 (length vec))))

根据您的使用情况,这可能比 更可取static-vectors,因为您不必记住手动释放它。在 SBCL 上,这通过在with-pointer-to-vector-data.

于 2019-05-14T20:50:17.807 回答