[Resend] How to free the array element

Huang, Ying huang_ying_caritas at 163.com
Tue Apr 14 23:38:06 UTC 2015


Hi, Luís,

Luís Oliveira <luismbo at gmail.com> writes:

> Hello Ying,
>
> On Sat, Apr 11, 2015 at 1:50 AM, Huang, Ying <huang_ying_caritas at 163.com> wrote:
>> I need to manipulate foreign array. I tried to define an extended
>> foreign array type because there are some features that are lacking in
>> foreign-array-type of cffi. I can access/assign element of foreign array
>> with cffi:mem-ref and (setf cffi:mem-ref). But I don't know how to free
>> element of foreign array (the element type can be aggregated).
>
> Indeed, in src/types.lisp:455 there's a FIXME mentioning just that!
>
>
>> I think if there is a cffi:mem-free (I know, the name is bad) like
>> cffi:mem-ref, may be this can be resolved.
>>
>> (defun mem-free (ptr type param &optional (offset 0))
>>   (let* ((parsed-type (parse-type type))
>>          (ctype (canonicalize parsed-type)))
>>     (if (aggregatep parsed-type)
>>         (free-translated-object (inc-pointer ptr offset)
>>                                 parsed-type param)
>>         (free-translated-object (%mem-ref ptr ctype offset)
>>                                 parsed-type param))))
>
> My first intuition would be to fix foreign-array-free to get a type
> argument. That way it would know how to free each element, essentially
> doing a mem-free (as you call it) for each element in the array.
>
> I've prototyped such a smarter foreign-array-free here:
> https://github.com/luismbo/cffi/commit/0a7d42720eacc32abb4338df32b4e5fceecdeb6d
>
> Your example then becomes:
>
> CFFI> (defparameter *string-array* (foreign-array-alloc #("a" "b" "c")
> '(:array :string 3)))
> *STRING-ARRAY*
> CFFI> (trace foreign-string-free)
> (FOREIGN-STRING-FREE)
> CFFI> (foreign-array-free *STRING-ARRAY* '(:array :string 3))
>   0: (FOREIGN-STRING-FREE #.(SB-SYS:INT-SAP #X002054A0))
>   0: FOREIGN-STRING-FREE returned NIL
>   0: (FOREIGN-STRING-FREE #.(SB-SYS:INT-SAP #X002054B0))
>   0: FOREIGN-STRING-FREE returned NIL
>   0: (FOREIGN-STRING-FREE #.(SB-SYS:INT-SAP #X002054C0))
>   0: FOREIGN-STRING-FREE returned NIL
> NIL
>
> Let me know what you think. :)

Yes.  That works for :string.  But how about aggregated array element
type such as :struct.

CL-USER> (defcstruct str-struct (str :string))
(:STRUCT STR-STRUCT)
CL-USER> (defparameter *str-struct-array* '(:array (:struct str-struct) 2))
*STR-STRUCT-ARRAY*
CL-USER> (convert-to-foreign #((str "a") (str "b")) *str-struct-array*)
#.(SB-SYS:INT-SAP #X7FFFEC000960)
CL-USER> (convert-from-foreign * *str-struct-array*)
#((STR "a") (STR "b"))
CL-USER> (free-converted-object ** *str-struct-array* t)
NIL

I know the :string slot in struct is not freed now.  But I think that
can be fixed too.

One possible solution is to make free-translated-object doesn't free the
aggregated foreign object itself, just its elements.  Make something
like foreign-free (should use another name) to take the type of foreign
object to be freed as paramter and call the free-translated-object for
the foreign object, the free the foreign object itself.  Or we can
define another method called something like
free-translated-object-in-memory for aggregated foreign type, which
corresponds to translate-into-memory, just like free-translated-object
corresponds to translate-to-foreign.

Best Regards,
Huang, Ying




More information about the cffi-devel mailing list