-
Notifications
You must be signed in to change notification settings - Fork 50
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
No way to create a foreign pointer for input and have it as an out parameter #46
Comments
I don't know who originally created this ticket in the old C2HS Trac, but here's my understanding of what's wanted here. Suppose we have a C header file typedef struct {
int a;
float b;
} oid;
void func(oid *obj, int aval, float bval); then we'd like for the following C2HS code (the module Main where
#include "issue46.h"
{#pointer *oid as Oid foreign newtype#}
{#fun func as ^ {+, `Int', `Float'} -> `Oid'#} to produce Haskell code like this: module Main where
newtype Oid = Oid (ForeignPtr Oid)
withOid :: Oid -> (Ptr Oid -> IO b) -> IO b
withOid (Oid fptr) = withForeignPtr fptr
func :: Int -> Float -> IO Oid
func a2 a3 =
mallocForeignPtrBytes 8 $ \oidfptr ->
withForeignPtr oidfptr $ \oidptr ->
let {a2' = fromIntegral a2} in
let {a3' = realToFrac a3} in
func'_ oidptr a2' a3' >>
return $ Oid oidfptr
foreign import ccall safe "Issue46.chs.h func"
func'_ :: Ptr (Oid) -> CInt -> CFloat -> IO () (some imports are missing). Here, the Does this seem like a reasonable approach? From what I can tell, it ought to cover the requirements of the original ticket. It would be useful to know which C library the original writer of the ticket was working with, to help get some better ideas of how this might work. |
I may have written the original ticket, but I'm not convinced. Doesn't seem like my writing style. But it is something I've wanted before, and I think the proposed solution is pretty reasonable. |
@JohnLato Thanks for the comment, John. No-one else has offered an opinion, so I think I'll just go ahead and do things the way I'd planned. It seems like it should be a useful capability whoever originally asked for it. |
I've implemented this pretty much as outlined above. It works for a simple test case, but there's a strong chance that it will be possible to break things by some combination of the new "+" parameters and other C2HS features. I'll close the issue for now anyway. |
Bug imported from C2HS Trac
Trac ticket created: 2012-07-04T10:45:25-0700
I have quite a few C functions like this:
... func(oid *, ...);
oid refers to a non-opaque C struct, and these functions treat it as an out parameter; a C caller would define an instance of the struct (knowing its size) and pass the address of that structure to have it filled in. I'd like to allocate memory for this struct using mallocForeignPtrBytes {# sizeof oid #}, pass the underlying Ptr to the function, and then return the foreign pointer wrapped in an opaque type (defined using {# pointer ... foreign newtype #}). Note that the documentation for mallocForeignPtrBytes specifically says that GHC implements it much more efficiently than a standard ForeignPtr with a finalizer of finalizerFree; otherwise, I could just use malloc and then wrap the pointer on the way out.
As far as I can tell, a {# fun ... #} wrapper cannot implement this pattern. Any output marshaller has to work using the same value passed to the function, which in this case would be a Ptr, not a ForeignPtr. Thus, I can't both create an OID in the input marshaller (using a - so the caller doesn't have to pass one) and return that OID from the function.
At the moment, I've come up with three workarounds, none of which work very well:
Ideally, I'd prefer to have a way to declare this pattern directly in a marshaller. I'd suggest adding a new symbol to apply to the input marshaller, which allows it to provide an output directly.
The text was updated successfully, but these errors were encountered: