Use C functions in Idris - c

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

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"

How to generate a R wrapper for a C function that returns an int*?

I would like to generate a R (programming language) wrapper for the following C function:
int *test(void)
{
int i;
i = 1024;
return (int *) i;
}
To create this wrapper I am using SWIG with the following interface:
%module X
%{
extern int *test(void);
%}
extern int *test(void);
I can successfully create and compile this wrapper. However, when I run the following R code (the wrapper was loaded beforehand):
print(test())
It will give the following error:
Error in getClass(Class, where = topenv(parent.frame())) :
“_p_int” is not a defined class
Calls: print -> test -> new -> getClass
My question is the following: how can I wrap the C test function (more precisely the int * returned by this function)?
SWIG is not so widely used around R. But the inline package can help you.
R> library(inline)
R> foo <- cfunction(signature(i="int"), body="*i = 1024;",
+ language="C", convention=".C")
R> foo(12)$i
[1] 1024
R>
That said, you probably want .Call() instead of .C(), and you should probably look into Rcpp even if you want to use plain C -- the tooling is pretty rich and useful.

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

Calling Haskell FFI Function Ptrs from 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.

Resources