Интерпретировать внешнюю память как память LISP (или наоборот) без копирования данных - PullRequest
0 голосов
/ 19 ноября 2018

Я пытаюсь записать BLOB в базу данных - порция за порцией, используя C-функцию API базы данных (скажем, 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 для Large, и цикл может повторяться много раз.Кроме того, весь этот код может быть обернут внешним циклом (например, массовой вставкой).Итак, я хочу минимизировать количество шагов в теле цикла (ов).

Чтобы это сделать, мне нужно:

  • , чтобы можно было прочитать последовательность, а нев потоковый буфер, но напрямую в чужой буфер, например:

    (read-sequence (coerce foreign-buffer '(vector/array ...)) MY-STREAM)
    
  • или чтобы иметь возможность интерпретировать потоковый буфер как внешнюю память, например:

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

Можно ли решить мою проблему, используя только один буфер - собственный или внешний, без копирования памяти между ними?

1 Ответ

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.

...