Skip to content

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

@lehmacdj

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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions