Hello,
Kenny complained about foreign-object-alloc not being documented a few hours ago which reminded me about the foreign-alloc vs. foreign-object-alloc issue James and I briefly discussed on IRC.
I would like to experiment with a typed pointer interface (something similar to CMUCL/SBCL's Alien objects) and was planning to call those pointers "foreign objects" in which case foreign-object-alloc would be confusing since all it does is allocate raw memory.
One idea James suggested was to move foreign-object-alloc's functionality to foreign-alloc and export the lower level %foreign-alloc (renamed to malloc or something similar). [Or just have the users use foreign-alloc with a :char type, why not?]
Well, but why not improve (and hopefully not bloat) foreign-alloc. Here's a proposed interface based mostly on Lispworks's ffi:allocate-foreign-object and CL's make-array:
foreign-alloc =============
Syntax ------
-- Function: foreign-alloc type &key initial-element initial-contents (count 1) => pointer
Arguments and Values --------------------
_type_ A foreign type.
_initial-element_ A Lisp object.
_initial-contents_ A sequence.
_count_ /Note: probably :nelems would be a better name?/ An integer bigger than or equal to 1. 1, by default.
_pointer_ A foreign pointer to the newly allocated memory.
Description -----------
The `foreign-alloc' function allocates enough memory to hold _count_ objects of type _type_ and returns a _pointer_. This memory must be explicitly freed using `foreign-free' once it is no longer needed.
If _initial-element_ is supplied, it is used to initialize the _count_ objects the newly allocated memory holds.
If an _initial-contents_ sequence is supplied, it must have a length less than or equal to _count_ and each of its elements will be used to initialize the contents of the newly allocated memory. /Note: Should the remainder be zero filled?/
/Note: also is initial-contents is supplied and count isn't then count will be (length initial-contents) [plus 1, probably]. See note in the examples./
_initial-element_ and _initial-contents_ are mutually exclusive.
Examples --------
CFFI> (foreign-alloc :char) #<A Mac Pointer #x1022E0> ; A pointer to 1 byte of memory.
CFFI> (foreign-alloc :char :count 20) #<A Mac Pointer #x1022E0> ; A pointer to 20 bytes of memory.
CFFI> (foreign-alloc :int :initial-element 12) #<A Mac Pointer #x1022E0> CFFI> (mem-ref * :int) 12
CFFI> (foreign-alloc :int :initial-contents '(1 2 3)) #<A Mac Pointer #x1022E0> CFFI> (loop for i from 0 below 3 collect (mem-ref * :int i)) (1 2 3)
CFFI> (foreign-alloc :int :initial-contents #(1 2 3)) #<A Mac Pointer #x1022E0> CFFI> (loop for i from 0 below 3 collect (mem-ref * :int i)) (1 2 3)
;; Another note: what should should be in (mem-ref ** :int 3)? ;; Zero? Ie. Should these previous two calls to foreign-alloc ;; allocate 3*sizeof(int) or 4*sizeof(int) bytes? Lispworks seems to ;; do the latter.
CFFI> (foreign-alloc :string :initial-element "foo") ;; I think this should do something similar to CLISP's ;; FFI:ALLOCATE-DEEP, and it should Just Work if we apply the :to-c ;; translator, which will allocate space for "foo".
;; A problem here is freeing this memory. Should we tell the user ;; he has to free the complex stuff inside by himself. Or should we ;; come up with something similar to CLISP's FFI:FOREIGN-FREE when ;; passed ":full t". (In this case CFFI:FOREIGN-FREE would have to ;; take an optional type or something to describe what needs ;; freeing.)
Comments are most welcome.