I need to call some dynamically linked routines recieved via Posix.DynamicLinker but am unsure how to do this from haskell. I do not know the types of the functions I wish to call at compile time so can't create appropriate foreign import statements. What would be nice is something like callFunPtr :: (Storable a, Storable b) => FunPtr z -> a -> IO b with a being a tuple if I want to push multiple arguments onto the stack perhaps. this function should be straightforward to implement, as it just needs to place the arguments on the stack in the appropriate fashion and pull the return value of out the proper register or memory location, but would obviously be very architecture specific so should be provided by the compiler. does something like this exist? is there another way to do this? John -- --------------------------------------------------------------------------- John Meacham - California Institute of Technology, Alum. - john@foo.net ---------------------------------------------------------------------------
The simplest would be to generate some C code at runtime, pass it to gcc and dynamically load the resulting .o file. Since the Storable class is for marshalling Haskell values into and out of contiguous memory, the C code you need would read values out of contiguous memory, pass them as arguments to your C function, then copy the result back into a block of contiguous memory. Details: 1) It's going to be challenging to use the resulting Haskell functions because Haskell's typechecker won't know their type at runtime. You'll probably need to use something like the Dynamic library's runtime typechecking. 2) If you don't want to invoke gcc, you could look at code from StgHugs (badly bitrotted): http://cvs.haskell.org/cgi-bin/cvsweb.cgi/fptools/ghc/rts/Attic/ForeignCall.... Versions around 1.20 seem to be about the best. This provided a function with type something like the following: HsThunk mkFun(char* argtype, char* restype, HsFunPtr fun) The two string arguments contained encodings of the argument and result types. For example, "II" translated to the C type "int, int". Finally, the Storable class doesn't seem quite right: 1) You can't use type classes with types that aren't known until runtime. (Well, you can but you have to jump through hoops to do it.) Easier to simply have a lookup table from type names to marshalling help code. 2) You almost certainly want to map a C type to a Haskell type. Storable is much more setup for mapping a Haskell type onto a list of C types. Fighting or ignoring that detail will require some more hoop jumping. Hope this helps, -- Alastair Reid www.haskell-consulting.com On Friday 17 October 2003 11:09 am, John Meacham wrote:
I need to call some dynamically linked routines recieved via Posix.DynamicLinker but am unsure how to do this from haskell. I do not know the types of the functions I wish to call at compile time so can't create appropriate foreign import statements. What would be nice is something like
callFunPtr :: (Storable a, Storable b) => FunPtr z -> a -> IO b
with a being a tuple if I want to push multiple arguments onto the stack perhaps.
this function should be straightforward to implement, as it just needs to place the arguments on the stack in the appropriate fashion and pull the return value of out the proper register or memory location, but would obviously be very architecture specific so should be provided by the compiler. does something like this exist? is there another way to do this? John
On Fri, Oct 17, 2003 at 01:38:06PM +0100, Alastair Reid wrote:
The simplest would be to generate some C code at runtime, pass it to gcc and dynamically load the resulting .o file. yeah, I considered this but want to implement an interpreter where the user has the ability to call arbitrary C functions, A C compiler can't be guarenteed to exist.
1) It's going to be challenging to use the resulting Haskell functions because Haskell's typechecker won't know their type at runtime. You'll probably need to use something like the Dynamic library's runtime typechecking. yeah, thinking about it the type I gave to callFunPtr is all wrong. something involving Dynamic or existential types will probably have to be used.
Okay, this seems like it will be much trickier than I expected, so I am thinking of the following 'hack' generate every foreign dynamic import for all types of functions with less than say 5 arguments (I can probably prune this due to argument promotion rules) then just call the appropriate mkFun on the function pointer based on the types I want to pass to it. does this seem plausable? I am not quite sure how I would chose the appropriate dynamic import when they all have different types, in any case I will probably not want to write this by hand.. is there any big overhead in attaching a ton of forign import dynamic statements to a program? John -- --------------------------------------------------------------------------- John Meacham - California Institute of Technology, Alum. - john@foo.net ---------------------------------------------------------------------------
participants (2)
-
Alastair Reid -
John Meacham