<html><head></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space; "><div>Hi Thomas again,</div><div><br></div><div>for time reasons, I'm answering the second (or rather, first) part of your mail separately :-;</div><div><br></div><div>Just wanted to say that your code suggestion</div><div><blockquote type="cite"><div><font class="Apple-style-span" color="#000000"><br></font><br> (define (string-list->fixed-width-array width items)<br> (string-join (map (cut string-pad-right <> width #\null) items)))<br></div></blockquote><div><br></div><div><br></div><div>was even more helpful than I was aware of at first (it being always good to have code examples) :-)</div><div>I tried writing a simple null-appending and string-joining function first, but it turned out that padding every string to an equal length is a necessity, simply null-terminating them is not enough :-;</div><div><br></div><div>So thanks again,</div><div>Sigrid</div><div><br></div><div><br></div><div><br></div><div><br></div><br><blockquote type="cite"><div><br> (provide<br> (all-defined-out))<br><br><blockquote type="cite">[...]<br></blockquote><blockquote type="cite">Regarding racket garbage collection, on the one hand, and c pointer<br></blockquote><blockquote type="cite">freeing, that is generally a topic I'm very unsure about and could<br></blockquote><blockquote type="cite">perhaps use some "basic" advice (more basic than the FFI reference,<br></blockquote><blockquote type="cite">I mean). For example, do I have to explicitly "destroy" c pointers<br></blockquote><blockquote type="cite">somehow, and if so, when? In the case of my c library given, I<br></blockquote><blockquote type="cite">assume I have to implement every function like '<object>Free' and<br></blockquote><blockquote type="cite">call it when I'm done, but apart from that?<br></blockquote><blockquote type="cite">[...]<br></blockquote><br>Ok, I'll try to sum up a few basics: First it's important to note that<br>values allocated by Racket and blocks allocated by C code live in<br>different memory areas and are handled differently. While Racket<br>values are reclaimed automatically by the garbage collector some time<br>after they are no longer referenced, blocks allocated from C live<br>forever unless explicitly destroyed. These two worlds know nothing<br>about each other by default.<br><br>The pointers your code handles never have to be destroyed explicitly,<br>but the objects they point to may have to be destroyed. There is no<br>simple general rule when and how this has to happen. It all depends on<br>the way the C code is designed and what mechanisms it uses for memory<br>management.<br><br>In the most simple situation, you do not use any C functions that<br>allocate and store or return (pointers to) blocks of memory, so you<br>can just let all the data live in the memory area managed by Racket<br>and let the garbage collector do its job without caring about manually<br>freeing any blocks of memory. C structures can be allocated through<br>Racket's garbage collector, too, and they will be reclaimed just like<br>Racket values some time after all pointers referring to them go out of<br>scope. Look at the documentation of malloc in the ffi/unsafe module<br>for details about memory allocation from the Racket side.<br><br>Another case encountered frequently is that there are C functions<br>creating, operating on and destroying pointers to some opaque data<br>structure. These structures do not live in Racket's managed memory, so<br>calls to the creation functions have to be matched by calls to the<br>destruction functions or the objects will stay in memory until the<br>process terminates.<br><br>In this situation you have two basic choices: You can either provide<br>bindings to the functions that create and destroy objects and require<br>any client code to handle memory management of those objects<br>explicitly, manually destroying them when they are no longer<br>needed. Or you can set up an automatism in Racket that ensures all<br>those objects created by calls from Racket are freed some time after<br>Racket code no longer holds any references to them. An easy way to<br>achieve this is by decorating the bindings for the creation and<br>destruction procedures using allocator and deallocator from the<br>ffi/unsafe/alloc module. However, care has to be taken that no code<br>outside Racket is still using the objects when they are reclaimed by<br>the Racket garbage collector. Some C libraries use reference counting<br>to better handle the situation that different pieces of code may hold<br>references to an object for random periods of time; the<br>ffi/unsafe/alloc module also has support for that situation.<br><br>Things get progressively more complicated if the C structures put<br>inside Racket's memory areas contain pointers themselves, if<br>structures outside Racket's memory areas contain pointers to Racket<br>values, or if callbacks from C into Racket are used.<br><br><blockquote type="cite">[...]<br></blockquote><blockquote type="cite">I hope I didn't ask too many too basic questions now, but never<br></blockquote><blockquote type="cite">having done any c programming and just knowing the concepts<br></blockquote><blockquote type="cite">"theoretically", there a quite some things about using FFI I don't<br></blockquote><blockquote type="cite">automatically understand from the Reference...<br></blockquote><blockquote type="cite">[...]<br></blockquote><br>Among all the FFIs I have used, Racket's is one of the most<br>comfortable and full featured ones. However, its features imply<br>complexity, too, and I can well imagine that without any prior<br>experience in low level programming and manual memory management, one<br>can easily get lost. So questions have to be expected :-)<br><br>Ciao,<br>Thomas<br><br><br>-- <br>When C++ is your hammer, every problem looks like your thumb.<br></div></blockquote></div><br></body></html>