Stable pointers: use of cast to/from Ptr

Hello, According to the documentation ( http://hackage.haskell.org/packages/archive/base/4.5.0.0/doc/html/Foreign-St...), StablePtrs aims at being opaque on C-side. But they provide functions to be casted to/from regular *void**'s. Does that mean if for instance you have a StablePtr CInt you can cast it to Ptr () and alter it on C-side? void alter(void* data) { int* x = (int*)data; *x = 42; } -------------------------------------------------- -- using 'unsafe' doesn't change anything. foreign import ccall safe "alter" alter :: Ptr () -> IO () main = do sptr <- newStablePtr (0 :: CInt) deRefStablePtr sptr >>= print alter (castStablePtrToPtr sptr) -- SEGFAULTS! deRefStablePtr sptr >>= print freeStablePtr sptr But I tried it, and it doesn't work: I got a segfault when 'alter' is called. Is it normal? Does this mean I can only use my pointer as opaque? (Which I know to be working, as I already got a C function call back into Haskell and pass it the StablePtr via a 'foreign export') But in that case, what is the use of castStablePtrToPtr/castPtrToStablePtr, as you can already pass StablePtrs to and from C code? Thanks!

On Sun, Feb 12, 2012 at 8:18 AM, Yves Parès
Hello,
According to the documentation (http://hackage.haskell.org/packages/archive/base/4.5.0.0/doc/html/Foreign-St...), StablePtrs aims at being opaque on C-side. But they provide functions to be casted to/from regular void*'s. Does that mean if for instance you have a StablePtr CInt you can cast it to Ptr () and alter it on C-side?
void alter(void* data) { int* x = (int*)data; *x = 42; }
--------------------------------------------------
-- using 'unsafe' doesn't change anything. foreign import ccall safe "alter" alter :: Ptr () -> IO ()
main = do sptr <- newStablePtr (0 :: CInt) deRefStablePtr sptr >>= print alter (castStablePtrToPtr sptr) -- SEGFAULTS! deRefStablePtr sptr >>= print freeStablePtr sptr
But I tried it, and it doesn't work: I got a segfault when 'alter' is called.
I think that 'castStablePtrToPtr' exists because many C APIs use 'void*' to mean 'opaque lump of data', and these exist to conform to that sort of API. Antoine

Yes, but from C side, a StablePtr* is **already a **void**. (See HsFFI.h
which typedefs HsStablePtr to void*)
So its sufficient for a use as an opaque pointer, no need to cast it.
So what is the use of casting it to a Ptr () if this doesn't allow to
access the memory space addressed?
2012/2/12 Antoine Latter
On Sun, Feb 12, 2012 at 8:18 AM, Yves Parès
wrote: Hello,
According to the documentation ( http://hackage.haskell.org/packages/archive/base/4.5.0.0/doc/html/Foreign-St... ), StablePtrs aims at being opaque on C-side. But they provide functions to be casted to/from regular void*'s. Does that mean if for instance you have a StablePtr CInt you can cast it to Ptr () and alter it on C-side?
void alter(void* data) { int* x = (int*)data; *x = 42; }
--------------------------------------------------
-- using 'unsafe' doesn't change anything. foreign import ccall safe "alter" alter :: Ptr () -> IO ()
main = do sptr <- newStablePtr (0 :: CInt) deRefStablePtr sptr >>= print alter (castStablePtrToPtr sptr) -- SEGFAULTS! deRefStablePtr sptr >>= print freeStablePtr sptr
But I tried it, and it doesn't work: I got a segfault when 'alter' is called.
I think that 'castStablePtrToPtr' exists because many C APIs use 'void*' to mean 'opaque lump of data', and these exist to conform to that sort of API.
Antoine

On 12-02-12 09:18 AM, Yves Parès wrote:
According to the documentation (http://hackage.haskell.org/packages/archive/base/4.5.0.0/doc/html/Foreign-St...), StablePtrs aims at being opaque on C-side.
The doc multiply warns again and again that StablePtr, as well as
whatever Ptr you get from castStablePtrToPtr, are opague (meaningless)
to the C side. This is sanctioned by Haskell 2010, and GHC certainly
exploits it to the fullest. The following example shows what kind of
"pointer" values the C side receives for real (I deliberately do not
free anything to show you more possible values):
#include

Thanks for your explanation Albert, it makes things clearer.
So StablePtrs are just useful so that C code can:
1) call back into Haskell (through a foreign exported function like
doSomethingWithTheObjectIGaveYou
:: StablePtr MyObjectType -> Stuff -> IO ())
2) store them to return them later to Haskell when prompted (through a
foreign imported function like getObject :: Stuff -> IO (StablePtr
MyObjectType))
That's it?
But then,
In use case 1), how can a Haskell function modify the data addressed?
If StablePtrs cannot have their pointed value modified (either C or
Haskell-side), that mostly limits their interest, doesn't it?
2012/2/12 Albert Y. C. Lai
On 12-02-12 09:18 AM, Yves Parès wrote:
According to the documentation (http://hackage.haskell.org/**packages/archive/base/4.5.0.0/** doc/html/Foreign-StablePtr.**htmlhttp://hackage.haskell.org/packages/archive/base/4.5.0.0/doc/html/Foreign-St... ), StablePtrs aims at being opaque on C-side.
The doc multiply warns again and again that StablePtr, as well as whatever Ptr you get from castStablePtrToPtr, are opague (meaningless) to the C side. This is sanctioned by Haskell 2010, and GHC certainly exploits it to the fullest. The following example shows what kind of "pointer" values the C side receives for real (I deliberately do not free anything to show you more possible values):
#include
void expose(void *p, void *q) { printf("%p %p\n", p, q); } import Foreign.StablePtr import Foreign.Ptr main = do printout (0 :: Int) printout (let x = not x in x) printout ([] :: [Integer]) printout :: a -> IO () printout thunk = do p <- newStablePtr thunk expose p (castStablePtrToPtr p) -- I deliberately do not free foreign import ccall expose :: StablePtr a -> Ptr b -> IO ()
Typically the output is like 0xf 0xf 0x10 0x10 0x11 0x11 Looks more like keys of a lookup table than pointers.
I do not know what good is castStablePtrToPtr for, given that StablePtr is already translated to C side void*, so that no intermediate Ptr step is necessary. Perhaps there is a story from a historical perspective.
______________________________**_________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/**mailman/listinfo/haskell-cafehttp://www.haskell.org/mailman/listinfo/haskell-cafe

On Sun, Feb 12, 2012 at 3:09 PM, Yves Parès
But then, In use case 1), how can a Haskell function modify the data addressed?
http://hackage.haskell.org/packages/archive/base/latest/doc/html/Foreign-Sta... Antoine

You mean I have to use a type like StablePtr (IORef Stuff)?
Because there I can only "peek" (deRefStablePtr) the pointer, not "poke" it.
I take it I should return to C a StablePtr to the new value if I don't want
to use IORefs...
Or else I have to use regular Ptrs with Foreign.Marshall.Alloc.malloc
2012/2/12 Antoine Latter
On Sun, Feb 12, 2012 at 3:09 PM, Yves Parès
wrote: But then, In use case 1), how can a Haskell function modify the data addressed?
http://hackage.haskell.org/packages/archive/base/latest/doc/html/Foreign-Sta...
Antoine

Quoth =?ISO-8859-1?Q?Yves_Par=E8s?=
You mean I have to use a type like StablePtr (IORef Stuff)? Because there I can only "peek" (deRefStablePtr) the pointer, not "poke" it.
I take it I should return to C a StablePtr to the new value if I don't want to use IORefs...
Yes ...
Or else I have to use regular Ptrs with Foreign.Marshall.Alloc.malloc
yes! Both of these are good ways, to do different things. In your initial message, you asked about a foreign function modifying a value in storage accessible from Haskell - that's regular Ptr. Either way, read or write, communication with the foreign layer is through Ptr, not StablePtr. StablePtr is for Haskell expressions, which would be totally inscrutable to the foreign function anyway, and which naturally do not expect to be modified, so yes, a new value shall be attached to a new StablePtr. Donn

Quoth Yves Pares, ...
If StablePtrs cannot have their pointed value modified (either C or Haskell-side), that mostly limits their interest, doesn't it?
I'm not sure I follow what's happening in the two cases you mention, but in case it helps, I use StablePtr as a way to smuggle Haskell values through a non-Haskell layer. On the other side, they are just things - not really pointers, so while void* is all right as long as it's the right size, it is a little misleading. "Tag" might be a better word. castStablePtrToPtr doesn't change that - you still get a tag, not a memory address. I can think of no use for it, unless you want to call a function that happens to use a Ptr () without expecting it to point somewhere in the memory address sense. Since they're Haskell values, it would be perverse to modify them. I just want them back, in a Haskell function dispatched by the other layer. If I want to pass data per se to the other side, I have to marshal it to be readable CInts and such, and then pass it as a Ptr. And/or if the data is to be modified by the other side, same deal, I have to un-marshal it back into Haskell. I actually use them with a C++ layer, where of course the dispatch happens through C++ object member functions. That allows me to map Haskell functions to the C++ API in a C++ derived class that just maintains a table of the actual Haskell `member functions', and a StablePtr for the actual Haskell data. Donn

No, you can do nothing with the pointer on the C side other than pass
it back into haskell. It may not even be a pointer, it may be an index
into an array deep within the RTS for instance. The reason they can be
cast to void *'s is so you can store them in C data structures that
don't know about haskell, which tend to take void *s.
John
On Sun, Feb 12, 2012 at 6:18 AM, Yves Parès
Hello,
According to the documentation (http://hackage.haskell.org/packages/archive/base/4.5.0.0/doc/html/Foreign-St...), StablePtrs aims at being opaque on C-side. But they provide functions to be casted to/from regular void*'s. Does that mean if for instance you have a StablePtr CInt you can cast it to Ptr () and alter it on C-side?
void alter(void* data) { int* x = (int*)data; *x = 42; }
--------------------------------------------------
-- using 'unsafe' doesn't change anything. foreign import ccall safe "alter" alter :: Ptr () -> IO ()
main = do sptr <- newStablePtr (0 :: CInt) deRefStablePtr sptr >>= print alter (castStablePtrToPtr sptr) -- SEGFAULTS! deRefStablePtr sptr >>= print freeStablePtr sptr
But I tried it, and it doesn't work: I got a segfault when 'alter' is called.
Is it normal? Does this mean I can only use my pointer as opaque? (Which I know to be working, as I already got a C function call back into Haskell and pass it the StablePtr via a 'foreign export') But in that case, what is the use of castStablePtrToPtr/castPtrToStablePtr, as you can already pass StablePtrs to and from C code?
Thanks!
_______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
participants (5)
-
Albert Y. C. Lai
-
Antoine Latter
-
Donn Cave
-
John Meacham
-
Yves Parès