我尝试使用数据库API C函数(例如db-write-chunk)将BLOB逐块写入数据库。此函数将指向外部存储器(放置块)的指针作为参数。因此,我为块创建了缓冲区: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
Run Code Online (Sandbox Code Playgroud)
LBLOB中的“ Large”表示“大”,循环可能会迭代多次。除此之外,所有这些代码都可以由外部循环包装(例如,批量插入)。因此,我想最小化循环主体中的步骤数。
为此,我需要:
能够将序列读取到的不是流缓冲区,而是直接读取到外部缓冲区,如下所示:
(read-sequence (coerce foreign-buffer '(vector/array ...)) MY-STREAM)
Run Code Online (Sandbox Code Playgroud)或能够将流缓冲区解释为外部内存,如下所示:
(db-write-chunk (mem-aptr stream-buffer :uchar 0))
Run Code Online (Sandbox Code Playgroud)是否可以仅使用单个缓冲区(本机缓冲区或外部缓冲区)解决我的问题,而无需在它们之间复制内存?
小智 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))))
Run Code Online (Sandbox Code Playgroud)
根据您的使用情况,这可能比 更好static-vectors,因为您不必记住手动释放它。在 SBCL 上,这是通过在 期间固定矢量数据来实现的with-pointer-to-vector-data。