Hello Lets say I have a library in C with a header like this: #include <stdio.h> /*really big structure*/ typedef struct { int *a; int *b; /*lots of stuff ... */ int *z; } foo; /*this function allocate memory and fill the structure, reading from a file*/ int create_foo(foo *f,FILE *file,int x,int y); /*some functions that use the structure*/ int use_foo(foo *f,int w); /*a funtion that releases the memory*/ int destroy_foo(foo *f); And I want to use it in haskell using FFI. I can create a .hsc file like this: {-# LANGUAGE CPP, ForeignFunctionInterface #-} import Foreign import Foreign.C.Types #include "foo.h" newtype Foo = Foo () foreign import ccall "static foo.h create_foo" c_create_foo :: Ptr (Foo) -> Ptr (CFile) -> CInt -> CInt -> IO CInt foreign import ccall "static foo.h use_foo" c_use_foo :: Ptr (Foo) -> CInt -> IO CInt foreign import ccall "static foo.h destroy_foo" c_destroy_foo :: Ptr (Foo) -> IO CInt It compiles but I have no idea how to call c_create_foo and get back Foo Any suggestions? thanks
typedef struct { int *a; int *b; /*lots of stuff ... */ int *z; } foo; int create_foo(foo *f,FILE *file,int x,int y); int use_foo(foo *f,int w); int destroy_foo(foo *f);
newtype Foo = Foo () foreign import ccall "static foo.h create_foo" c_create_foo :: Ptr (Foo) -> Ptr (CFile) -> CInt -> CInt -> IO CInt foreign import ccall "static foo.h use_foo" c_use_foo :: Ptr (Foo) -> CInt -> IO CInt foreign import ccall "static foo.h destroy_foo" c_destroy_foo :: Ptr (Foo) -> IO CInt
Your 'create_foo' is only an initialization function, i.e., it initializes data in a Foo but do not allocate memory for the data such pointer points to. So, what you would like to do is something like this: import Foreign.Marshall.Alloc (...) ptrFoo <- malloc c_create_foo ptrFoo ptrCFile (...) (...) free ptrFoo Looking at malloc you see: malloc :: Storable a => IO (Ptr a) and this gives you the hint: you need to make an instance of Storable class with your Foo type. Storable method 'sizeOf' should provide the proper size to be used in such kind of memory allocation. (After that, you would probably want to learn about ForeignPtr, which would call, say, free and c_destroy_foo when your pointer is not beeing used anymore.) Best, Maurício P.S.: (Warning: spam promoting my own work.) If you use my package bindings-common, available in hackage, you can get that type and instance in a .hsc file by doing this: #bindings_starttype struct foo #bindings_stoptype _ But this package is not very popular yet, so I can't guarantee it's bug free.
participants (2)
-
José Prous -
Maurício CA