0

I am following examples (e.g. 1 or 2) to construct a data structure to pass to a C program using FFI in GHC (8.0.2). The C file tagger-api.h is:

 typedef struct {
  int  number_of_words;  /* number of words to be tagged */
  int  next_word;        /* needed internally */
  char **word;           /* array of pointers to the words */
  char **inputtag;       /* array of pointers to the pretagging information */
  const char **resulttag;/* array of pointers to the tags */
  const char **lemma;    /* array of pointers to the lemmas */
} TAGGER_STRUCT;

void init_treetagger(char *param_file_name);
double tag_sentence( TAGGER_STRUCT *ts );

The code is in a MainFFI4TT.hsc file:

{-# LANGUAGE CPP #-}
{-# LANGUAGE ForeignFunctionInterface   #-}
{-# LANGUAGE FlexibleInstances, RecordWildCards #-}

module Main     where      -- must have Main (main) or Main where

import Foreign
import Foreign.C

#include "tagger-api.h"

main =  do    
    withCString parameterFileName c_initTreeTagger    
    return ()   

parameterFileName = "/home/frank/additionalSpace/AF_amd_install/treeTagger/TreeTaggerDaemon/lib/german-utf8.par"

foreign import ccall "tagger-api.h init_treetagger"
    c_initTreeTagger :: CString -> IO ()

foreign import ccall "tagger-api.h tag_sentence"
     c_tag_sentence :: CString -> IO ()     -- structure required....

data Struct = Struct   -- this requires ccp
    { noOfWords :: !Int
    , nextWord :: !Int
    , wordsIn :: ![String]
    , pretag :: ![String]
    , tags :: ![String]
    , lemmas :: ![String]
    }
{-
type StructPtr = Ptr Struct
instance Storable Struct  where
    alignement _ = #{alignment TAGGER_STRUCT}
    sizeOf _ = #{size TAGGER_STRUCT}
    poke p  Struct{..} = do
        number_of_words <- newCString noOfWords
        nextWord <- CInt nextWord
     -}

the cabal stanza is:

executable ttclient
    main-is:    MainFFI4TT.hs
    build-depends: base
    default-language: Haskell2010
    hs-source-dirs: src
    other-modules:
    Include-dirs: treetaggerSourceC
    Includes: tagger-api.h
    extra-libraries: treetagger
    extra-lib-dirs: /home/frank/Workspace8/repo8/treeTaggerClient/treetaggerSourceC

I was confused whether the file should have the extension .hsc or .cpphs - I was under the erroneous impression, that the .hsc file is automatically produced, now I have one. I assume that cabal is automatically converting the .hsc to a .hs, but it now fails with:

Linking dist/build/ttclient/ttclient ...
dist/build/ttclient/ttclient-tmp/Main.o: In function `c3Lp_info':
(.text+0x49a): undefined reference to `init_treetagger'
dist/build/ttclient/ttclient-tmp/Main.o: In function `c3Nl_info':
(.text+0x762): undefined reference to `tag_sentence'
collect2: error: ld returned 1 exit status
`gcc' failed in phase `Linker'. (Exit code: 1)

The next problem will be how to construct the structure with the array of pointers to strigs.

I appreciated the help in clarifying what preprocessor I have to use and to overcome the first hurdle. Now i am at a different one, help is greatly appreciated.

Community
  • 1
  • 1
user855443
  • 2,596
  • 3
  • 25
  • 37
  • I'm voting to close since you didn't give nearly enough information. Where is the haskell code? How are you trying to build this? – Thomas M. DuBuisson Apr 22 '17 at 21:12
  • 1
    It appears you are using `ghc` but have used CPP to include a C file... what did you think would happen when using a Haskell compiler on C code? You linked to people talking about `hsc2hs` so perhaps you want to install and use that instead of invoking GHC directly. – Thomas M. DuBuisson Apr 22 '17 at 21:14

1 Answers1

0

This new error message suggests that the libtreetagger.a library in the directory /home/frank/Workspace8/repo8/treeTaggerClient/treetaggerSourceC doesn't actually contain definitions for init_treetagger or tag_sentence, whatever tagger-api.h might say.

Can you run nm libtreetagger.a and see if init_treetagger and tag_sentence actually appear as defined symbols in that file? There should be lines like:

00000000000003b0 T init_treetagger
0000000000001c40 T tag_sentence

Specifically, the names should match exactly, the records should include addresses, and the types should be T.

K. A. Buhr
  • 45,621
  • 3
  • 45
  • 71