Page 1 of 1

how do i pass structs by value with cffi-libffi?

Posted: Mon Sep 23, 2013 6:38 pm
by joeish80829
I would appreciate any and all help/guidance on this. ok, Im under the impression that lisp's cffi cant pass structs by value, but the cffi documentation says:

"To pass or return a structure by value to a function, load the cffi-libffi system and specify the structure as (:struct structure-name). To pass or return the pointer, you can use either :pointer or (:pointer (:struct structure-name)). "

Im re-wrapping the cl-opencv function get-size, which is a wrapper for this opencv function...

CvSize cvGetSize(const CvArr* arr)

and since i don't think cffi had the ability to pass structs by value, with the cffi-libffi system, when the author of cl-opencv wrote the library, so he had to use all of the below code to wrap..cvGetSize

Code: Select all

 (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)))
so now how, with the cffi-libffi system, as outlined in the cffi documentation here:

"To pass or return a structure by value to a function, load the cffi-libffi system and specify the structure as (:struct structure-name). To pass or return the pointer, you can use either :pointer or (:pointer (:struct structure-name)). "

would i pass this cvGetSize struct...CvSize by value.....pls give me detailed instructions....I'll be updating the cl-opencv package which is available here:

https://github.com/ryepup/cl-opencv

i would like to know where and how in the cl-opencv package i "load the cffi-libffi system" as the cffi documentation states....and the cffi documentation says "and specify the structure as (:struct structure-name). To pass or return the pointer, you can use either :pointer or (:pointer (:struct structure-name))." I could use detailed instructions on how to do that using the above cvGetSize wrapper..get-size....again here:

Code: Select all

;; 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)))

Re: how do i pass structs by value with cffi-libffi?

Posted: Fri Sep 27, 2013 7:21 pm
by nuntius
The pass-by-value feature in CFFI is relatively new and rarely needed. Thus I suspect most people this board are not familiar with it yet. Please post your question on the CFFI mailing list.

To join the list, send an email to [email protected] (address found on http://common-lisp.net/project/cffi/)

Re: how do i pass structs by value with cffi-libffi?

Posted: Thu Oct 03, 2013 7:40 am
by joeish80829
i did subscribe to the cffi mailing list like u suggested....can you give me a quick step by step on how to post ?'s on it or a link...cant seem 2 find one online =).

Re: how do i pass structs by value with cffi-libffi?

Posted: Fri Oct 04, 2013 5:45 pm
by nuntius
Just send your question to [email protected]

Subject: "how do i pass structs by value with cffi-libffi?"
Body: similar to your post here, possibly a link here.

Re: how do i pass structs by value with cffi-libffi?

Posted: Fri Oct 04, 2013 9:21 pm
by joeish80829
thank you very much =)!

Re: how do i pass structs by value with cffi-libffi?

Posted: Sat Oct 05, 2013 6:32 am
by joeish80829
one last ? on this ...when i upload my code the formatting is destroyed ....how do you upload your code to cffi-devel

Re: how do i pass structs by value with cffi-libffi?

Posted: Wed Oct 12, 2016 1:34 am
by muyinliu
You just have to add `:class xxx` to `cffi:defcstruct` then `(cffi:defmethod translate-into-foreign-memory (object (type xxx) pointer) yyyy)`, it will pass structure by value to a foreign function automatically!! Amazing!!

And `(cffi:defmethod translate-from-foreign (pointer (type xxx)) zzzz)` will convert the returned structure data into lisp data.

More details please visit this answer http://stackoverflow.com/a/39942257/2765530 also by me.