    (_, errClassRaw) <- errorClass code
    let errClass = cToEnum errClassRaw
    unless (errClass == Success) $ do
-      errStr <- errorStringWrapper code
-      throwIO $ MPIError errClass errStr
-
-errorStringWrapper :: CInt -> IO String
-errorStringWrapper code =
+      errStr <- errorString code
+      throwIO $ MPIError errClass errStr code
+
+errorString :: CInt -> IO String
+errorString code =
   allocaBytes (fromIntegral maxErrorString) $ \ptr ->
     alloca $ \lenPtr -> do
        -- We ignore the error code from the call to Internal.errorString
        -- because we call errorString from checkError. We'd end up
        -- with an infinite loop if we called checkError here.
-       _ <- errorString code ptr lenPtr
+       _ <- errorString' code ptr lenPtr
        len <- peek lenPtr
        peekCStringLen (ptr, cIntConv len)
+  where
+    errorString' = {# call unsafe Error_string as errorString_ #}


{# fun unsafe Error_class as ^
                { id `CInt', alloca- `CInt' peek*} -> `CInt' id #}
errorString = {# call unsafe Error_string as errorString_ #}

-- | Set the error handler for a communicator.
-- This function corresponds to @MPI_Comm_set_errhandler@.

   = MPIError
     { mpiErrorClass :: ErrorClass
     , mpiErrorString :: String
     , mpiErrorCode :: CInt
     }
   deriving (Eq, Show, Typeable)

