Does the equivalent of dynamic-extent for foreign objects.
fli
with-dynamic-foreign-objects bindings &body body => last
bindings ::= (binding*)
binding ::= (var foreign-type &key initial-element initial-contents fill nelems size-slot)
body⇩ |
Forms to be executed with bindings in effect. |
var⇩ |
A symbol to be bound to a pointer to a foreign object. |
foreign-type⇩ |
A foreign type descriptor. |
initial-element⇩ |
The initial value of the newly allocated objects. |
initial-contents⇩ |
A list of values to initialize the contents of the newly allocated objects. |
fill⇩ |
An integer between 0 to 255. |
nelems⇩ |
An integer specifying how many copies of the object should be allocated. The default value is 1. |
size-slot⇩ |
A symbol naming a slot in the object. |
last |
The value of the last form in body. |
The macro with-dynamic-foreign-objects
binds variables according to the list bindings, and then evaluaed the forms in body as an implicit progn. Each element of bindings is a list which caused var to be bound to a pointer to a locally allocated instance of 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 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.
Windows version:
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; };
Non-Windows version:
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 1.4 An example of dynamic memory allocation.
5.2.4 Modifying a string in a C function
allocate-dynamic-foreign-object
free-foreign-object
with-coerced-pointer
Foreign Language Interface User Guide and Reference Manual - 01 Dec 2021 19:34:58