首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >用cffi按值传递结构?

用cffi按值传递结构?
EN

Stack Overflow用户
提问于 2013-09-24 01:34:58
回答 3查看 2.3K关注 0票数 5

我的印象是,CFFI不能按值传递结构,但CFFI文档说:

若要将结构按值传递或返回给函数,请加载cffi系统并将结构指定为(:struct structure-name)。要传递或返回指针,可以使用:pointer(:pointer (:struct structure-name))

我正在重新包装cl函数get-size,它是这个opencv函数的包装:

代码语言:javascript
复制
CvSize cvGetSize(const CvArr* arr)

而且,由于当code的作者编写库时,CFFI没有能力通过cffi-libffi系统按值传递结构,所以他必须使用以下所有代码来包装cvGetSize

代码语言:javascript
复制
 (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包中我将在哪里以及如何按照CFFI文档“加载CFFI系统”,以及在哪里“将结构指定为(:struct structure-name)”和“使用:(:struct structure-name)或(:指针(:structure name)”)“传递或返回指针”。

我可以使用上面的cvGetSize包装器详细说明如何做到这一点:

代码语言:javascript
复制
;; 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加载到我的当前会话中,如下所示(输出)

代码语言:javascript
复制
CL-OPENCV> (asdf:oos 'asdf:load-op :cffi-libffi) 
#<ASDF:LOAD-OP NIL {10076CCF13}>
NIL

它会加载,所以我只运行defcfun和您提供的解结构(包括输出):

代码语言:javascript
复制
 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测试,它们都通过了这里显示的(输出)。

代码语言:javascript
复制
(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)>

它似乎并不是以(:struct cv-size)作为问题来调用defcfun,因为当我调用它时

代码语言:javascript
复制
(defcfun ("cvGetSize" %get-size) cv-size
  (arr cv-array))

我也犯了同样的错误

代码语言:javascript
复制
Execution of a form compiled with errors.
Form:
  ("cvGetSize" %GET-SIZE)
Compile-time error:

我可以像这样运行我的ipl映像结构

代码语言:javascript
复制
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)

现在我的创建映像包装器已经加载了cffi libffi,并且您的(:struct ipl-image)在它上运行得很好,尽管使用了输出的...shown。

代码语言:javascript
复制
;; 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)))

创造形象

但当我跑

代码语言:javascript
复制
(defparameter img-size (make-size :width 640 :height 480))

(defparameter img (create-image img-size +ipl-depth-8u+ 1))

在repl上创建一个图像,什么都不会发生,只会挂起.

但是,当我使用ipl-image而不是(:struct ipl- image )运行创建图像包装时

我可以运行:

代码语言:javascript
复制
 (defparameter img-size (make-size :width 640 :height 480))

 (defparameter img (create-image img-size +ipl-depth-8u+ 1))

很好,然后运行它来访问struct值(带有输出)

代码语言:javascript
复制
 (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  

但我没有得到我得到的结构

代码语言:javascript
复制
 color-model #.(SB-SYS:INT-SAP #X59415247) 

,当我在c中显示img->颜色模型时,

代码语言:javascript
复制
IplImage* img=cvCreateImage(cvSize(640,480), IPL_DEPTH_8U, 3);
cout << "colorModel = " << endl << " " << img->colorModel << endl << endl;

output> colorModel = 
 RGB

所以任何帮助都是非常感谢的

好的1再编辑:

我再试一次,它在这里起作用了,这是我的输出

代码语言:javascript
复制
  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> 

不知道我做错了什么,第一次but...if,你可以检查我的结果,并证实我刚刚通过了一个结构的价值,我将永远感激

谢谢Rord

如果您仍有兴趣帮助我调试Rord,请再进行一次编辑

如果出现错误:

代码语言:javascript
复制
  The value (HEIGHT 480 WIDTH 640)
   is not of type
   SB-SYS:SYSTEM-AREA-POINTER.
   [Condition of type TYPE-ERROR]

这是导致这种情况的原因(这是在我发布prev之后直接发生的。编辑这样我的emacs就有了所有的监考。编辑仍然加载的代码):

代码语言:javascript
复制
   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]

我明白是因为:

代码语言:javascript
复制
(defparameter size (get-size img)) 

访问你的解闷.我跟踪它所以当我运行时-用输出显示:

代码语言:javascript
复制
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 ))

我得到了错误:

代码语言:javascript
复制
The value (HEIGHT 480 WIDTH 640)
  is not of type
    SB-SYS:SYSTEM-AREA-POINTER.
     [Condition of type 

我认为这是因为你的脱逃乐趣只是一个列表,而对于外国的插槽,需要一个指针。

我查过这个:

代码语言:javascript
复制
(HEIGHT 480 WIDTH 640)
CL-OPENCV> (first size)
HEIGHT

来验证,这只是一个列表

顺便说一下,我使用这些函数进行测试。

代码语言:javascript
复制
(defparameter capture (create-camera-capture 0))

(defparameter frame (query-frame capture))

因为有一个更纯的输出.创建-图像使用的黑客获得的大小,我口头上张贴在顶部?

我想使用create-image和get-size w/o所有的hackery,只需要使用结构来返回,这样我就可以停止使用make-size并使其更多pure....so -任何关于gold...here的建议都是我想要的创建-映像.我只需要让它接受来自您的(Rord‘s) defcfun的输出.我现在正在尝试将您的defcfun输出( 480高宽640)转换为pointer...so,它将在这里运行。

代码语言:javascript
复制
;; IplImage* cvCreateImage(CvSize size, int depth, int channels)
(cffi:defcfun ("cvCreateImage" %create-image) ipl-image
  (size cv-size)
  (depth :int)
  (channels :int))

或者整个尺寸的事情都是必要的.

另外,如果我改变了你添加到

代码语言:javascript
复制
(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)))

如果我搞砸了,如果你玩的更好的话,now...still古玩就好了。

编辑!我都搞清楚了!

代码语言:javascript
复制
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!...

编辑!我都搞清楚了!...Part....II-更好!

代码语言:javascript
复制
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编辑

好的,我尝试过您的从国外翻译的方法,它确实有效,我在我的structs.lisp文件中定义了这些方法。

代码语言:javascript
复制
(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大小和创建图像的定义如下

代码语言:javascript
复制
;; 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 64的定义。

代码语言:javascript
复制
  (DEFUN SIZE->INT64 (S) (+ (SIZE-WIDTH S) (ASH (SIZE-HEIGHT S) 32)))

但我喜欢翻译

所以,我想知道你是否能告诉我如何从方法中把下面的翻译成外国版本,这真的会让我的库唱歌.我的目标是为opencv制作一个完整的cffi包装,就像gsll对gsl一样好,所以这将真正地帮助quicker....Thanks再次发生,因为你在所有这些方面的帮助。

代码语言:javascript
复制
(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))))
EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2013-09-25 12:48:29

要“加载cffi系统”,需要在库的.asd文件中将其指定为依赖项。(注意:cffi需要在您的系统上安装C库libffi。)

为了能够使用(:struct structure-name),您需要首先使用cffi:defcstruct定义结构,如下所示(在这里,我假设cffi:defcstructcffi:defcfuncffi:with-foreign-slots是在当前包中导入的):

代码语言:javascript
复制
(defcstruct cv-size
  (width :int)
  (height :int))

然后,可以在(:struct cv-size)中使用defcfun,如下所示:

代码语言:javascript
复制
(defcfun ("cvGetSize" %get-size) (:struct cv-size)
  (arr cv-array))

编辑:修正了按值传递结构的get-size .

最后,像这样定义get-size

代码语言:javascript
复制
(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:

代码语言:javascript
复制
(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)))
票数 4
EN

Stack Overflow用户

发布于 2013-09-28 23:07:37

您不必同时定义%get-sizeget-size。相反,您可以定义

代码语言:javascript
复制
(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定义适当的方法:将其转换为外部内存。如果在指向结构的指针上使用mem,也会自动获得转换。或者,如果你打电话给cffi:从国外转过来。

在本例中,我使用了默认的plist转换方法;如果您愿意,可以直接访问插槽,而无需调用(调用-下一步-方法)。

(顺便说一句,你之所以认为CFFI不能按值传递结构,是因为它直到最近才能传递;cffi是在0.11.0版中引入的。)

票数 1
EN

Stack Overflow用户

发布于 2016-10-12 08:27:17

您只需将: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数据。

更多信息请通过me^_^查看me^_^

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/18971611

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档