Передача структур по значению с помощью cffi-libffi?
У меня сложилось впечатление, что CFFI не может передать структуры по значению, но документация CFFI гласит:
Чтобы передать или вернуть структуру по значению функции, загрузите систему cffi-libffi и задайте структуру как
(:struct structure-name)
, Чтобы передать или вернуть указатель, вы можете использовать либо:pointer
или же(:pointer (:struct structure-name))
,
Я переупаковываю функцию cl-opencv get-size
, которая является оберткой для этой функции opencv:
CvSize cvGetSize(const CvArr* arr)
и поскольку я не думаю, что CFFI имел возможность передавать структуры по значению с помощью системы cffi-libffi, когда автор cl-opencv написал библиотеку, ему пришлось использовать весь следующий код для переноса cvGetSize
:
(defmacro make-structure-serializers (struct slot1 slot2)
"Create a serialization and deserialization function for the
structure STRUCT with integer slots SLOT1 and SLOT2. These functions
will pack and unpack the structure into an INT64."
(let ((pack-fn (intern (concatenate 'string (string struct)
(string '->int64))))
(slot1-fn (intern (concatenate 'string (string struct) "-"
(string slot1))))
(slot2-fn (intern (concatenate 'string (string struct) "-"
(string slot2))))
(unpack-fn (intern (concatenate 'string (string 'int64->)
(string struct))))
(make-fn (intern (concatenate 'string (string 'make-)
(string struct)))))
`(progn
(defun ,pack-fn (s)
(+ (,slot1-fn s) (ash (,slot2-fn s) 32)))
(defun ,unpack-fn (n)
(,make-fn ,slot1 (logand n #x00000000ffffffff)
,slot2 (ash n -32))))))
;; CvSize - Input = (defparameter a (make-size :width 640 :height 480)) Output = #S(SIZE :WIDTH 640 :HEIGHT 480) for
;; following the two.
(defstruct size (width 0) (height 0))
(make-structure-serializers :size :width :height)
;; CvSize cvGetSize(const CvArr* arr)
(cffi:defcfun ("cvGetSize" %get-size) :int64
(arr cv-array))
(defun get-size (arr)
"Get the dimensions of the OpenCV array ARR. Return a size struct with the
dimensions."
(let ((nsize (%get-size arr)))
(int64->size nsize)))
Учитывая документацию CFFI, приведенную выше, как бы мне это передать? cvGetSize
структура CvSize
по значению?
Я намереваюсь обновить пакет cl-opencv, и я хотел бы знать, где и как в пакете cl-opencv я бы "загрузил систему cffi-libffi" согласно документации CFFI, а где "указать структуру как (:struct structure-name)
"и" использовать либо: указатель, либо (: указатель (: имя структуры структуры))" " чтобы передать или вернуть указатель."
Я мог бы использовать подробные инструкции о том, как сделать это, используя выше cvGetSize
обертка:
;; CvSize cvGetSize(const CvArr* arr)
(cffi:defcfun ("cvGetSize" %get-size) :int64
(arr cv-array))
(defun get-size (arr)
"Get the dimensions of the OpenCV array ARR. Return a size struct with the
dimensions."
(let ((nsize (%get-size arr)))
(int64->size nsize)))
Редактировать для @Rörd
Я ценю ваш ответ
В любом случае я получаю ту же ошибку... но в целях тестирования, скажем, я загружаю cffi-libffi в мою текущую сессию следующим образом (с выводом)
CL-OPENCV> (asdf:oos 'asdf:load-op :cffi-libffi)
#<ASDF:LOAD-OP NIL {10076CCF13}>
NIL
он загружается, поэтому я запускаю только defcfun и defcstruct, которые вы указали следующим образом (с выводом):
CL-OPENCV> (cffi:defcstruct cv-size
(width :int)
(height :int))
(:STRUCT CV-SIZE)
CL-OPENCV>
(defcfun ("cvGetSize" %get-size) (:struct cv-size)
(arr cv-array))
; in: DEFCFUN ("cvGetSize" %GET-SIZE)
; ("cvGetSize" CL-OPENCV::%GET-SIZE)
;
; caught ERROR:
; illegal function call
;
; compilation unit finished
; caught 1 ERROR condition
Execution of a form compiled with errors.
Form:
("cvGetSize" %GET-SIZE)
Compile-time error:
illegal function call
[Condition of type SB-INT:COMPILED-PROGRAM-ERROR]
Restarts:
0: [RETRY] Retry SLIME REPL evaluation request.
1: [*ABORT] Return to SLIME's top level.
2: [ABORT] Abort thread (#<THREAD "repl-thread" RUNNING {1007BA8063}>)
Backtrace:
0: ((LAMBDA ()))
[No Locals]
1: (SB-INT:SIMPLE-EVAL-IN-LEXENV ("cvGetSize" %GET-SIZE) #<NULL-LEXENV>)
Locals:
SB-DEBUG::ARG-0 = ("cvGetSize" %GET-SIZE)
SB-DEBUG::ARG-1 = #<NULL-LEXENV>
2: (SB-INT:SIMPLE-EVAL-IN-LEXENV (DEFCFUN ("cvGetSize" %GET-SIZE) (:STRUCT CV-SIZE) (ARR CV-ARRAY)) #<NULL-LEXENV>)
Locals:
SB-DEBUG::ARG-0 = (DEFCFUN ("cvGetSize" %GET-SIZE) (:STRUCT CV-SIZE) (ARR CV-ARRAY))
SB-DEBUG::ARG-1 = #<NULL-LEXENV>
3: (EVAL (DEFCFUN ("cvGetSize" %GET-SIZE) (:STRUCT CV-SIZE) (ARR CV-ARRAY)))
Locals:
Я знаю, что libffi установлен правильно, потому что с загруженным gsll (который использует cffi-libffi) я запускаю тесты gsll, и они все проходят, как показано здесь (с выводом)
(ql:quickload "lisp-unit")
(in-package :gsl)
(lisp-unit:run-tests)
To load "lisp-unit":
Load 1 ASDF system:
lisp-unit
Loading "lisp-unit"
..................................
Unit Test Summary
| 4023 assertions total
| 4022 passed
| 1 failed
| 0 execution errors
| 0 missing tests
#<TEST-RESULTS-DB Total(4023) Passed(4022) Failed(1) Errors(0)>
Кажется, он не вызывает defcfun с (:struct cv-size) в качестве проблемы, потому что, когда я называю это как
(defcfun ("cvGetSize" %get-size) cv-size
(arr cv-array))
я получаю ту же ошибку
Execution of a form compiled with errors.
Form:
("cvGetSize" %GET-SIZE)
Compile-time error:
Я могу запустить мою структуру ipl-изображения, хотя, как это
CL-OPENCV> ;; ;(cffi:foreign-type-size '(:struct ipl-image)) = 144
(cffi:defcstruct ipl-image
(n-size :int)
(id :int)
(n-channels :int)
(alpha-channel :int)
(depth :int)
(color-model :pointer)
(channel-seq :pointer)
(data-order :int)
(origin :int)
(align :int)
(width :int)
(height :int)
(roi :pointer)
(mask-roi :pointer)
(image-id :pointer)
(tile-info :pointer)
(image-size :int)
(image-data :string)
(width-step :int)
(border-mode :pointer)
(border-const :pointer)
(image-data-origin :string))
output>(:STRUCT IPL-IMAGE)
и моя обертка create-image теперь с загруженным cffi-libffi и ваша (:struct ipl-image) на ней работает нормально, хотя... показывается с выводом
;; IplImage* cvCreateImage(CvSize size, int depth, int channels)
(cffi:defcfun ("cvCreateImage" %create-image) (:struct ipl-image)
(size :int64)
(depth :int)
(channels :int))
(defun create-image (size depth channels)
"Create an image with dimensions given by SIZE, DEPTH bits per
channel, and CHANNELS number of channels."
(let ((nsize (size->int64 size)))
(%create-image nsize depth channels)))
СОЗДАТЬ-IMAGE
но когда я бегу
(defparameter img-size (make-size :width 640 :height 480))
(defparameter img (create-image img-size +ipl-depth-8u+ 1))
создать изображение при repl ничего не происходит repl просто зависает...
но когда я запускаю оболочку создания изображения с ipl-изображением вместо (:struct ipl-image)
я могу запустить:
(defparameter img-size (make-size :width 640 :height 480))
(defparameter img (create-image img-size +ipl-depth-8u+ 1))
хорошо, затем запустите это для доступа к значениям структуры (с выходом)
(cffi:with-foreign-slots ((
n-size
id
n-channels
alpha-channel
depth
color-model
channel-seq
data-order
origin
align
width
height
roi
mask-roi
image-id
tile-info
image-size
image-data
width-step
border-mode
border-const
image-data-origin) img (:struct ipl-image))
(cffi:mem-ref img :char )
(format t "n-size ~a ~%" n-size)
(format t "id ~a ~%" id)
(format t "n-channels ~a ~%" n-channels)
(format t "alpha-channel ~a ~%" alpha-channel)
(format t "depth ~a ~%" depth)
(format t "color-model ~a ~%" color-model)
(format t "channel-seq ~a ~%" channel-seq)
(format t "data-order ~a ~%" data-order)
(format t "origin ~a ~%" origin)
(format t "align ~a ~%" align)
(format t "width ~a ~%" width)
(format t "height ~a ~%" height)
(format t "roi ~a ~%" roi)
(format t "mask-roi ~a ~%" mask-roi)
(format t "image-id ~a ~%" image-id)
(format t "tile-info ~a ~%" tile-info)
(format t "image-size ~a ~%" image-size)
(format t "image-data ~a ~%" image-data)
(format t "width-step ~a ~%" width-step)
(format t "border-mode ~a ~%" border-mode)
(format t "border-const ~a ~%" border-const)
(format t "image-data-origin ~a ~%" image-data-origin))
output>
n-size 144
id 0
n-channels 1
alpha-channel 0
depth 8
color-model #.(SB-SYS:INT-SAP #X59415247)
channel-seq #.(SB-SYS:INT-SAP #X400000000)
data-order 640
origin 480
align 0
width 0
height 0
roi #.(SB-SYS:INT-SAP #X00000000)
mask-roi #.(SB-SYS:INT-SAP #X00000000)
image-id #.(SB-SYS:INT-SAP #X0004B000)
tile-info #.(SB-SYS:INT-SAP #X7FFFF7F04020)
image-size 640
image-data NIL
width-step 0
border-mode #.(SB-SYS:INT-SAP #X00000000)
border-const #.(SB-SYS:INT-SAP #X00000000)
image-data-origin
но я не получаю структуру по значению я получаю
color-model #.(SB-SYS:INT-SAP #X59415247)
который, когда я cout это значение img->colorModel в с этим
IplImage* img=cvCreateImage(cvSize(640,480), IPL_DEPTH_8U, 3);
cout << "colorModel = " << endl << " " << img->colorModel << endl << endl;
output> colorModel =
RGB
поэтому любая помощь будет высоко ценится
хорошо, еще 1 редактировать:
Я попробовал еще раз, и это сработало, вот мой вывод
CL-OPENCV> (asdf:oos 'asdf:load-op :cffi-libffi)
#<ASDF:LOAD-OP NIL {1006D7B1F3}>
NIL
CL-OPENCV>
;; ;(cffi:foreign-type-size '(:struct cv-size)) = 8
(cffi:defcstruct cv-size
(width :int)
(height :int))
;; CvSize cvGetSize(const CvArr* arr)
(cffi:defcfun ("cvGetSize" %get-size) (:struct cv-size)
(arr cv-array))
STYLE-WARNING: redefining CL-OPENCV::%GET-SIZE in DEFUN
%GET-SIZE
CL-OPENCV>
(defparameter img-size (make-size :width 640 :height 480))
(defparameter img (create-image img-size +ipl-depth-8u+ 1))
IMG
CL-OPENCV>
(defparameter size (%get-size img))
SIZE
CL-OPENCV> size
(HEIGHT 480 WIDTH 640)
CL-OPENCV>
не знаю, что я сделал неправильно в первый раз, но... если вы можете проверить мои результаты и убедиться, что я только что передал структуру по значению, я был бы всегда благодарен
спасибо Рорд
хорошо, еще одно редактирование, если вы все еще заинтересованы в том, чтобы помочь мне отладить Rord
если получаю ошибку:
The value (HEIGHT 480 WIDTH 640)
is not of type
SB-SYS:SYSTEM-AREA-POINTER.
[Condition of type TYPE-ERROR]
и вот история, которая его вызвала (это произошло сразу после того, как я опубликовал prev. edit, так что в моем emacs все еще загружен код prev. edit s):
CL-OPENCV> (defun get-size (arr)
"Get the dimensions of the OpenCV array ARR. Return a size struct with the
dimensions."
(cffi:with-foreign-slots ((width height) (%get-size arr) (:struct cv-size))
(make-size :width width :height height)))
STYLE-WARNING: redefining CL-OPENCV:GET-SIZE in DEFUN
GET-SIZE
CL-OPENCV>
(defparameter img-size (make-size :width 640 :height 480))
(defparameter img (create-image img-size +ipl-depth-8u+ 1))
IMG
CL-OPENCV>
(defparameter size (get-size img))
The value (HEIGHT 480 WIDTH 640)
is not of type
SB-SYS:SYSTEM-AREA-POINTER.
[Condition of type TYPE-ERROR]
Я понимаю это, потому что:
(defparameter size (get-size img))
обращается к вашему defun... я проследил это так, когда я просто бегу - показано с выводом:
CL-OPENCV>
;; ;(cffi:foreign-type-size '(:struct cv-size)) = 8
(cffi:defcstruct cv-size
(width :int)
(height :int))
;; CvSize cvGetSize(const CvArr* arr)
(cffi:defcfun ("cvGetSize" %get-size) (:struct cv-size)
(arr cv-array))
STYLE-WARNING: redefining CL-OPENCV::%GET-SIZE in DEFUN
%GET-SIZE
CL-OPENCV> (defparameter capture (create-camera-capture 0))
CAPTURE
CL-OPENCV> (defparameter frame (query-frame capture))
FRAME
CL-OPENCV>
(defparameter size (%get-size frame))
SIZE
CL-OPENCV> size
(HEIGHT 480 WIDTH 640)
CL-OPENCV> (cffi:with-foreign-slots ((width height) size (:struct cv-size))
(list width height ))
я получаю ошибку:
The value (HEIGHT 480 WIDTH 640)
is not of type
SB-SYS:SYSTEM-AREA-POINTER.
[Condition of type
Я думаю, потому что выход вашего defcfun - это просто список, а with-foreign-slots нужен указатель
я запустил это:
(HEIGHT 480 WIDTH 640)
CL-OPENCV> (first size)
HEIGHT
проверить и его просто список
Кстати, я использовал эти функции для тестирования
(defparameter capture (create-camera-capture 0))
(defparameter frame (query-frame capture))
потому что у них более чистый вывод... create-image использует хакерство get-size, которое я изначально разместил вверху?
Я хотел бы использовать create-image и get-size без всех хакерских атак и просто использовать структуры для возвратов, чтобы я мог прекратить использовать make-size и сделать его более чистым... поэтому любой совет по этому поводу быть золотым... вот как я хотел бы создать create-image... я просто должен заставить его принять вывод из вашего (Rord's) defcfun... я сейчас пытаюсь включить ваш вывод defcfun ((HEIGHT 480 ШИРИНА 640)) до указателя... так он просто запустится в этом
;; IplImage* cvCreateImage(CvSize size, int depth, int channels)
(cffi:defcfun ("cvCreateImage" %create-image) ipl-image
(size cv-size)
(depth :int)
(channels :int))
или все дело в том, что размер должен быть необходимостью...
Кроме того, я изменил Defun вы добавили в
(defun get-size (arr)
"Get the dimensions of the OpenCV array ARR. Return a size struct with the
dimensions."
(setf arr (%get-size arr))
(make-size :width (cadddr arr) :height (cadr arr)))
и это работает сейчас... все еще любопытно, если я что-то напутал, и если бы ваш defun был бы лучше
РЕДАКТИРОВАТЬ!!!! Я ПОЛУЧИЛ ЭТО ВСЕ ФИГУРЫ!!!!!
here is the repl output :
; SLIME 2012-05-25
CL-OPENCV> ;; CvSize cvGetSize(const CvArr* arr)
(cffi:defcfun ("cvGetSize" get-size) (:pointer (:struct cv-size))
(arr cv-array))
STYLE-WARNING: redefining CL-OPENCV:GET-SIZE in DEFUN
GET-SIZE
CL-OPENCV> ;; IplImage* cvCreateImage(CvSize size, int depth, int channels)
(cffi:defcfun ("cvCreateImage" create-image) (:pointer (:struct ipl-image))
(size (:pointer (:struct ipl-image)))
(depth :int)
(channels :int))
STYLE-WARNING: redefining CL-OPENCV:CREATE-IMAGE in DEFUN
CREATE-IMAGE
CL-OPENCV> (defun detect-red-objects (&optional (camera-index 0))
"Uses IN-RANGE-SCALAR to detect red objects"
(with-capture (capture (create-camera-capture camera-index))
(let ((window-name-1 "Video")
(window-name-2 "Ball"))
(named-window window-name-1)
(named-window window-name-2)
(move-window window-name-1 290 225)
(move-window window-name-2 940 225)
(do* ((frame (query-frame capture) (query-frame capture))
(img (clone-image frame))
(frame (clone-image img))
(img-size (get-size frame))
(img-hsv (create-image img-size +ipl-depth-8u+ 3))
(img-hsv-size (get-size img-hsv))
(img-thresh (create-image img-hsv-size +ipl-depth-8u+ 1))
(scalar-1 (make-cv-scalar 170.0 160.0 60.0))
(scalar-2 (make-cv-scalar 180.0 256.0 256.0)))
((plusp (wait-key *millis-per-frame*)) nil)
(smooth frame frame +gaussian+ 3 3)
(cvt-color frame img-hsv +bgr2hsv+)
(in-range-s img-hsv scalar-1 scalar-2 img-thresh)
(smooth img-thresh img-thresh +gaussian+ 3 3)
(show-image window-name-1 frame)
(show-image window-name-2 img-thresh))
(destroy-all-windows))))
DETECT-RED-OBJECTS
(the function detect-red-objects runs btw!...
РЕДАКТИРОВАТЬ!!!! Я ПОЛУЧИЛ ЭТО ВСЕ ФИГУРЫ!!!!!... Часть.... II - Еще лучше!
I messed up the struct on create-image the first time but it still ran...weird...but it runs when put the create-image struct back to cv-size....so no prob there...here is revised repl output
; SLIME 2012-05-25
CL-OPENCV> ;; CvSize cvGetSize(const CvArr* arr)
(cffi:defcfun ("cvGetSize" get-size) (:pointer (:struct cv-size))
(arr cv-array))
STYLE-WARNING: redefining CL-OPENCV:GET-SIZE in DEFUN
GET-SIZE
CL-OPENCV> ;; IplImage* cvCreateImage(CvSize size, int depth, int channels)
(cffi:defcfun ("cvCreateImage" create-image) (:pointer (:struct ipl-image))
(size (:pointer (:struct cv-size)))
(depth :int)
(channels :int))
STYLE-WARNING: redefining CL-OPENCV:CREATE-IMAGE in DEFUN
CREATE-IMAGE
CL-OPENCV> (defun detect-red-objects (&optional (camera-index 0))
"Uses IN-RANGE-SCALAR to detect red objects"
(with-capture (capture (create-camera-capture camera-index))
(let ((window-name-1 "Video")
(window-name-2 "Ball"))
(named-window window-name-1)
(named-window window-name-2)
(move-window window-name-1 290 225)
(move-window window-name-2 940 225)
(do* ((frame (query-frame capture) (query-frame capture))
(img (clone-image frame))
(frame (clone-image img))
(img-size (get-size frame))
(img-hsv (create-image img-size +ipl-depth-8u+ 3))
(img-hsv-size (get-size img-hsv))
(img-thresh (create-image img-hsv-size +ipl-depth-8u+ 1))
(scalar-1 (make-cv-scalar 170.0 160.0 60.0))
(scalar-2 (make-cv-scalar 180.0 256.0 256.0)))
((plusp (wait-key *millis-per-frame*)) nil)
(smooth frame frame +gaussian+ 3 3)
(cvt-color frame img-hsv +bgr2hsv+)
(in-range-s img-hsv scalar-1 scalar-2 img-thresh)
(smooth img-thresh img-thresh +gaussian+ 3 3)
(show-image window-name-1 frame)
(show-image window-name-2 img-thresh))
(destroy-all-windows))))
DETECT-RED-OBJECTS
@Liam Edit
хорошо, я попробовал ваш метод translate-from-foreign, и он сработал, я определил их в моем файле structs.lisp
(cffi:defcstruct (cv-size :class cv-size-type)
(width :int)
(height :int))
(defmethod cffi:translate-from-foreign (p (type cv-size-type))
(let ((plist (call-next-method)))
(make-size :width (getf plist 'width)
:height (getf plist 'height))))
и get-size и create-image определяются следующим образом
;; CvSize cvGetSize(const CvArr* arr)
(cffi:defcfun ("cvGetSize" get-size) (:struct cv-size)
(arr cv-arr))
;; IplImage* cvCreateImage(CvSize size, int depth, int channels)
(cffi:defcfun ("cvCreateImage" %create-image) ipl-image
(size :int64)
(depth :int)
(channels :int))
(defun create-image (size depth channels)
"Create an image with dimensions given by SIZE, DEPTH bits per
channel, and CHANNELS number of channels."
(let ((nsize (size->int64 size)))
(%create-image nsize depth channels)))
вот определение размера->int64
(DEFUN SIZE->INT64 (S) (+ (SIZE-WIDTH S) (ASH (SIZE-HEIGHT S) 32)))
но мне нравится идея иностранного переводчика
так что мне было интересно, если вы покажете мне, как сделать переведенную на иностранную версию приведенного ниже метода from, это действительно заставило бы мою библиотеку петь... Я собираюсь сделать полную оболочку cffi для opencv и gsll это gsl, так что это действительно помогло бы, чтобы это произошло быстрее.... Еще раз спасибо за вашу помощь на все это до сих пор
(defmethod cffi:translate-from-foreign (p (type cv-size-type))
(let ((plist (call-next-method)))
(make-size :width (getf plist 'width)
:height (getf plist 'height))))
3 ответа
Чтобы "загрузить систему cffi-libffi", вам нужно указать ее как зависимость в библиотеке .asd
файл. (Примечание: cffi-libffi требует, чтобы libffi библиотеки C была установлена в вашей системе.)
Чтобы иметь возможность использовать (:struct structure-name)
необходимо сначала определить структуру с cffi:defcstruct
, вот так (я буду предполагать, что здесь cffi:defcstruct
, cffi:defcfun
, а также cffi:with-foreign-slots
импортируются в текущий пакет):
(defcstruct cv-size
(width :int)
(height :int))
Вы можете использовать (:struct cv-size)
в defcfun
как это:
(defcfun ("cvGetSize" %get-size) (:struct cv-size)
(arr cv-array))
РЕДАКТИРОВАТЬ: Исправлено get-size
для передаваемых по стоимости структур.
И, наконец, определить get-size
как это:
(defun get-size (arr)
"Get the dimensions of the OpenCV array ARR. Return a size struct with the
dimensions."
(let ((%size (%get-size arr)))
(make-size :width (getf %size 'width)
:height (getf %size 'height))))
РЕДАКТИРОВАТЬ 2:
Если я правильно понимаю ответ Лиама, это как написать translate-from-foreign
метод, так что он создает структуру напрямую, без создания промежуточного plist:
(defmethod cffi:translate-from-foreign (p (type cv-size-type))
(with-foreign-slots ((width height) p (:struct cv-size))
(make-size :width width :height height)))
Вам не нужно определять оба %get-size
а также get-size
, Вместо этого вы можете определить
(defcstruct (cv-size :class cv-size-type)
(width :int)
(height :int))
(defmethod cffi:translate-from-foreign (p (type cv-size-type))
(let ((plist (call-next-method)))
(make-size :width (getf plist 'width)
:height (getf plist 'height))))
а затем определить функцию get-size
непосредственно с defcfun
,
Преимущество такого подхода заключается в том, что в любое время, когда у вас есть функция, которая возвращает размер cv, она будет автоматически переведена. И, если у вас есть сторонние функции, которым вы хотите передать размер cv, определите соответствующий метод для cffi: translate-into-foreign-memory. Вы также получите перевод автоматически, если вы используете mem-aref для указателя на структуру. Или, если вы вызываете cffi: convert-from-foreign.
В этом примере я использовал метод перевода по умолчанию; Вы можете, если хотите, напрямую обращаться к слотам без вызова (call-next-method).
(Кстати, причина, по которой у вас сложилось впечатление, что CFFI не может передавать структуры по значению, была в том, что он не мог до недавнего времени; cffi-libffi был представлен с выпуском 0.11.0.)
Вам просто нужно добавить :class xxx
в cffi:defcstruct
затем (cffi:defmethod translate-into-foreign-memory (object (type xxx) pointer) yyyy)
, он автоматически передаст структуру по значению сторонней функции!! Удивительно!!
А также (cffi:defmethod translate-from-foreign (pointer (type xxx)) zzzz)
преобразует возвращенные данные структуры в данные lisp.
Более подробную информацию, пожалуйста, проверьте этот ответ также мной ^_^