yes, usually C-functions should not allocate memory themselves. Otherwise, where all those custom allocators will be used? :)
And to be serious: during the time, that I had spent with haskell and ocaml, I came to conclusion, that one of big issues in haskell, is interfacing with C/C++
to have recvfrom (as an example), you will have those options:
1. define it yourself with something like
```
foreign import "socket.h" c_recvfrom :: CInt-> Ptr a-> CLong-> CInt-> Ptr b-> Ptr c-> IO CInt
recvfrom:: Fd-> IO (SockAddr, ByteString)
recvfrom fd =
alloca $ \src_sz -> do
pending_bytes <- ioctl fd FIONREAD
buf <- mallocBytes pending_bytes
src_addr <- malloc
poke src_sz (sizeOf (undefined::SockAddr))
ret <- c_recvfrom fd buf pending_bytes src_addr src_sz
if ret >= 0
then (peek src_addr, packCStringLen buf pending_bytes)
else throwIO $ userError "recvfrom failed"
```
seems not difficult, unless you need to define an instance of Storable for SockAddr, for which you should know memory layout of SockAddr, including size, alignment and so on. Fast way, but mastering your own wrapper for GTK or QT is not a good idea.
2. use third-party library, which has all the dirty stuff, but it will add dependencies, which will affect build times, binary size, can grow occupied space due to cross dependencies and it will be pain when you need to cross compile, but, hopefully, it will contain everything you ever need
3. master things like c2hs
I was thinking, that I am struggling with haskell's FFI, until I had to use OCaml's FFI like this:
```
external recvfrom: int-> (sockaddr_t, bytes) = "c_recvfrom"
//caml_stub.c
value c_recvfrom(value _fd){
CAMLparams1(_fd);
CAMLlocal2(buf, tuple. sa);
int ret = 0;
int fd = 0;
int buf_sz = 0;
sockaddr_in src_addr;
size_t sa_sz = sizeof( src_addr);
fd = Int_val( _fd);
ioctl(fd, FIONREAD, &buf_sz);
buf = malloc( buf_sz);
ret = recvfrom( Int_val(fd), buf, buf_sz, 0, &src_addr, &sa_sz);
buf = caml_copy_string( buf, buf_sz);
sa = caml_alloc_custom( &default_pointers, sizeof(void*), 0, 1);
tuple = caml_alloc(1, 0);
Store_field( tuple, 0, sa);
Store_field( tuple, 1, buf);
CAMLreturn(tuple);
}
```
so OCaml's FFI is basically untyped C, in which you have to operate with variables of type 'value' and bunch of macroses and hope that you haven't messed up anything.
In this regard, ATS's way of interfacing is like a breath of fresh air for me :)