ffi array and peekArray

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
5 messages Options
Reply | Threaded
Open this post in threaded view
|

ffi array and peekArray

PICCA Frederic-Emmanuel
Hello,

Here the signature of one of my C function

-- hkl.h --

typedef struct _HklFactory HklFactory;

HKLAPI HklFactory **hkl_factory_get_all(size_t *n) HKL_ARG_NONNULL(1);

HKLAPI HklFactory *hkl_factory_get_by_name(const char *name,
                                           GError **error) HKL_ARG_NONNULL(1) HKL_WARN_UNUSED_RESULT;

HKLAPI const char *hkl_factory_name_get(const HklFactory *self) HKL_ARG_NONNULL(1);

HKLAPI HklGeometry *hkl_factory_create_new_geometry(const HklFactory *self) HKL_ARG_NONNULL(1);

HKLAPI HklEngineList *hkl_factory_create_new_engine_list(const HklFactory *self) HKL_ARG_NONNULL(1);


I will focuss for now only the get_all method. As you can see even for the C client of my  API HklFactory is an opac struct
This get_all method return an array of (HklFactory *) and get the size of the array via the n parameter.

So I am trying to use this API from haskell with the foreign system and return a [HklFactory]

import Foreign (Ptr, peek)
import Foreign.Marshal.Alloc (alloca)
import Foreign.Marshal.Array (peekArray)

data HklFactory

foreign import ccall safe "hkl.h hkl_factory_get_all"
        c_hkl_factory_get_all :: Ptr Int -> IO (Ptr HklFactory)

hklFactoryGetAll :: IO [HklFactory]
hklFactoryGetAll = alloca $ \n -> do
                 factories <- c_hkl_factory_get_all n
                 peekArray n factories


but indeed it doesn not work, peekArray complain that n is Ptr Int instead of Int.

what should I do in order to get my array of HklFactory

thanks for your help.


Frederic
_______________________________________________
Beginners mailing list
[hidden email]
http://mail.haskell.org/cgi-bin/mailman/listinfo/beginners
Reply | Threaded
Open this post in threaded view
|

Re: ffi array and peekArray

Sylvain HENRY
Hi,
you have to peek the pointed value. Something like:

hklFactoryGetAll :: IO [HklFactory]
hklFactoryGetAll = alloca $ \ptrn -> do
                 factories <- c_hkl_factory_get_all ptrn
                 n <- peek ptrn
                 peekArray n factories

2015-11-08 10:55 GMT+01:00 PICCA Frederic-Emmanuel <[hidden email]>:
Hello,

Here the signature of one of my C function

-- hkl.h --

typedef struct _HklFactory HklFactory;

HKLAPI HklFactory **hkl_factory_get_all(size_t *n) HKL_ARG_NONNULL(1);

HKLAPI HklFactory *hkl_factory_get_by_name(const char *name,
                                           GError **error) HKL_ARG_NONNULL(1) HKL_WARN_UNUSED_RESULT;

HKLAPI const char *hkl_factory_name_get(const HklFactory *self) HKL_ARG_NONNULL(1);

HKLAPI HklGeometry *hkl_factory_create_new_geometry(const HklFactory *self) HKL_ARG_NONNULL(1);

HKLAPI HklEngineList *hkl_factory_create_new_engine_list(const HklFactory *self) HKL_ARG_NONNULL(1);


I will focuss for now only the get_all method. As you can see even for the C client of my  API HklFactory is an opac struct
This get_all method return an array of (HklFactory *) and get the size of the array via the n parameter.

So I am trying to use this API from haskell with the foreign system and return a [HklFactory]

import Foreign (Ptr, peek)
import Foreign.Marshal.Alloc (alloca)
import Foreign.Marshal.Array (peekArray)

data HklFactory

foreign import ccall safe "hkl.h hkl_factory_get_all"
        c_hkl_factory_get_all :: Ptr Int -> IO (Ptr HklFactory)

hklFactoryGetAll :: IO [HklFactory]
hklFactoryGetAll = alloca $ \n -> do
                 factories <- c_hkl_factory_get_all n
                 peekArray n factories


but indeed it doesn not work, peekArray complain that n is Ptr Int instead of Int.

what should I do in order to get my array of HklFactory

thanks for your help.


Frederic
_______________________________________________
Beginners mailing list
[hidden email]
http://mail.haskell.org/cgi-bin/mailman/listinfo/beginners


_______________________________________________
Beginners mailing list
[hidden email]
http://mail.haskell.org/cgi-bin/mailman/listinfo/beginners
Reply | Threaded
Open this post in threaded view
|

Re: ffi array and peekArray

PICCA Frederic-Emmanuel
Ok, so now I get this error


ghkl.hs:20:18:
    No instance for (Foreign.Storable.Storable HklFactory)
      arising from a use of ‘peekArray’
    In a stmt of a 'do' block: peekArray n factories
    In the expression:
      do { factories <- c_hkl_factory_get_all ptr;
           n <- peek ptr;
           peekArray n factories }
    In the second argument of ‘($)’, namely
      ‘\ ptr
         -> do { factories <- c_hkl_factory_get_all ptr;
                 n <- peek ptr;
                 .... }’


What should I do to create a Storable for HklFactory which is a simple pointer.

Thanks

Frederic
_______________________________________________
Beginners mailing list
[hidden email]
http://mail.haskell.org/cgi-bin/mailman/listinfo/beginners
Reply | Threaded
Open this post in threaded view
|

Re: ffi array and peekArray

Sylvain HENRY
You can alias HklFactory:
type HklFactory = Ptr ()

Or if you want to avoid mixing HklFactory and other pointers, you can use:
newtype HklFactory = HklFactory (Ptr ()) deriving (Storable)

The latter requires the GeneralizedNewtypeDeriving extension, see: https://wiki.haskell.org/Foreign_Function_Interface#Renaming_and_Storable_instances

Sylvain

2015-11-08 21:30 GMT+01:00 PICCA Frederic-Emmanuel <[hidden email]>:
Ok, so now I get this error


ghkl.hs:20:18:
    No instance for (Foreign.Storable.Storable HklFactory)
      arising from a use of ‘peekArray’
    In a stmt of a 'do' block: peekArray n factories
    In the expression:
      do { factories <- c_hkl_factory_get_all ptr;
           n <- peek ptr;
           peekArray n factories }
    In the second argument of ‘($)’, namely
      ‘\ ptr
         -> do { factories <- c_hkl_factory_get_all ptr;
                 n <- peek ptr;
                 .... }’


What should I do to create a Storable for HklFactory which is a simple pointer.

Thanks

Frederic
_______________________________________________
Beginners mailing list
[hidden email]
http://mail.haskell.org/cgi-bin/mailman/listinfo/beginners


_______________________________________________
Beginners mailing list
[hidden email]
http://mail.haskell.org/cgi-bin/mailman/listinfo/beginners
Reply | Threaded
Open this post in threaded view
|

Re: ffi array and peekArray

PICCA Frederic-Emmanuel
Thanks a lot it works now :)

________________________________________
De : Beginners [[hidden email]] de la part de Sylvain Henry [[hidden email]]
Envoyé : dimanche 8 novembre 2015 21:45
À : The Haskell-Beginners Mailing List - Discussion of primarily beginner-level topics related to Haskell
Objet : Re: [Haskell-beginners] ffi array and peekArray

You can alias HklFactory:
type HklFactory = Ptr ()

Or if you want to avoid mixing HklFactory and other pointers, you can use:
newtype HklFactory = HklFactory (Ptr ()) deriving (Storable)

The latter requires the GeneralizedNewtypeDeriving extension, see: https://wiki.haskell.org/Foreign_Function_Interface#Renaming_and_Storable_instances

Sylvain

2015-11-08 21:30 GMT+01:00 PICCA Frederic-Emmanuel <[hidden email]<mailto:[hidden email]>>:
Ok, so now I get this error


ghkl.hs:20:18:
    No instance for (Foreign.Storable.Storable HklFactory)
      arising from a use of ‘peekArray’
    In a stmt of a 'do' block: peekArray n factories
    In the expression:
      do { factories <- c_hkl_factory_get_all ptr;
           n <- peek ptr;
           peekArray n factories }
    In the second argument of ‘($)’, namely
      ‘\ ptr
         -> do { factories <- c_hkl_factory_get_all ptr;
                 n <- peek ptr;
                 .... }’


What should I do to create a Storable for HklFactory which is a simple pointer.

Thanks

Frederic
_______________________________________________
Beginners mailing list
[hidden email]<mailto:[hidden email]>
http://mail.haskell.org/cgi-bin/mailman/listinfo/beginners

_______________________________________________
Beginners mailing list
[hidden email]
http://mail.haskell.org/cgi-bin/mailman/listinfo/beginners