maurer / c-storable-deriving Goto Github PK
View Code? Open in Web Editor NEWDerivation of C-like Storable Instances
License: BSD 3-Clause "New" or "Revised" License
Derivation of C-like Storable Instances
License: BSD 3-Clause "New" or "Revised" License
This package is great, it really makes working with structs over the FFI easier. In my use-case I want to put a StablePtr
inside a struct and return the struct over the FFI. Unfortunately this does not work, as StablePtr a
does not instantiate Generic
. It results in the following error message if want to create an (orphan) instance.
instance CStorable (StablePtr a)
/home/alex/allscale/insieme/code/analysis/src/cba/haskell/insieme-hat/src/Insieme/Adapter.hs:253:10: error:
• No instance for (Generic (StablePtr a))
arising from a use of ‘c-storable-deriving-0.1.2:Foreign.CStorable.TypeClass.$dmcPeek’
• In the expression:
c-storable-deriving-0.1.2:Foreign.CStorable.TypeClass.$dmcPeek
@StablePtr a
In an equation for ‘cPeek’:
cPeek
= c-storable-deriving-0.1.2:Foreign.CStorable.TypeClass.$dmcPeek
@StablePtr a
In the instance declaration for ‘CStorable (StablePtr a)’
Since Ptr a
is an instance of Generic
I can cast the StablePtr Ctx.Context
to Ptr ()
and us this as a workaround.
Do you have an idea how I could get a StablePtr
into my struct?
Please consider showing one or two usage examples
Although I can understand not supporting sum types out of the box, as it isn't obvious what those instances should look like, I would find it helpful/useful to have some example code that facilitates automatic derivation of CStorable instances for sum types, perhaps as part of the documentation if not an official part of the library.
Feels a little strange jumping right in to this request, without saying it so let me also add: Thankyou for what you are doing/have done. This is a useful package.
Am I missing something?
Isn't this instance:
instance (Storable a) => CStorable (StorableWrap a)
completly useless?
Why would I want CStorable if I already have Storable?
It should be other way round:
instance(Generic a, CStorable (Rep a)) => Storable (StorableWrap a)
so I could derive Generic instance for my type, wrap it with StorableWrap and feed it to some function that takes Storable.
Typically when providing these generic implementation packages, you provide top level functions that act as stubs for the actual type class your interested in. I would propose that this:
class CStorable a where
cPeek :: Ptr a -> IO a
default cPeek :: (Generic a, GCStorable (Rep a)) => Ptr a -> IO a
cPeek p = fmap to $ gcPeek 0 (castPtr p)
cPoke :: Ptr a -> a -> IO ()
default cPoke :: (Generic a, GCStorable (Rep a)) => Ptr a -> a -> IO ()
cPoke p x = gcPoke 0 (castPtr p) $ from x
cAlignment :: a -> Int
default cAlignment :: (Generic a, GCStorable (Rep a)) => a -> Int
cAlignment = gcAlignment . from
cSizeOf :: a -> Int
default cSizeOf :: (Generic a, GCStorable (Rep a)) => a -> Int
cSizeOf = gcSizeOf 0 . from
Becomes just
gpeek :: (Generic a, GCStorable (Rep a)) => Ptr a -> IO a
gpeek p = fmap to $ gcPeek 0 (castPtr p)
gpoke :: (Generic a, GCStorable (Rep a)) => Ptr a -> a -> IO ()
gpoke p x = gcPoke 0 (castPtr p) $ from x
galignment :: (Generic a, GCStorable (Rep a)) => a -> Int
galignment = gcAlignment . from
gsizeOf :: (Generic a, GCStorable (Rep a)) => a -> Int
gsizeOf = gcSizeOf 0 . from
Your users would then do
data Foo = Foo { a :: X, b :: Y }
deriving (Generic)
instance Storable Foo where
peek = gpeek
poke = gpoke
sizeOf = gsizeOf
alignment = galignment
See https://hackage.haskell.org/package/generic-deriving-1.9.0/docs/Generics-Deriving-Monoid.html for a similar example (note they don't export a copy of the Monoid
type class, but just the necessary implementations for the methods).
I have a datatype with 32 fields and the offsets of some of the fields are wrong as is the global cSizeOf the structure.
My data structure:
data ObjT = ObjT Word32 Word32 CString MemoryObject (Ptr ()) Word32 Word32 (Ptr Object) (Ptr Object) (Ptr Object)
Word32 (Ptr Object) (Ptr Object) Word32 (Ptr (Ptr Object)) (Ptr Object) (Ptr Object) Int32
Word32 (Ptr Object) Word32 (Ptr Object) (Ptr ()) (Ptr ()) (Ptr ()) (Ptr ()) (Ptr ()) (Ptr ())
(Ptr (Ptr Distance)) Word32 (Ptr Info) Word32 (Ptr ())
where MemoryObject is a 32 bytes object and Ptr are 8 bytes long. The size in C is 264 with the padding bytes. With cSizeOf it is 280.
I think the problem is that fields are not evaluated from left to right hence some offsets are wrong. From the documentation of Generics:
As :+: and :: are just binary operators, one might ask what happens if the datatype has more than two constructors, or a constructor with more than two fields. The answer is simple: the operators are used several times, to combine all the constructors and fields as needed. However, users /should not rely on a specific nesting strategy/ for :+: and :: being used. The compiler is free to choose any nesting it prefers. (In practice, the current implementation tries to produce a more or less balanced nesting, so that the traversal of the structure of the datatype from the root to a particular component can be performed in logarithmic rather than linear time.)
I will try to submit a patch
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.