我尝试使用数据库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
BLOB中的 L
适用于Large,循环可能会迭代多次。
除此之外,所有这些代码都可以由外部循环包装(例如,批量插入)。
因此,我想减少循环主体中的步骤数。
要完成此操作,我需要:
能够将序列读取到流缓冲区中,而不是直接读取到外部缓冲区中,如下所示:
(read-sequence (coerce foreign-buffer '(vector/array ...)) MY-STREAM)
,或者能够将流缓冲区解释为外部内存,如下所示:
(db-write-chunk (mem-aptr stream-buffer :uchar 0))
是否可以仅使用单个缓冲区(本机缓冲区或外部缓冲区)解决我的问题,而无需在它们之间复制内存?
答案 0 :(得分:0)
与其他任何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
期间固定矢量数据来实现。