Re: Ptr and ForeignPtr Questions
At 2001-10-10 01:19, I wrote: foreign import foo raw_foo :: Ptr () - IO (Ptr ()); foo :: Ptr SomeLinkedList - IO (ConstPtr Char); foo = importFunction raw_foo; Actually I don't need to convert the pointers, do I? If I have (Storable SomeLinkedList), I can just declare foreign import foo foo :: Ptr SomeLinkedList - IO (Ptr Char); and it should work. The only thing that's missing is a ConstPtr type... -- Ashley Yakeley, Seattle WA ___ Glasgow-haskell-users mailing list [EMAIL PROTECTED] http://www.haskell.org/mailman/listinfo/glasgow-haskell-users
Re: Ptr and ForeignPtr Questions
At 2001-09-23 23:12, Manuel M. T. Chakravarty wrote: I was just hoping for GHC to be able to spit out headers for 'foreign import' functions that the user could then define. This merely means a map from some restricted set of Haskell function types to C types. Functionality like that is not part of the FFI. However, it would surely be possible to write an extra tool that accomplishes just what you want. (It was a general design rule to avoid in the basic FFI features that would be complicated to define/implement and can as easily be implemented by a tool.) Right. This would be very similar to the 'javah' tool used in the Java world. That works on compiled .class files, I suppose the equivalent would be a module that plugged in to the GHC motherboard. Moreover, the case where you bind to existing C functions is much more common than where you bind to C functions that you have written yourself. Right, but it's a more ambitious goal for the FFI designer, at least if they want to do it completely. As you point out, there are restrictions on just what existing C functions you can bind to. If your function looks like this: const char* foo (struct SomeLinkedList*); ...you have no choice but to write 'impedance-matching' code for that function. structs are not allowed as arguments to foreign imported functions. Exactly! And neither are const pointers. But argument const-ness, at least, can be safely ignored. -- Ashley Yakeley, Seattle WA ___ Glasgow-haskell-users mailing list [EMAIL PROTECTED] http://www.haskell.org/mailman/listinfo/glasgow-haskell-users
Re: Ptr and ForeignPtr Questions
Ashley Yakeley [EMAIL PROTECTED] wrote, At 2001-09-21 02:20, Manuel M. T. Chakravarty wrote: One could attempt to generate C prototypes from the Haskell type declarations or similar things, btu it doesn't work out. Why not? Isn't there a straightforward type map? No, unfortunately not. Consider, for example, that storage qualifiers would have to be generated correctly and there is no way to determine form a Haskell type whether a `const' modifier needs to be added. Manuel ___ Glasgow-haskell-users mailing list [EMAIL PROTECTED] http://www.haskell.org/mailman/listinfo/glasgow-haskell-users
Re: Ptr and ForeignPtr Questions
At 2001-09-23 00:45, Manuel M. T. Chakravarty wrote: No, unfortunately not. Consider, for example, that storage qualifiers would have to be generated correctly and there is no way to determine form a Haskell type whether a `const' modifier needs to be added. I would assume that Ptr types would always be mapped to non-const pointers. Do you have an example of a Haskell type for a foreign import function, for which the corresponding C function type would be ambiguous? -- Ashley Yakeley, Seattle WA ___ Glasgow-haskell-users mailing list [EMAIL PROTECTED] http://www.haskell.org/mailman/listinfo/glasgow-haskell-users
Re: Ptr and ForeignPtr Questions
Ashley Yakeley [EMAIL PROTECTED] wrote, At 2001-09-23 00:45, Manuel M. T. Chakravarty wrote: No, unfortunately not. Consider, for example, that storage qualifiers would have to be generated correctly and there is no way to determine form a Haskell type whether a `const' modifier needs to be added. I would assume that Ptr types would always be mapped to non-const pointers. Do you have an example of a Haskell type for a foreign import function, for which the corresponding C function type would be ambiguous? Take, for example, the following excerpt of the Linux man pages STRCAT(3) Linux Programmer's Manual STRCAT(3) NAME strcat, strncat - concatenate two strings SYNOPSIS #include string.h char *strcat(char *dest, const char *src); char *strncat(char *dest, const char *src, size_t n); If you want to bind these functions from Haskell, you have to deal with `const' qualifiers. The same holds for many other functions in existing C libraries. Manuel ___ Glasgow-haskell-users mailing list [EMAIL PROTECTED] http://www.haskell.org/mailman/listinfo/glasgow-haskell-users
Re: Ptr and ForeignPtr Questions
Sun, 23 Sep 2001 02:04:49 -0700, Ashley Yakeley [EMAIL PROTECTED] pisze: I would assume that Ptr types would always be mapped to non-const pointers. It would be impossible then to directly call a C function with a parameter declared as a const pointer. It's illegal in C to have mismatching prototypes of the same function. -- __( Marcin Kowalczyk * [EMAIL PROTECTED] http://qrczak.ids.net.pl/ \__/ ^^ SYGNATURA ZASTÊPCZA QRCZAK ___ Glasgow-haskell-users mailing list [EMAIL PROTECTED] http://www.haskell.org/mailman/listinfo/glasgow-haskell-users
Re: Ptr and ForeignPtr Questions
At 2001-09-23 04:02, Manuel M. T. Chakravarty wrote: I would assume that Ptr types would always be mapped to non-const pointers. Do you have an example of a Haskell type for a foreign import function, for which the corresponding C function type would be ambiguous? Take, for example, the following excerpt of the Linux man pages But do you have an example of a Haskell type for a foreign import function, for which the corresponding C function type would be ambiguous? At 2001-09-21 02:20, Manuel M. T. Chakravarty wrote: One could attempt to generate C prototypes from the Haskell type declarations or similar things, btu it doesn't work out. Surely one can still do this? This was what we were discussing, was it not? A C type for any given Haskell function type, not necessarily the other way around... -- Ashley Yakeley, Seattle WA ___ Glasgow-haskell-users mailing list [EMAIL PROTECTED] http://www.haskell.org/mailman/listinfo/glasgow-haskell-users
Re: Ptr and ForeignPtr Questions
Sun, 23 Sep 2001 15:41:41 -0700, Ashley Yakeley [EMAIL PROTECTED] pisze: But do you have an example of a Haskell type for a foreign import function, for which the corresponding C function type would be ambiguous? Ptr CChar (as an argument). It could be either char * or const char *. -- __( Marcin Kowalczyk * [EMAIL PROTECTED] http://qrczak.ids.net.pl/ \__/ ^^ SYGNATURA ZASTÊPCZA QRCZAK ___ Glasgow-haskell-users mailing list [EMAIL PROTECTED] http://www.haskell.org/mailman/listinfo/glasgow-haskell-users
Re: Ptr and ForeignPtr Questions
At 2001-09-23 04:04, Marcin 'Qrczak' Kowalczyk wrote: It would be impossible then to directly call a C function with a parameter declared as a const pointer. It's illegal in C to have mismatching prototypes of the same function. You can always do this: module MyModule where { foreign import StringCopy :: Ptr Int8 - Ptr Int8 - IO (); } which autogenerates this header: extern C { void MyModule__StringCopy(signed char* a,signed char* b); } which the user can implement like this: char* strcat(char* dest, const char* src); void MyModule__StringCopy(char* dest,char* src) { strcat(dest,src); } (assuming char and signed char are identical). -- Ashley Yakeley, Seattle WA ___ Glasgow-haskell-users mailing list [EMAIL PROTECTED] http://www.haskell.org/mailman/listinfo/glasgow-haskell-users
Re: Ptr and ForeignPtr Questions
At 2001-09-23 15:56, Marcin 'Qrczak' Kowalczyk wrote: But do you have an example of a Haskell type for a foreign import function, for which the corresponding C function type would be ambiguous? Ptr CChar (as an argument). It could be either char * or const char *. It's always char*. A Haskell function passed a Ptr CChar is not prevented from modifying the contents of the pointer simply due to its type-declaration. In C, a char* can be implicitly converted to a const char* where necessary (but not the other way around). -- Ashley Yakeley, Seattle WA ___ Glasgow-haskell-users mailing list [EMAIL PROTECTED] http://www.haskell.org/mailman/listinfo/glasgow-haskell-users
Re: Ptr and ForeignPtr Questions
Ashley Yakeley [EMAIL PROTECTED] wrote, At 2001-09-23 04:04, Marcin 'Qrczak' Kowalczyk wrote: It would be impossible then to directly call a C function with a parameter declared as a const pointer. It's illegal in C to have mismatching prototypes of the same function. You can always do this: module MyModule where { foreign import StringCopy :: Ptr Int8 - Ptr Int8 - IO (); } which autogenerates this header: extern C { void MyModule__StringCopy(signed char* a,signed char* b); } which the user can implement like this: char* strcat(char* dest, const char* src); void MyModule__StringCopy(char* dest,char* src) { strcat(dest,src); } (assuming char and signed char are identical). If you are writing a Haskell binding to a large C library that has hundreds of functions, it is extremely unattractive to write impedance matchers like `MyModule__StringCopy' manually. Manuel ___ Glasgow-haskell-users mailing list [EMAIL PROTECTED] http://www.haskell.org/mailman/listinfo/glasgow-haskell-users
Re: Ptr and ForeignPtr Questions
Ashley Yakeley [EMAIL PROTECTED] wrote, At 2001-09-23 19:14, Manuel M. T. Chakravarty wrote: Hmm, we must be misunderstanding each other. Given that you have foreign import strcat :: Ptr CChar - Ptr CChar - IO (Ptr CChar) How do you want to know whether the C prototype is char *strcat(char *dest, const char *src); or char *strcat(char *dest, char *src); I was just hoping for GHC to be able to spit out headers for 'foreign import' functions that the user could then define. This merely means a map from some restricted set of Haskell function types to C types. Functionality like that is not part of the FFI. However, it would surely be possible to write an extra tool that accomplishes just what you want. (It was a general design rule to avoid in the basic FFI features that would be complicated to define/implement and can as easily be implemented by a tool.) Moreover, the case where you bind to existing C functions is much more common than where you bind to C functions that you have written yourself. And if you have written them yourself, adding a function prototype shouldn't be much more work. But it looks like you want to be able to arbitrarily import any C library function. Of course this means a map from C functions to Haskell functions. In the case you gave Haskell could get away with calling strcat using this: char* strcat(char*,char*); ...even if the function had actually been defined like this: char* strcat(char*,const char*); This is quite safe from a 'const' point of view. More difficult is this: The only good reason to actually emit prototypes by the compiler is to check them against the prototypes in an already existing C header file for the same library. However, in this case, the above would lead to a type error when compiling the C code. At 2001-09-23 19:21, Manuel M. T. Chakravarty wrote: If you are writing a Haskell binding to a large C library that has hundreds of functions, it is extremely unattractive to write impedance matchers like `MyModule__StringCopy' manually. I'm taking an approach similar to JNI, in which the user defines in C what has been declared in Haskell. But what you want to do is to allow the user to declare in Haskell what has been defined in C, obviously a more ambitious goal. Const pointers are not your only worry; how would you deal with structs? structs are not allowed as arguments to foreign imported functions. Manuel ___ Glasgow-haskell-users mailing list [EMAIL PROTECTED] http://www.haskell.org/mailman/listinfo/glasgow-haskell-users
Re: Ptr and ForeignPtr Questions
Ashley Yakeley [EMAIL PROTECTED] wrote, At 2001-09-20 19:32, Manuel M. T. Chakravarty wrote: What I meant with the remark that you quote is that if you would use foreign import foo :: Ptr Int - IO Float with float foo (float *x) { return *x; } the system will not complain, but your program may dump core. What if the C looked like this: float foo (int *x) { return *x; } ...? That's ok. All I am saying is that the FFI doesn't ensure any concistency between the Haskell and the C type. Manuel ___ Glasgow-haskell-users mailing list [EMAIL PROTECTED] http://www.haskell.org/mailman/listinfo/glasgow-haskell-users
Re: Ptr and ForeignPtr Questions
Ashley Yakeley [EMAIL PROTECTED] wrote, At 2001-09-21 01:39, Manuel M. T. Chakravarty wrote: That's ok. All I am saying is that the FFI doesn't ensure any concistency between the Haskell and the C type. Well it can't can it? There's no type information in object-code symbols (unless you use C++ identifier mangling, which Haskell doesn't). One could attempt to generate C prototypes from the Haskell type declarations or similar things, btu it doesn't work out. Manuel ___ Glasgow-haskell-users mailing list [EMAIL PROTECTED] http://www.haskell.org/mailman/listinfo/glasgow-haskell-users
Re: Ptr and ForeignPtr Questions
Ashley Yakeley [EMAIL PROTECTED] wrote, The documentation for FFI in the GHC user's guide seems to be out of date with regard to passing Ptrs across. 1. My reference is http://www.haskell.org/ghc/docs/latest/set/ffi.html (from http://www.haskell.org/ghc/docs/latest/set/book-users-guide.html) Is this the latest documentation available? 2. My understanding is that you can use any instance of 'Storable a = Ptr a' as an FFI argument and return type for both imported and exported functions? Is this correct? If I understand you question correctly and you want to pass a pointer to C land and back, yes, this is possible. What if the type is polymorphic (e.g. declared as 'Storable a = Ptr a' rather than something like 'Ptr Word8')? Also possible, as the argument to `Ptr' is just dummy. 3. What about ForeignPtr? Can instances of 'Storable a = ForeignPtr a' be used in FFI? They can be passed to C, but you can't get them back. (The storange manager wouldn't know what finaliser to attach.) 4. Does newForeignPtr work safely with null pointers, and will the finalizer get called? For instance: fp - newForeignPtr nullPtr finalFunc; let {isNull = (foreignPtrToPtr fp) == nullPtr}; r - withForeign fp (\p - foo p); Will foo be passed nullPtr? Will finalFunc ever get called? Is my use, above, of foreignPtrToPtr safe, and will isNull be True? Should work. From the storage managers point of view, a `Ptr' is just an uninterpreted bit-pattern. A glorified `Int'. Of course, you should better make sure that `finalFunc' can handle getting a `nullPtr'. Cheers, Manuel ___ Glasgow-haskell-users mailing list [EMAIL PROTECTED] http://www.haskell.org/mailman/listinfo/glasgow-haskell-users
RE: Ptr and ForeignPtr Questions
Ashley Yakeley [EMAIL PROTECTED] wrote, The documentation for FFI in the GHC user's guide seems to be out of date with regard to passing Ptrs across. 1. My reference is http://www.haskell.org/ghc/docs/latest/set/ffi.html (from http://www.haskell.org/ghc/docs/latest/set/book-users-guide.html) Is this the latest documentation available? 2. My understanding is that you can use any instance of 'Storable a = Ptr a' as an FFI argument and return type for both imported and exported functions? Is this correct? If I understand you question correctly and you want to pass a pointer to C land and back, yes, this is possible. I'll just add that the docs have been updated for 5.02, and the FFI section now refers to Ptr and ForeignPtr instead of Addr and ForeignObj. 4. Does newForeignPtr work safely with null pointers, and will the finalizer get called? For instance: fp - newForeignPtr nullPtr finalFunc; let {isNull = (foreignPtrToPtr fp) == nullPtr}; r - withForeign fp (\p - foo p); Will foo be passed nullPtr? Will finalFunc ever get called? Is my use, above, of foreignPtrToPtr safe, and will isNull be True? Should work. From the storage managers point of view, a `Ptr' is just an uninterpreted bit-pattern. A glorified `Int'. Of course, you should better make sure that `finalFunc' can handle getting a `nullPtr'. And don't forget that using foreignPtrToPtr is quite dangerous; much better to use withForeignPtr instead, otherwise you might find the ForeignPtr being finalised earlier than you expect. Cheers, Simon ___ Glasgow-haskell-users mailing list [EMAIL PROTECTED] http://www.haskell.org/mailman/listinfo/glasgow-haskell-users
Re: Ptr and ForeignPtr Questions
At 2001-09-19 23:45, Manuel M. T. Chakravarty wrote: What if the type is polymorphic (e.g. declared as 'Storable a = Ptr a' rather than something like 'Ptr Word8')? Also possible, as the argument to `Ptr' is just dummy. What? What about 'withObject'? A Haskell 'Ptr a' is a C array-pointer of whatever corresponds to 'a'. I don't think the argument is dummy. Consider this: int foo (char selector,char* arg) { if (selector == 100) return reinterpret_castunsigned char*(arg)[1]; if (selector == 200) return reinterpret_castunsigned short*(arg)[1]; return 0; } foreign import foo foo :: Storable a = Word8 - Ptr a - IO Int32; a - withObject ([1,2] :: [Word8]) (foo 100); b - withObject ([3,4] :: [Word16]) (foo 200); Will this work as expected? I expect 'a' to be 2 and 'b' to be 4... 3. What about ForeignPtr? Can instances of 'Storable a = ForeignPtr a' be used in FFI? They can be passed to C, but you can't get them back. (The storange manager wouldn't know what finaliser to attach.) OK. Are ForeignPtrs intelligible in the C function as pointers to the named type? 4. Does newForeignPtr work safely with null pointers, and will the finalizer get called? For instance: fp - newForeignPtr nullPtr finalFunc; let {isNull = (foreignPtrToPtr fp) == nullPtr}; r - withForeign fp (\p - foo p); Will foo be passed nullPtr? Will finalFunc ever get called? Is my use, above, of foreignPtrToPtr safe, and will isNull be True? Should work. From the storage managers point of view, a `Ptr' is just an uninterpreted bit-pattern. A glorified `Int'. So you are saying that the ForeignPtr code is not interested in the pointer-ness of the Ptr contents of a ForeignPtr, except when a ForeignPtr is used as an FFI argument? Presumably this also means that one can create two separate ForeignPtrs around the same Ptr, each with their own finaliser set. Presumably they would not be equal (note that Eq (ForeignPtr a)). Is this correct? Also, I assume that a ForeignPtr is eligible for garbage collection whenever it is no longer 'reachable', even if the Ptr it contains is reachable. Is that correct? Is there anything resembling Java's 'soft' and 'weak references'? Of course, you should better make sure that `finalFunc' can handle getting a `nullPtr'. Of course... -- Ashley Yakeley, Seattle WA ___ Glasgow-haskell-users mailing list [EMAIL PROTECTED] http://www.haskell.org/mailman/listinfo/glasgow-haskell-users
RE: Ptr and ForeignPtr Questions
At 2001-09-20 02:14, Simon Marlow wrote: I'll just add that the docs have been updated for 5.02, Do you have a URL for that? And don't forget that using foreignPtrToPtr is quite dangerous; much better to use withForeignPtr instead, otherwise you might find the ForeignPtr being finalised earlier than you expect. This is because foreignPtrToPtr is not in the IO monad, correct? foreignPtrToPtr :: ForeignPtr a - Ptr a; A function like this: ioForeignPtrToPtr :: ForeignPtr a - IO (Ptr a); ioForeignPtrToPtr fp = withForeignPtr fp return; ...would surely be safe? The 5.00 documentation claims that it isn't, however, but I don't see why. -- Ashley Yakeley, Seattle WA ___ Glasgow-haskell-users mailing list [EMAIL PROTECTED] http://www.haskell.org/mailman/listinfo/glasgow-haskell-users
Re: Ptr and ForeignPtr Questions
At 2001-09-20 02:31, I wrote: int foo (char selector,char* arg) ... if (selector == 200) I guess that should be int foo (unsigned char selector,char* arg) -- Ashley Yakeley, Seattle WA ___ Glasgow-haskell-users mailing list [EMAIL PROTECTED] http://www.haskell.org/mailman/listinfo/glasgow-haskell-users
RE: Ptr and ForeignPtr Questions
At 2001-09-20 02:14, Simon Marlow wrote: I'll just add that the docs have been updated for 5.02, Do you have a URL for that? Not yet, but the release is imminent (really!) so it'll be up on the web site shortly. And don't forget that using foreignPtrToPtr is quite dangerous; much better to use withForeignPtr instead, otherwise you might find the ForeignPtr being finalised earlier than you expect. This is because foreignPtrToPtr is not in the IO monad, correct? foreignPtrToPtr :: ForeignPtr a - Ptr a; A function like this: ioForeignPtrToPtr :: ForeignPtr a - IO (Ptr a); ioForeignPtrToPtr fp = withForeignPtr fp return; ...would surely be safe? The 5.00 documentation claims that it isn't, however, but I don't see why. No, it's not safe. The reason is that the compiler can track a ForeignPtr to discover when it dies, in order to run the finalizer, but it can't track a Ptr. As soon as you drop all references to the ForeignPtr then the finalizer will run, even if you converted it to a Ptr and you're still using it. withForeignPtr is safe to use because it ensures that the ForeignPtr is kept live until it returns. The documentation is a little terse on this issue; I'll see if I can improve it. Cheers, Simon ___ Glasgow-haskell-users mailing list [EMAIL PROTECTED] http://www.haskell.org/mailman/listinfo/glasgow-haskell-users
RE: Ptr and ForeignPtr Questions
At 2001-09-20 02:46, Simon Marlow wrote: No, it's not safe. The reason is that the compiler can track a ForeignPtr to discover when it dies, in order to run the finalizer, but it can't track a Ptr. As soon as you drop all references to the ForeignPtr then the finalizer will run, even if you converted it to a Ptr and you're still using it. OK, there are different types of safety. The risk here is that the finalisers may have been called by the time you use the Ptr. But if you don't mind that, for instance, if for some reason the finalisers don't render the Ptr invalid, I assume you can still use the Ptr. -- Ashley Yakeley, Seattle WA ___ Glasgow-haskell-users mailing list [EMAIL PROTECTED] http://www.haskell.org/mailman/listinfo/glasgow-haskell-users
Re: Ptr and ForeignPtr Questions
At 2001-09-20 06:55, Manuel M. T. Chakravarty wrote: The FFI does not ensure any type consistency between the arguments to `Ptr'/`ForeignPtr' and the corresponding C types. I've been using 'Ptr Word8' with newArray to pass lists of bytes to C functions. They appear as unsigned char arrays in the C function. Is this wrong, or not guaranteed? -- Ashley Yakeley, Seattle WA ___ Glasgow-haskell-users mailing list [EMAIL PROTECTED] http://www.haskell.org/mailman/listinfo/glasgow-haskell-users
Re: Ptr and ForeignPtr Questions
Ashley Yakeley [EMAIL PROTECTED] wrote, At 2001-09-20 06:55, Manuel M. T. Chakravarty wrote: The FFI does not ensure any type consistency between the arguments to `Ptr'/`ForeignPtr' and the corresponding C types. I've been using 'Ptr Word8' with newArray to pass lists of bytes to C functions. They appear as unsigned char arrays in the C function. Is this wrong, or not guaranteed? It is guaranteed that when you marshal a `[Word8]' into a `Ptr Word8' with newArray that you get a contiguous memory area filled with the bytes from the list. So, what you are doing is perfectly fine. What I meant with the remark that you quote is that if you would use foreign import foo :: Ptr Int - IO Float with float foo (float *x) { return *x; } the system will not complain, but your program may dump core. Manuel ___ Glasgow-haskell-users mailing list [EMAIL PROTECTED] http://www.haskell.org/mailman/listinfo/glasgow-haskell-users
Re: Ptr and ForeignPtr Questions
At 2001-09-20 19:32, Manuel M. T. Chakravarty wrote: What I meant with the remark that you quote is that if you would use foreign import foo :: Ptr Int - IO Float with float foo (float *x) { return *x; } the system will not complain, but your program may dump core. What if the C looked like this: float foo (int *x) { return *x; } ...? -- Ashley Yakeley, Seattle WA ___ Glasgow-haskell-users mailing list [EMAIL PROTECTED] http://www.haskell.org/mailman/listinfo/glasgow-haskell-users