Skip to content

C types with void explicitly in the parameter list (e.g. void (*)(void)) are assigned the wrong Haskell type #155

Description

@lehmacdj

When attempting to invoke a function with a void argument like in this snippet:

-- | - (void)prepareForReadingItemsAtURLs:(NSArray<NSURL *> *)readingURLs
--        options:(NSFileCoordinatorReadingOptions)readingOptions
--        writingItemsAtURLs:(NSArray<NSURL *> *)writingURLs
--        options:(NSFileCoordinatorWritingOptions)writingOptions
--        error:(NSError **)outError
--        byAccessor:(void (^)(void (^completionHandler)(void)))batchAccessor;
m_NSFileCoordinator_prepareForReadingAndWritingItems ::
  Ptr NSFileCoordinator ->
  Ptr NSArray ->  -- readingURLs
  NSFileCoordinatorReadingOptions ->
  Ptr NSArray ->  -- writingURLs
  NSFileCoordinatorWritingOptions ->
  Ptr (Ptr NSError) ->
  IO () ->
  IO ()
m_NSFileCoordinator_prepareForReadingAndWritingItems fileCoordinator readingURLs readingOptions writingURLs writingOptions errorPtr accessor = do
  -- let accessor' :: FunPtr (CInt -> IO ()) -> IO () = \completionHandler -> accessor ($(C.peekFunPtr [t| CInt -> IO () |]) completionHandler 0)
  [C.block| void {
    [$(NSFileCoordinator *fileCoordinator)
      prepareForReadingItemsAtURLs: $(NSArray *readingURLs)
      options: $(NSFileCoordinatorReadingOptions readingOptions)
      writingItemsAtURLs: $(NSArray *writingURLs)
      options: $(NSFileCoordinatorWritingOptions writingOptions)
      error: $(NSError **errorPtr)
      byAccessor: ^(void (^completionHandler)(void)) {
        $fun:(void (*accessor)(void))();
        completionHandler()
      }
    ];
  }
  |]

I get an error like so:

• Unacceptable argument type in foreign declaration:
    ‘()’ cannot be marshalled in a foreign call
• When checking declaration:
    foreign import ccall safe "wrapper" inline_c_ffi_6989586621681841573
      :: (() -> IO ()) -> IO (FunPtr (() -> IO ()))

Inspecting the FunPtr docs, I see that this is not the expected type for a function pointer of type void (*)(void) instead it should have type IO () or (). The bug is in buildArr in the antiquoter for $fun:. I'm working on a fix and will make a PR shortly.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions