Returning an empty structure from C to Haskell in c2hs

I am trying to bind to a C function that returns a struct (by value). I know I can wrap it up manually using FFI, but can't figure out how to coax c2hs into generating the correct code. It seems my function is returning a pointer.

Here's a simple example:

module Point where

#c
struct point {
  int x;
  int y;
};

struct point get_zero(void);
#endc

data Point = Point { x :: Int, y :: Int }

instance Storable Point where
    sizeOf _ = {#sizeof point#}
    alignment _ = {#alignof point#}
    peek p = point <$> liftA fromIntegral ({#get point.x #} p)
                   <*> liftA fromIntegral ({#get point.y #} p)
    poke p s = do {#set point.x #} p (fromIntegral $ x s)
                  {#set point.y #} p (fromIntegral $ y s)

{#pointer *point as PointPtr -> Point#}

-- Causes error:
{#fun get_zero as ^ { } -> `Point'#}

      

Mistake:

c2hs: Errors during expansion of binding hooks:

Point.chs:25: (column 28) [ERROR]  >>> Missing "out" marshaller!
  There is no default marshaller for this combination of Haskell and C type:
  Haskell type: Point
  C type      : (Ptr ())

      

+3


source to share


1 answer


This is currently not possible. You can create a wrapper that returns the result by pointer:

void get_zero_wrapper(struct point* p) {
  *p = get_zero();
}

      



Note that you need to allocate space for the structure, eg. using alloca

.

There is a proposal to support passing and returning C structures by value to FFI. But it is unlikely to be implemented in the near future, because it has not received enough attention from the community. The proposal needs more careful design, for example. it is unclear how it will work with other language features.

+4


source







All Articles