FFI and a struct containing a string and allocating memory space

If I have a struct like struct EventInfo { char * event_name; int year; int month; int date; } and an associated haskell datatype that I want to marshall into it, it seems to me that I can't take advantage of the speed advantages of alloca (and its friends like "with") The only safe way I've thought of to do this is to do this is to have the poke function for EventInfo (the associated haskell type) call malloc (or newCAString or something) and then poking the string into the newly allocated space. I realized after a few successful runs of using withCString in the poke function for EventInfo, that I don't think that this (calling withCString from the poke function) was a safe approach, and I'm thinking it was just dumb luck that this worked at all. Thoughts? Am I on the right track? Am I missing any better approaches? (I'm using Haskell 8.0.1 and a Storable instance for EventInfo, BTW)

You could make your own `withEventInfo :: EventInfo -> (Ptr CEventInfo -> IO a) -> IO a` that calls withCString internally, and gives the passed function a pointer that is valid for the execution of the function. You could also use inline-c http://hackage.haskell.org/package/inline-c and create a struct EventInfo when you need it, and then you know that your bindings are typesafe, which you don't get with Storable etc. On Tue, Aug 8, 2017 at 7:45 PM, Brian Sammon < haskell-cafe@brisammon.fastmail.fm> wrote:
If I have a struct like struct EventInfo { char * event_name; int year; int month; int date; }
and an associated haskell datatype that I want to marshall into it, it seems to me that I can't take advantage of the speed advantages of alloca (and its friends like "with")
The only safe way I've thought of to do this is to do this is to have the poke function for EventInfo (the associated haskell type) call malloc (or newCAString or something) and then poking the string into the newly allocated space. I realized after a few successful runs of using withCString in the poke function for EventInfo, that I don't think that this (calling withCString from the poke function) was a safe approach, and I'm thinking it was just dumb luck that this worked at all.
Thoughts? Am I on the right track? Am I missing any better approaches?
(I'm using Haskell 8.0.1 and a Storable instance for EventInfo, BTW) _______________________________________________ Haskell-Cafe mailing list To (un)subscribe, modify options or view archives go to: http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe Only members subscribed via the mailman list are allowed to post.

On Tue, 8 Aug 2017 20:03:16 +0200
Patrick Chilton
You could make your own `withEventInfo :: EventInfo -> (Ptr CEventInfo -> IO a) -> IO a` that calls withCString internally, and gives the passed function a pointer that is valid for the execution of the function. You
This seems a little more complicated than the malloc method, so I think I'd save it for if using the malloc method makes my program too slow. Also, I was thinking of a solution similar to what you suggested, and it seems like it would require having the "poke" for the EventInfo Storable not actually put all the data in the C Struct (or not actually using "poke", but something lower-level, for the more-efficient marshalling system). I envisioned having the EventInfo poke only poking the int fields, and the withCString that populates the string field living elsewhere. It seems like this would work, but it seems not quite kosher in some way to have a poke that doesn't marshal the full set of fields.

Then have a separate struct and datatype for the last three fields,
and make that Storable. Alternatively, look into using ForeignPtrs, so
you can have the finalizer free the memory for the EventInfo.
Another thing you might try instead, if you have control of the code,
is to change EventInfo to
struct EventInfo {
int year;
int month;
int day;
char event_name[1];
};
and use the variable-sized-struct-array trick whose actual name I don't know.
On Tue, Aug 8, 2017 at 9:19 PM, Brian Sammon
On Tue, 8 Aug 2017 20:03:16 +0200 Patrick Chilton
wrote: You could make your own `withEventInfo :: EventInfo -> (Ptr CEventInfo -> IO a) -> IO a` that calls withCString internally, and gives the passed function a pointer that is valid for the execution of the function. You
This seems a little more complicated than the malloc method, so I think I'd save it for if using the malloc method makes my program too slow.
Also, I was thinking of a solution similar to what you suggested, and it seems like it would require having the "poke" for the EventInfo Storable not actually put all the data in the C Struct (or not actually using "poke", but something lower-level, for the more-efficient marshalling system). I envisioned having the EventInfo poke only poking the int fields, and the withCString that populates the string field living elsewhere. It seems like this would work, but it seems not quite kosher in some way to have a poke that doesn't marshal the full set of fields.
_______________________________________________ Haskell-Cafe mailing list To (un)subscribe, modify options or view archives go to: http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe Only members subscribed via the mailman list are allowed to post.
participants (3)
-
Brian Sammon
-
Patrick Chilton
-
Zemyla