Safe API with tagged values - ffi

Many libraries have an interface where one must first call a function to initialize the library, which returns some value (often a pointer, sometimes called a "context" or "handle") to pass to other functions, for example (in C):
Library *initialize(long flags);
A mkA(Library *library, long n);
B mkB(Library *library, A a);
Calling mkB if a was not created with the same context library is an error.
I want to bind the API in Agda (thru Haskell), and enforce the same-context requirement in the type system, but am not sure how to do so safely. (Note the API is pure in that mkA for example returns an equivalent value each time it is called with the same arguments.) My idea of the API is as follows:
module Data.Tagged where
open import Level
data Tagged {ℓ ℓ′} {A : Set ℓ} (a : A) (B : Set ℓ′) : Set (ℓ ⊔ ℓ′) where
tag : B → Tagged a B
module Raw where
postulate
Library A B HsWord : Set
initialize : IO Library
mkA : Library → HsWord → A
mkB : Library → A → B
{-# COMPILE GHC Library = type Library #-}
{-# COMPILE GHC A = type A #-}
{-# COMPILE GHC B = type B #-}
{-# COMPILE GHC HsWord = type Word #-}
open import Data.Tagged
open Raw public using (Library)
module _ {lib : Library} where
A B : Set
A = Tagged lib A
B = Tagged lib B
mkA : Raw.HsWord → A
mkA n = tag (Raw.mkA lib n)
mkB : A → B
mkB a = tag (Raw.mkB lib a)
Thus type safety would be ensured — mkB accepts only A values made with the same Library — except one can write the following term:
castTagged : ∀ {a a′ B} → Tagged a B → Tagged a′ B
castTagged (tag b) = tag b
I would make the definitions
A = Tagged lib A
B = Tagged lib B
abstract, except so they would become irreducible even in other type signatures in the same module. I'd like to be able to define these to be reducible in the same module but irreducible elsewhere but am not sure it's possible. I would like to keep Data.Tagged in a separate module so i can prove other theorems about it there, rather than redefine it for each library i want to bind.
Anyhow, how can one define such a tag-safe API in Agda?

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 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 EXPORT_SYMBOL uniquely with the function's arguments?

As we all know when using EXPORT_SYMBOL("function name") we get into the symbol list in System.map the function name as symbol.
c041bc90 b packet_sklist
c041bc94 b packet_sklist_lock
c041bc94 b packet_socks_nr
c041bc98 A __bss_stop
c041bc98 A _end
c041c000 A pg0
ffffe400 A __kernel_vsyscall
My question is: is there any compile option, hacking, macro or anything in the world enables you to include also the arguments of the function ?
i.e
c041bc90 b packet_sklist (list of arguments...)
two reasons for these:
you can export do_something(int a) and export do_something(int a,int b) .
you won't have bugs when using extern functions in kernel modules
which have mismatch in the arguments.
The no 1 reason you've shown, even if EXPORT_SYMBOL supports argument, it won't support variable argument, cause Linux uses C.

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