Calling Haskell FFI Function Ptrs from C - c

I am trying to get the following code to work:
sample_hs :: CInt -> (CInt -> CInt)
sample_hs x = (x+)
foreign export ccall sample_hs :: CInt -> (CInt -> CInt)
I would like to be able to do something like this in c:
pf = sample_hs(2);
result = pf(3); //Should be 5;
When I try to do this, however, I get an error message:
error: too few arguments to function ‘sample_hs’
I am guessing that the interface between the language isn't working how I thought it would. Is there a way to do what I'm trying to do?

It is possible, FFI Does allow Higher-Order functions to be exported. Some modifications to your Haskell is required though:
{-# LANGUAGE ForeignFunctionInterface #-}
module Main where
import Foreign.C.Types
import Foreign
foreign export ccall sample_hs :: CInt -> IO (FunPtr Sample)
type Sample = CInt -> CInt
foreign import ccall "wrapper" mkSample :: Sample -> IO (FunPtr Sample)
sample_hs :: CInt -> IO (FunPtr Sample)
sample_hs x = mkSample (x+)
main = return ()
Higher-Order functions are exported in Haskell by using the explicit FunPtr type. Just to make it a bit clear I've named the higher ordered type Sample in this case. In order to be able to create a function pointer you need to use a "wrapper" function, hence the extra FFI declaration.
I haven't tested this, But it should work fine, It compiles anyway. More on FunPtr here
-- EDIT I have tested It and it works fine. returns 5 as expected.
If you're by any chance doing this on windows, I have a package on hackage Hs2Lib that would export Haskell functions and compile them to a .DLL automatically for you. It also provides you includes for C/C++ and C#. If You're on Linux however, I'm still working on that.
shameless plug :P
Using Hs2Lib the only thing you need in your file is:
module Test where
-- ## Export
sample_hs :: Int -> IO (Int -> Int)
sample_hs x = return (x+)
and a simple call to Hs2lib
PS C:\Users\Phyx\Desktop> hs2lib .\Test.hs
Linking main.exe ...
Done.
The reason for the IO and explicit return is that Int -> (Int -> Int) is just Int -> Int -> Int, since types are right associative. But Int -> IO (Int -> Int) indicates that you want to return a function. It's in IO because creating a function pointer is a side-effecting operation.
For completeness the C file used is:
#include <stdio.h>
#include <stdlib.h>
#include "Hs2lib_FFI.h"
/*
*
*/
int main(int argc, char** argv) {
HsStart();
CBF1_t pf = sample_hs(2);
int result = pf(3);
printf("%d\n", result);
HsEnd();
return (EXIT_SUCCESS);
}
So It's pretty plug-n-play. But again, It only works for Windows for now.

Although I can't find a clause that specifies it in the FFI, I'm pretty sure that no functions are exported with partial application abilities. The C declaration corresponding to
foreign export ccall sample_hs :: CInt -> CInt -> CInt
is
int sample_hs(int, int);
not
type int (*function_pointer)(int); // or whatever the right syntax is
function_pointer sample_hs(int);
Moreover, the syntax for foreign types forbids exporting higher-order functions -- so function pointers never appear in the declarations on the C side.

Related

How to use C library from Haskell?

I am trying to call a C function from Haskell using the FFI and I keep getting this error :
ghc.exe: ^^ Could not load 'getSize', dependency unresolved. See top
entry above.
main: ByteCodeLink: can't find label During interactive linking, GHCi
couldn't find the following symbol: getSize This may be due to you
not asking GHCi to load extra object files, archives or DLLs needed by
your current session. Restart GHCi, specifying the missing library
using the -L/path/to/object/dir and -lmissinglibname flags, or simply
by naming the relevant files on the GHCi command line. Alternatively,
this link failure might indicate a bug in GHCi. If you suspect the
latter, please send a bug report to:
glasgow-haskell-bugs#haskell.org
I am using the stdio.h library in my C library:
C library
// lib.h
#include <stdio.h>
double getSize() {
double size = 0;
scanf("$f", &size);
return size;
}
FFI module
{-# LANGUAGE ForeignFunctionInterface #-}
module Ffi where
import Foreign
import Foreign.C.Types
foreign import ccall "lib.h getSize" c_size :: IO Double
Main
module Main where
import Ffi
main :: IO ()
main = do a <- getLine
b <- c_size
print $ "got from C: " ++ show b
Running script
gcc -o lib -lib.h
runghc main
P.S. Could this be because I somehow have to specify the dependency stdio.h somewhere else too?
Okay, there are several things to do here:
Rename "lib.h" to "lib.c". It's a C source file (containing code), not a C header file.
Ideally, add a separate "lib.h" header file with the prototype for getSize.
Fix the bug in "lib.c". You want "%lf" in place of "$f" to read in a double.
Compile the program with ghc instead of running it with runghc. A single ghc command can compile and link both Haskell modules and C code.
In other words, your files should look like:
// lib.c
#include "lib.h"
#include <stdio.h>
double getSize() {
double size = 0;
scanf("%lf", &size);
return size;
}
// lib.h
double getSize(void);
-- Ffi.hs
{-# LANGUAGE ForeignFunctionInterface #-}
module Ffi where
import Foreign
import Foreign.C.Types
foreign import ccall "lib.h getSize" c_size :: IO Double
-- Main.hs
module Main where
import Ffi
main :: IO ()
main = do a <- getLine
b <- c_size
print $ "got from C: " ++ show b
and you should compile it with:
$ ghc Main.hs lib.c
[1 of 2] Compiling Ffi ( Ffi.hs, Ffi.o )
[2 of 2] Compiling Main ( Main.hs, Main.o )
Linking Main ...
Then you can run it, supply a line for the Haskell getLine and a second line for the C scanf, and it should work fine:
$ ./Main
hello world!! -- line for Haskell
135.0 -- line for C
"got from C: 135.0"

Use C functions in Idris

Idris can compile .idr to C-code (JS, NodeJS). Is it possible to do so in reverse direction - compile C-code to Idris format? Or, maybe, to use C functions direct in Idris code?
Sure! Take a look at the foreign function interface (FFI). Based on your compilation target (f.e. C, JavaScript, …) you can use the native functions like this example call of void *fileOpen(char *path, char *mode) inside the IO monad:
do_fopen : String -> String -> IO Ptr
do_fopen f m
= foreign FFI_C "fileOpen" (String -> String -> IO Ptr) f m

How to pass a string from Haskell to C?

All I want to do is pass a plain-text string from Haskell to C. However, it says that [Char] is an unacceptable return type. I can't find anywhere why they think it is, nor what acceptable return types are.
I'm trying to make a very simple OS image that I can boot with Qemu.
Does anyone know how to do this? Thanks.
{-# LANGUAGE ForeignFunctionInterface #-}
module Hello where
import Foreign
import Foreign.C.String
import Foreign.C.Types
hello :: String -> (CString -> IO a) -> IO a
hello = "Hello, world!"
foreign export ccall hello :: String -> (CString -> IO a) -> IO a
You want a CString.
Going from CString to String:
peekCString :: CString -> IO String
Going from String to CString:
withCString :: String -> (CString -> IO a) -> IO a
There's also Haddock documentation for module Foreign.C.String.
The general list of types that can be used in foreign declarations is specified as part of the Foreign Function Interface in the Haskell Report.
Edit
Ok, here's a very small example of a thing you can do, somewhat based on your sample code. Create a Haskell file CTest.hs with the following contents:
module CTest where
import Foreign.C
hello :: IO CString
hello = newCString "hello"
foreign export ccall hello :: IO CString
Then create a C file ctest.c with the following contents:
#include <stdio.h>
#include "CTest_stub.h"
int main (int argc, char *argv[]) {
hs_init(&argc, &argv);
printf("%s\n", hello());
hs_exit();
return 0;
}
Then compile and run as follows:
$ ghc CTest
[1 of 1] Compiling CTest ( CTest.hs, CTest.o )
$ ghc -o ctest ctest.c CTest.o -no-hs-main
$ ./ctest
hello
I think what you need is System.IO.Unsafe.unsafePerformIO to convert IO CString to CString before sending the CString to C. newCString will convert a Haskell String to IO CString. Thus System.IO.Unsafe.unsafePerformIO $ newCString a can be passed to your C routine which will accept input of type char*. If your C routine returns static char* then System.IO.Unsafe.unsafePerformIO $ peekCString will give you back a Haskell string. You need to import System.IO.Unsafe. unsafePerformIO has an implementation in Foreign.C.String (or Foreign.C.Types ?) which is deprecated, so you have to use the full path. I had a hell of a time before I could find unsafePerformIO - probably because people are allergic to something that is so dangerous as to force declaration of impure to pure. newCString can lead to memory leaks if used repeatedly without cleaning. withCString may be a better option - will learn that later.

Passing void * through haskell

I'm working on a C library (libpandoc) that uses a haskell library (pandoc) to do some work. The C library gives the haskell wrapper callbacks to read and write data. Typical with callbacks, I would also like to send a void *user_data so that the callbacks would not have to depend on global variables.
Searching the internet however, I can't seem to figure out how to pass Haskell a void * variable.
There is the CString which is a char * (and can eventually be used as a workaround, but it's not so nice) and the general Ptr which makes pointers out of things. However, those things seem not to include void (which is also understandable). Looking at Foreign.C I don't see anything else that could be useful.
My question is, what type can I use to pass such a function to Haskell?
int func(char *buffer, void *user_data);
...
that_haskell_function(..., func, my_data);
Any pointer type at all should work, I think, but Ptr () makes the most sense.
{-# LANGUAGE ForeignFunctionInterface #-}
import Foreign
import Numeric
foreign import ccall unsafe "foo"
c_foo :: Ptr () -> IO ()
main :: IO ()
main =
allocaBytes 8 $ \ptr -> do
c_foo ptr
x <- peek (castPtr ptr) :: IO Word64
putStrLn (showHex x "")
And the C file:
#include <string.h>
void foo(void *ptr)
{
memset(ptr, 0xEB, 8);
}
Gives the result:
ebebebebebebebeb

No output from a Fortran program using the Gnu Scientific Library via a c wrapper

I'm trying to write a wrapper to use the gsl library with Fortran. I have managed to get a simple wrapper to work - the example from http://www.helsinki.fi/~fyl_tlpk/luento/ohj-13-GSL-e.html
Fortran code
program gsltest
implicit none
real(kind=selected_real_kind(12)) :: a = 0.11, res
external :: glsgateway
call gslgateway(a,res)
write(*,*) 'x', a, 'atanh(x)', res
end program gsltest
c function
#include <gsl/gsl_math.h>
void gslgateway_(double *x, double *res){
*res = gsl_atanh(*x);
}
That's all well and good. However, I'm having problems with a more complicated wrapper. I have the following code modified from an example at http://apwillis.staff.shef.ac.uk/aco/freesoftware.html
c wrapper (rng_initialise.c)
#include <gsl/gsl_rng.h>
#include <gsl/gsl_randist.h>
static gsl_rng* r;
void rng_initialise__(int* s) {
r = gsl_rng_alloc(gsl_rng_taus);
gsl_rng_set(r, (unsigned long int)(*s));
}
Fortran main (main.f90)
PROGRAM main
integer seed
call system_clock(seed)
WRITE (*,*) 'calling rng_initialise'
call rng_initialise(seed)
END PROGRAM main
which I then compile and link by
gcc -c rng_initialise.c
g95 -c main.f90
g95 -o main main.o rng_initialise.o -L/usr/libs -lgsl
When I run this program, I get no output. However, if I comment out the lines inside rng_initialise
...
void rng_initialise__(int* s) {
// r = gsl_rng_alloc(gsl_rng_taus);
// gsl_rng_set(r, (unsigned long int)(*s));
}
then I get output from the Fortran code (it writes 'calling_rng_initialise' to STDOUT).
So, the problem seems to be the calls to gsl_rng_alloc and gsl_rng_set. But I don't get any error messages, and I don't know why they would prevent the Fortran code from doing anything. Any ideas?
As already suggested, the best way to do this is to use the Fortran ISO C Binding because it will instruct Fortran to use the C calling conventions to match the C routines of the GSL library. The ISO C Binding is part of the Fortran 2003 standard and has been available in many Fortran 95 compilers for several years. As part of the standard it makes interfacing Fortran and C, in both directions, portable and much easier than the OS and compiler dependent hacks that used to be necessary. I recommend ignoring instructions that pre-date the ISO C Binding as obsolete.
Generally you won't need to write any C wrapper code to call the GSL library, only Fortran specifications statements to describe the C routine interfaces to Fortran in Fortran syntax. Here is a simple example that calls the GSL routine gsl_cdf_chisq_Q
program cum_chisq_prob
use iso_c_binding
interface GSL_CummulativeChiSq_Prob_Upper
function gsl_cdf_chisq_Q ( x, nu ) bind ( C, name="gsl_cdf_chisq_Q" )
import
real (kind=c_double) :: gsl_cdf_chisq_Q
real (kind=c_double), VALUE, intent (in) :: x
real (kind=c_double), VALUE, intent (in) :: nu
end function gsl_cdf_chisq_Q
end interface GSL_CummulativeChiSq_Prob_Upper
real (kind=c_double) :: chisq_value
real (kind=c_double) :: DoF
real (kind=c_double) :: Upper_Tail_Prob
write ( *, '( / "Calculates cumulative upper-tail probability for Chi-Square distribution." )' )
write ( *, '( "Input Chisq Value, Degrees of Freedom: " )', advance='no' )
read ( *, * ) chisq_value, DoF
Upper_Tail_Prob = gsl_cdf_chisq_Q ( chisq_value, DoF )
write ( *, '( "Probability is:", 1PG17.10 )' ) Upper_Tail_Prob
stop
end program cum_chisq_prob
Even easier: you can find a pre-written library to allow you to call GSL from Fortran at http://www.lrz.de/services/software/mathematik/gsl/fortran/
Most likely you have the linkage between the two routines wrong in some way. If the stack isn't dealt with correctly when you hop through that interface, dang near anything can happen.
I'm not noticing any code on either the Fortran side or the C side specifying the other's calling convention. I'm not an expert with Gnu Fortran, but I know most compilers will require some kind of note that they should be using another compiler's calling convention, or Bad Things may happen.
With just a little web searching, I see that the G95 Fortran manual (PDF) has a nice long section titled "Interfacing with G95 Programs", that appears to go into this in detail. Just from skimming, it looks like you should be using the BIND(C) attribute on your Fortran function declaration for that C routine.
The problem is with the static gsl_rng* r; defined in your C file. But I do not know/understand why the standard does not allow this. After studying the source file of the fgsl package a little bit, I found a tweak that works. The fortran file random_f.f90
module fgsl
use, intrinsic :: iso_c_binding
implicit none
type, bind(C) :: fgsl_rng_type
type(c_ptr) :: gsl_rng_type_ptr = c_null_ptr
end type fgsl_rng_type
type, bind(C) :: fgsl_rng
type(c_ptr) :: gsl_rng_ptr = c_null_ptr
end type fgsl_rng
end module fgsl
PROGRAM call_fgsl_rndm
use, intrinsic :: iso_c_binding
use fgsl
implicit none
interface
subroutine srndm(seed, t, r) bind(C)
import
integer(C_INT) :: seed
type(fgsl_rng) :: r
type(fgsl_rng_type) :: t
end subroutine srndm
function rndm(r) bind(C)
import
real(C_DOUBLE) :: rndm
type(fgsl_rng) :: r
end function rndm
end interface
type(fgsl_rng) :: r
type(fgsl_rng_type) :: t
integer(C_INT) :: seed
real(C_DOUBLE) :: xi
seed = 1
call srndm(seed, t, r)
xi = rndm(r)
print *, xi
xi = rndm(r)
print *, xi
xi = rndm(r)
print *, xi
END PROGRAM
and the C file random_c.c
#include <gsl/gsl_rng.h>
typedef struct{
gsl_rng *gsl_rng_ptr;
} fgsl_rng;
typedef struct{
gsl_rng_type *gsl_rng_type_ptr;
} fgsl_rng_type;
void srndm(int *seed, fgsl_rng_type* t, fgsl_rng* r) {
t->gsl_rng_type_ptr = (gsl_rng_type *) gsl_rng_mt19937; // cast to remove the const qualifier
r->gsl_rng_ptr = gsl_rng_alloc(gsl_rng_mt19937);
gsl_rng_set(r->gsl_rng_ptr, *seed);
}
double rndm(fgsl_rng* r) {
return gsl_rng_uniform(r->gsl_rng_ptr);
}
Although only the pointers in the structures are used, the introduction of fgsl_rng and fgsl_rng_type is necessary. Otherwise, the program will fail. Unfortunately, I still have no clear idea why it has to work this way.

Resources