Allocates memory for a list of foreign objects, executes a list of forms which may use the objects across the scope of the macro, and then deallocates the foreign objects.
with-dynamic-foreign-objects bindings &body body => last
binding ::= ( var foreign-type &key initial-element initial-contents fill nelems size-slot )
A symbol to be bound to a foreign type.
A foreign type descriptor to be bound to the variable var .
A form to be executed with bindings in effect.
The macro
with-dynamic-foreign-objects
binds variables according to the list
bindings
, and then executes
body
. Each element of
bindings
is a list which binds a symbol to a pointer which points to a locally allocated instance of a foreign type.
initial-element , initial-contents , fill , nelems and size-slot initialize the allocated instance as if by allocate-foreign-object.
The lifetime of the bound foreign objects, and hence the allocation of the memory they take up, is within the scope of the
with-dynamic-foreign-objects
function.
Any object created with allocate-dynamic-foreign-object within
body
will automatically be deallocated once the scope of the
with-dynamic-foreign-objects
function has been left.
This example shows the use of
with-dynamic-foreign-objects
with an implicitly created pointer.
typedef struct {
int one;
float two;
} foo ;
__declspec(dllexport) void __cdecl init_alloc(foo *ptr, int a, float b)
{
ptr->one = a;
ptr->two = b;
};
typedef struct {
int one;
float two;
} foo ;
void init_alloc(foo * ptr, int a, float b)
{
ptr->one = a;
ptr->two = b;
};
Here are the FLI definitions interfacing to the above C code:
(fli:define-c-typedef (foo (:foreign-name "foo"))
(:struct (one :int) (two :float)))
(fli:define-foreign-function (init-alloc "init_alloc")
((ptr (:pointer foo))
(a :int)
(b :float))
:result-type :void
:calling-convention :cdecl)
Try this test function which uses
with-dynamic-foreign-objects
to create a transient
foo
object and pointer:
(defun test-alloc (int-value float-value &optional (level 0))
(fli:with-dynamic-foreign-objects ((object foo))
(init-alloc object int-value float-value)
(format t "~%Level - ~D~& object : ~S~& slot one : ~S~& slot two : ~S~&"
level object
(fli:foreign-slot-value object 'one)
(fli:foreign-slot-value object 'two))
(when (> int-value 0)
(test-alloc (1- int-value)
(1- float-value) (1+ level)))
(when (> float-value 0)
(test-alloc (1- int-value)
(1- float-value) (1+ level)))))
(test-alloc 1 2.0)
=>
Level - 0
object : #<Pointer to type FOO = #x007E6338>
slot one : 1
slot two : 2.0
Level - 1
object : #<Pointer to type FOO = #x007E6340>
slot one : 0
slot two : 1.0
Level - 2
object : #<Pointer to type FOO = #x007E6348>
slot one : -1
slot two : 0.0
Level - 1
object : #<Pointer to type FOO = #x007E6340>
slot one : 0
slot two : 1.0
Level - 2
object : #<Pointer to type FOO = #x007E6348>
slot one : -1
slot two : 0.0
A further example using
with-dynamic-foreign-objects
and a pointer created explicitly by allocate-dynamic-foreign-object is given in An example of dynamic memory allocation.
There is an alternative syntax for binding with an optional initial-element which is the only way to supply an initial element in LispWorks 5.0 and previous versions. Like this:
binding ::= ( var foreign-type &optional initial-element )
This alternative syntax is deprecated in favor of the keyword syntax for binding defined in Signatureabove which is supported in LispWorks 5.1 and later.
allocate-dynamic-foreign-object
free-foreign-object
with-coerced-pointer
with-dynamic-foreign-objects-with-cleanups