Hi, Luís, Luís Oliveira <luis...@gmail.com> writes:
> Hello Ying, > > On Sat, Apr 11, 2015 at 1:50 AM, Huang, Ying <huang_ying_cari...@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