Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Calling Haskell from C, getting "multiple definition of main" linker error

I am trying to learn how to interface Haskell and C. To start it out, I wrote Inc.hs, the simplest thing I can conceive:

{-# LANGUAGE ForeignFunctionInterface #-}

module Inc where

import Foreign
import Foreign.C.Types

inc :: Int -> Int
inc = (+1)

foreign export ccall cinc :: CInt -> CInt
cinc :: CInt -> CInt
cinc = fromIntegral . inc . fromIntegral

And compiled it to produce Inc_stub.h:

ghc -c Inc.hs

Worked fine. I then wrote the C file, also trying to be as simple as humanly possible:

#include <stdio.h>
#include "Inc_stub.h"

int main(int argc, char *argv[]) {
    int a = 1;
    hs_init(&argc, &argv);

    a = cinc(a);

    hs_exit();
    if (a == 2) {
        puts("Worked!");
    }

    return 0;
}

Tried to compile it, got this linker error:

ghc -no-hs-main inc.c Inc -o simplest
Linking simplest.exe ...
inc.o:inc.c:(.text+0x0): multiple definition of `main'
Inc.o:inc.c:(.text+0x0): first defined here
Inc.o:inc.c:(.text+0x31): undefined reference to `cinc'
c:/program files/haskell platform/7.10.2-a/mingw/bin/../lib/gcc/x86_64-w64-mingw32/4.6.3/../../../../x86_64-w64-mingw32/bin/ld.exe: Inc.o: bad reloc address 0x0 in section `.pdata'
collect2: ld returned 1 exit status

Everything was compiled using GHC 7.10.2 on Windows 10 64-bit.

like image 783
Benjamin Figueiredo Avatar asked Feb 09 '23 00:02

Benjamin Figueiredo


2 Answers

I did the following:

  1. renamed inc.c to inc_main.c because having C object file inc.o might overlap with haskell object
  2. run ghc -c -no-hs-main Inc.hs -o Inc.o
  3. Produce C object file by gcc -O -Wall -I/usr/lib/ghc/include -c inc_main.c
  4. Link to an executable with ghc -no-hs-main Inc.o inc_main.o -o simplest
like image 135
J.J. Hakala Avatar answered Feb 28 '23 06:02

J.J. Hakala


This is just explanation of what's going on, see @Hakala's answer for the solution.

The problem is that on Windows file names are case insensitive.
When you are executing

$ ghc -no-hs-main inc.c Inc -o simplest

GHC calls GCC to compile inc.c into object file inc.o. But on Windows it also overwrites Inc.o generated by ghc -c Inc.hs. So, it is actually the same as executing

$ ghc -no-hs-main inc.c inc.o -o simplest

And linking inc.o twice will obviously result in "multiple definition" error.

like image 36
max taldykin Avatar answered Feb 28 '23 05:02

max taldykin