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.
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 Signature above which is supported in LispWorks 5.1 and later.
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.
Modifying a string in a C function
allocate-dynamic-foreign-object
free-foreign-object
with-coerced-pointer
LispWorks Foreign Language Interface User Guide and Reference Manual - 29 Sep 2017