Can my type be allowed as return type in FFI?

Hi, When I do: foreign import "nameOfFunction" nameOfFunction :: IO MyType I can get a function that return MyType only if it's a pointer or some of the C* type family. Is it possible to write a new MyType and make it allowed as a return type from foreign functions? Is changing the compiler the only way to do that? Thanks, Maurício

On Wed, 2008-12-10 at 08:33 -0200, Mauricio wrote:
Hi,
When I do:
foreign import "nameOfFunction" nameOfFunction :: IO MyType
I can get a function that return MyType only if it's a pointer or some of the C* type family. Is it possible to write a new MyType and make it allowed as a return type from foreign functions? Is changing the compiler the only way to do that?
Of course you're not really returning a MyType but a pointer to one. So use: foreign import "nameOfFunction" nameOfFunction :: IO (Ptr MyType) Using raw Ptrs is not very nice, so we would usually either wrap that in a ForeignPtr or use a Storable instance to get a MyType directly. Which approach to use depends on if you want MyType to have value or reference semantics. If the C type is abstract and you only access it via a pointer then the ForeignPtr approach is sensible. If you directly access all the fields of the C type then using an equivalent Haskell MyType and converting using Storable is the sensible approach. If do recommend reading the FFI spec. It's quite readable and explains a lot of the issues. Getting familiar with the Foreign libraries will help too. The most important bits are understanding ForeignPtr and the Storable class. Duncan

On Wed, Dec 10, 2008 at 12:30:56PM +0000, Duncan Coutts wrote:
If do recommend reading the FFI spec. It's quite readable and explains a lot of the issues. Getting familiar with the Foreign libraries will help too. The most important bits are understanding ForeignPtr and the Storable class.
I would also add the chapter 17 of Real World Haskell. you can read it here: http://book.realworldhaskell.org/read/interfacing-with-c-the-ffi.html It will guide you through the writing of the bindings to the PCRE library. Very useful and nicely conceived. A good collection of Storable instances that I found very helpful in understanding the subject can be found in the X11 bindings. Hope this helps, Andrea

foreign import "nameOfFunction" nameOfFunction :: IO MyType
Is it possible to write a new MyType and make it allowed as a return type from foreign functions? Is changing the compiler the only way to do that?
Of course you're not really returning a MyType but a pointer to one. (...)
This would solve half my problem. Can I always trust that? I've been told before that everytime a C function returns a struct it is actually returning a pointer, but I wasn't able to find that written in stone so that I can trust it to be valid anywhere Haskell will run and for any return type (like a struct containing just a char, for instance). How does that pointer work? My code didn't provide it to the C function, so, I believe I don't have to deallocate it. Where does the memory it points to live? Did Haskell FFI engine gave that pointer to the C function? How much time is it going to live? Enough so I can 'peek' it?
Using raw Ptrs is not very nice, so we would usually either wrap that in a ForeignPtr or use a Storable instance to get a MyType directly.
OK. I've instances of Storable for all the appropriate types.
If do recommend reading the FFI spec. It's quite readable and explains a lot of the issues.
Sure. It helped a lot. Actually, I've been able to do everything I needed so far with just the spec and Foreign.*.
I would also add the chapter 17 of Real World Haskell. you can read it here:
Nice. It shows unsafePerformIO. Some functions returning structs are side effect free. I'm writing bindings I want to put on hackage, so what do you think would fit better the taste of Haskell programmers: pure functions using unsafePerformIO or IO functions? Thanks, Maurício

On Wed, 2008-12-10 at 14:17 -0200, Mauricio wrote:
foreign import "nameOfFunction" nameOfFunction :: IO MyType
Is it possible to write a new MyType and make it allowed as a return type from foreign functions? Is changing the compiler the only way to do that?
Of course you're not really returning a MyType but a pointer to one. (...)
This would solve half my problem. Can I always trust that? I've been told before that everytime a C function returns a struct it is actually returning a pointer, but I wasn't able to find that written in stone so that I can trust it to be valid anywhere Haskell will run and for any return type (like a struct containing just a char, for instance).
Sorry, I'm not talking about how C implements passing structures to functions. The Haskell FFI can only bind functions that pass structures by pointer, not by value. So if you've got a C function that passes them by value then you need to write a wrapper function in C and bind to that. That way you end up with a pointer on the Haskell side.
How does that pointer work? My code didn't provide it to the C function, so, I believe I don't have to deallocate it. Where does the memory it points to live? Did Haskell FFI engine gave that pointer to the C function? How much time is it going to live? Enough so I can 'peek' it?
You explicitly pass the pointer and typically you manage the allocation and de-allocation in Haskell using functions from the Foreign.* modules. There is no magic. You have to manage all the allocation, writing and object lifetimes explicitly. The Foreign.* modules provide many convenience functions that make this simpler in many cases.
Nice. It shows unsafePerformIO. Some functions returning structs are side effect free. I'm writing bindings I want to put on hackage, so what do you think would fit better the taste of Haskell programmers: pure functions using unsafePerformIO or IO functions?
If the C function is genuinely pure apart from having to allocate and de-allocate temporary objects (and you treat all such objects by value using Storable) then it's ok to make it pure in Haskell using unsafePerformIO. If it mutates any input parameters or uses objects managed by reference using ForeignPtr then it's not ok. So it really depends on what the C code is doing. Duncan

Sorry, I'm not talking about how C implements passing structures to functions. The Haskell FFI can only bind functions that pass structures by pointer, not by value. So if you've got a C function that passes them by value then you need to write a wrapper function in C and bind to that.
This should definitely be in the documentation somewhere. I delayed some work for a few weeks with that :) Thanks a lot for making this clear. Maurício

On 11 Dec 2008, at 5:17 am, Mauricio wrote:
This would solve half my problem. Can I always trust that? I've been told before that everytime a C function returns a struct it is actually returning a pointer, but I wasn't able to find that written in stone
That's because it isn't true. In fact one of the classical ways for a C function to return a struct is to be *GIVEN* a pointer, e.g., struct Foo f(......) { ... return x; } => void f(struct Foo *_hidden, ......) { ... *_hidden = x; return; } and obviously a C compiler is entitled to return a small struct in registers if it feels like it.

This would solve half my problem. Can I always trust that? I've been told before that everytime a C function returns a struct it is actually returning a pointer, but I wasn't able to find that written in stone
That's because it isn't true. In fact one of the classical ways for a C function to return a struct is to be *GIVEN* a pointer, e.g., (...)
Sure, sorry. I should have said that the C functions fill memory from a given pointer.
and obviously a C compiler is entitled to return a small struct in registers if it feels like it.
If a compiler is compiling code that calls a library, how is it supposed to know if a return pointer is been passed as a register or by using a pointer? The compiler may not have access to the built library to check that. (Begginer question, I never wrote assembly code.) Thanks, Maurício

On 2008 Dec 11, at 10:28, Mauricio wrote:
and obviously a C compiler is entitled to return a small struct in registers if it feels like it.
If a compiler is compiling code that calls a library, how is it supposed to know if a return pointer is been passed as a register or by using a pointer? The compiler may not have access to the
The rules are specified as part of an ABI. There is a default ABI for a platform, or you can use a special one (document it). IIRC some CPUs allow information about passed/returned values to be passed in a flag word. -- brandon s. allbery [solaris,freebsd,perl,pugs,haskell] allbery@kf8nh.com system administrator [openafs,heimdal,too many hats] allbery@ece.cmu.edu electrical and computer engineering, carnegie mellon university KF8NH
participants (5)
-
Andrea Rossato
-
Brandon S. Allbery KF8NH
-
Duncan Coutts
-
Mauricio
-
Richard O'Keefe