[Cffi-devel] Fw: readded broken link from last post

Willem Rein Oudshoorn woudshoo at xs4all.nl
Sat Apr 26 13:05:49 UTC 2014


Joeish W <joeish80829 at yahoo.com> writes:

> Thank you very much for all the help recently,   actually the Rect is
> a OpenCv C class here:
> http://docs.opencv.org/trunk/modules/core/doc/basic_structures.html?highlight=rect#Rect_...does
> your advice on making a defcstruct for it stand..

Hm, maybe not.  But I do not know exactly what you need to do.

> Remember, the same
> code works evaluating the same way at the REPL creating a
> vector<Rectt> like this:
>
>
> Functions:
>
> ;; template < class T, class Alloc = allocator<T> > class vector
> ;; vector_##t * carray_to_std_vector##tn( t * a, size_t len )
> (defcfun ("carray_to_std_vectorr" %c-arr-to-vector-rect) (:pointer vector-rect)
>   (a :pointer)
>   (len :unsigned-int))

It helps if you include or points to the C-functions
carray_to_std_vectorr and std_vectorr_to_carray, because now I have to
guess what they do.

[Some code omitted]

> (%c-arr-to-vector-rect
>          (foreign-alloc :pointer :initial-contents 
>                 (list (rect 1 2 3 4) 
>                       (rect 5 6 7 8))) 2)
>

I am assuming `rect` is a function which calls a defcfun wrapper to
create a Rect.


> VECTOR-RECT-SIZE just gets the size of the vector
>
>
> (dotimes (ic (%vector-rect-size faces))
> (setf n (%vector-rect-to-c-array faces))
> (format t "~a~%" (rect-x (mem-aref n :pointer ic))))
> ; 
> ; caught WARNING:
> ;   undefined variable: N
> ; 
> ; compilation unit finished
> ;   Undefined variable:
> ;     N
> ;   caught 1 WARNING condition
> 1 <-- both x values
> 5

Yes, this works. However most likely not in the way you think it does.
I think the following is happening:

1. The call to %c-arr-to-vector-rect gets two arguments:
   a. A pointer to a block of memory containging two pointers to
      instances of Rect.

      Argument 1: ---->   [pointer a |  pointer b ]  --> [RECT: 5 6 7 8]
                            |
                            v
                       [RECT: 1 2 3 4]

      Argument 2:  2

2. The function `carray_to_std_vectorr` takes these two arguments to do
   the following:

   a. Create an array of 2 rectangles like this:

          [ [RECT: * * * *] | [RECT: * * * *] ]

   b. Copies the content of Argument 1 into this array:

          [ [RECT: pointer a pointer b * *] | [RECT: * * * *]]

   c. Returns the pointer to a vector wrapping the array constructed above.

Now you can see that the constructed vector<Rect> is garbage.  
But when you retrieve in lisp the values of this array you assume that
the array is an array of pointers.  And as such it ignores it should be
RECTs and just sees two pointers, pointer a and pointer b.

Now your `rect-x` expects pointers and therefore it works.

So it does work, but only because both mistakes (when creating the
vector and when reading the vector) cancel each other out.
If you use the array of rectangles in the OpenCV API, the OpenCV code
will see garbage.

(Note I cannot see all the code, because you give snippets without the
underlying C-code and data structures, so I cannot be absolutely sure
but I am pretty confident that this is what is going on.)

Wim Oudshoorn.





More information about the cffi-devel mailing list