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.