Skip to content
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

Invalid identifier for non-typedef-ed structs #25

Closed
nc6 opened this issue Jun 30, 2015 · 6 comments
Closed

Invalid identifier for non-typedef-ed structs #25

nc6 opened this issue Jun 30, 2015 · 6 comments
Assignees
Labels

Comments

@nc6
Copy link

nc6 commented Jun 30, 2015

The following block of code:

freeFoo :: Ptr Foo -- ^ Pointer to head of array
              -> IO ()
freeFoo arr = [C.block|
  struct foo *arr = $(struct foo *arr);
  foo_free(arr);
|]

fails with the following error:

    Exception when trying to run compile-time code:
      Identifier fromString: invalid string "struct foo"
    Code: template-haskell-2.10.0.0:Language.Haskell.TH.Quote.quoteExp
            C.block
            "\n\
            \  struct foo *arr = $(struct foo *arr);\n\
            \  foo_free(arr);\n"

Foo is storable and has been added to a custom context. I'm guessing this is an issue with not being able to parse non typedef-ed structs. Unfortunately the C project I'm trying to bind to has a policy of not using typedef for structs, so this is a rather big issue.

@bitonic
Copy link
Collaborator

bitonic commented Jun 30, 2015

That code you posted is invalid, since the C block is malformed (there is no return type).

In any case, what you want to do is perfectly fine, can you post a full example?

If I try with

{-# LANGUAGE TemplateHaskell #-}
{-# LANGUAGE QuasiQuotes #-}
import qualified Language.C.Inline as C
import Foreign.Ptr

C.context C.baseCtx

data Foo

freeFoo :: Ptr Foo -> IO ()
freeFoo arr = [C.block|
    struct foo *arr = $(struct foo *arr);
    foo_free(arr);
  |]

And then ghc -c foo.hs, I get

foo.hs:11:24:
    "foo.hs" (line 12, column 21):
unexpected "="
expecting "[", "(" or "{"

Which is due to the problem I mentioned (no return type).

If I fix that, for example with

{-# LANGUAGE TemplateHaskell #-}
{-# LANGUAGE QuasiQuotes #-}
import qualified Language.C.Inline as C
import Foreign.Ptr

C.context C.baseCtx

data Foo

freeFoo :: Ptr Foo -> IO ()
freeFoo arr = [C.block| int {
    struct foo *arr = $(struct foo *arr);
    foo_free(arr);
  }
  |]

I get

foo.hs:11:24:
    Could not resolve Haskell type for C type struct foo *

Which is telling you that inline-c does not know how to handle something of type struct foo *. To fix that error, you need to augment the context with an entry for struct foo *.

@nc6
Copy link
Author

nc6 commented Jul 1, 2015

Interesting. That's not the error I get, even if I fix the block declaration. Looks like I need to flesh out my example.

@nc6
Copy link
Author

nc6 commented Jul 1, 2015

Okay, here's a repository demonstrating the "invalid string" error:

https://github.com/nc6/inline-c-test

@bitonic
Copy link
Collaborator

bitonic commented Jul 1, 2015

Thanks, I can reproduce. Currently investigating.

@bitonic bitonic added the bug label Jul 1, 2015
@bitonic bitonic self-assigned this Jul 1, 2015
@bitonic bitonic added invalid and removed bug labels Jul 1, 2015
@bitonic
Copy link
Collaborator

bitonic commented Jul 1, 2015

The problem is in your Context:

  C.ctxTypesTable = Map.fromList [
    (C.TypeName "struct a0_foo", [t| Foo |])
  ]

C.TypeName expects a C identifier, but struct a0_foo isn't one. To define a mapping from a struct to an Haskell type you would specify

  C.ctxTypesTable = Map.fromList [
    (C.Struct "a0_foo", [t| Foo |])
  ]

C.TypeName is to be used with typedefs. Maybe renaming it to C.Typedef would be nicer. @mboes , any thoughts?

I'll think about how we could make this error better...

@bitonic bitonic closed this as completed Jul 1, 2015
@nc6
Copy link
Author

nc6 commented Jul 1, 2015

Aha! I see. Probably just adding some example contexts using C.Struct would help, I think.

Many thanks for your help!

Nick

On 1 Jul 2015, at 09:43, Francesco Mazzoli notifications@github.com wrote:

The problem is in your Context:

C.ctxTypesTable = Map.fromList [
(C.TypeName "struct a0_foo", [t| Foo |])
]
C.TypeName expects a C identifier, but struct a0_foo isn't one. To define a mapping from a struct to an Haskell type you would specify

C.ctxTypesTable = Map.fromList [
(C.Struct "a0_foo", [t| Foo |])
]
I'll think about how we could make this error better...


Reply to this email directly or view it on GitHub #25 (comment).

bitonic pushed a commit that referenced this issue Jul 3, 2015
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants