Re: [Haskell-cafe] FFI, C/C++ and undefined references
Stephen Tetley wrote: Also binding to a C library is easier than binding to a C++ one, if you can think of another library rather than SRILM that will meet your needs... Alas, SRILM really is the standard tool for this so there aren't other (worthwhile) options AFAIK. But it's pretty standard for people to bind to SRILM as though it were C, since C bindings are standardized and C++ is a nightmare. I haven't done the gory details myself but I sat next to someone who did. -- Live well, ~wren ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] FFI, C/C++ and undefined references
Hi all, I got it to work...finally. Basically, I used Malcolm's suggestion of tracking down all the SRILM .o files needed. I need to run now, but I'll post the gory (oh, so gory) details soon. Thanks to all who helped. Best, D.N. -- View this message in context: http://old.nabble.com/FFI%2C-C-C%2B%2B-and-undefined-references-tp27139612p27181396.html Sent from the Haskell - Haskell-Cafe mailing list archive at Nabble.com. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] FFI, C/C++ and undefined references
I still get the undefined reference errors. It is likely there is some combination of other mistakes as well then. Other responses have made suggestions of fixes you require in the C++ code for instance. You will need those as well. I did eventually get ghc to compile Main.hs by putting the -c and -cpp flags after --make Main.hs. Then it produces a Main.o file which (even with +x permissions on my Linux box) will not run. I just get the message cannot run binary file, or some such message. The file Main.o is just an object file, not a complete executable. It still needs to be linked against some other (Haskell or C/C++) object files and libraries, and the Haskell runtime system, to form an executable that can be run. ghc is capable of doing all the linking, e.g. ghc -o myProg Main.o slirm.o -package base -package foo However, if you are unsure of which Haskell packages are needed, it is wise to let ghc work out the dependencies for you, e.g. with ghc --make Main.hs slirm.o It cannot work out the C/C++ dependencies though, so every time you get undefined reference linking errors, you must discover which C code provides those symbols, and add its object file to the commandline by hand. Regards, Malcolm ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] FFI, C/C++ and undefined references
OK. Before anyone expends any e-ink replying to my reply below -- the one where I demonstrate that I don't understand what -c, -cpp mean to 'ghc' (not that you can blame me, since there isn't any documentation in the 'ghc' man page) -- I see why the Main.o file doesn't run. It's an object file, not an executable (not being from the C/C++ world, being a distinction I did not have at the forefront of my mind). Anyhow, still no dice. Even when cleaning up my Haskell code, I can't get this to compile. --D.N. DNM wrote: Note: I'm relatively new to Haskell, and my knowledge of C and C++ is basically pretty minimal -- I can read, modify and compile C/C++ programs (usually). I'm trying to interface with some C++ code by writing a little bit of C code that uses that C++ code, and I'm getting undefined reference errors when I try to 'ghc --make' a client application to test it. Actually, I'm modifying Nitin Madnani's (freely available) Python SRILM toolkit wrapper code. (SRILM, by the bye, is a C++-based toolkit for training and using statistical n-gram language models. I was surprised that no-one has tried to do this yet -- or at least not that they have shared with the rest of us.) Anyhow, I've verified that my modification of Madnani's C code works by compiling it and running it through a SWIG interface in Madnani's Python code, so I'm pretty confident the C client of SRILM is solid. The culprit is either my Haskell FFI code or the client of that code. Without cooking up a microcosm of my problem with little Foo's and Bar's, I'll just give my actual C, header file and Haskell code (or at least the relevant bits), and then the error. - srilm.h #ifdef __cplusplus extern C { #else typedef struct Ngram Ngram; /* dummy type to stand in for class */ #endif Ngram* bldLM(int order, const char* filename); void deleteLM(Ngram* ngram); float getSeqProb(Ngram* ngram, const char* ngramstr, unsigned order, unsigned length); #ifdef __cplusplus } #endif - - srilm.c // Initialize and read in the ngram model Ngram* bldLM(int order, const char* filename) { ... } ... // Delete the ngram model void deleteLM(Ngram* ngram) { delete srilm_vocab; delete ngram; } ... // Get the ngram probability of the given string, given n-gram order 'order' and string length // 'length'. float getSeqProb(Ngram* ngram, const char* ngramstr, unsigned order, unsigned length) { ...} - Next, the Haskell FFI specs and code that marshals data between Haskell and C. LM.hs -- {-# INCLUDE srilm.h #-} {-# LANGUAGE ForeignFunctionInterface, EmptyDataDecls #-} ... module decl's, imports, etc. {- | A dummy placeholder for SRILM n-gram model thingies. -} data Ngram data NGModel = NGModel {ng :: !(ForeignPtr Ngram)} foreign import ccall srilm.h bldLM c_blm :: CInt - CString - Ptr Ngram foreign import ccall srilm.h deleteLM c_dlm :: FunPtr ((Ptr Ngram) - IO ()) foreign import ccall srilm.h getSeqProb c_ngramProb :: Ptr Ngram - CString - CUInt - CUInt - CFloat {- | Given an n-gram model, an Int representing the n-gram order and a list of strings (word sequence), compute the n-gram probability of the sequence. -} scoreSequence :: NGModel - Int - [String] - Float scoreSequence ngram order seq = unsafePerformIO $ do stringSeq - newCString (unwords seq) let sc = c_ngramProb (unsafeForeignPtrToPtr $ ng ngram) stringSeq (fromIntegral order) (fromIntegral $ length seq) return (realToFrac sc) ... buildLM :: Int - String - NGModel buildLM order fname = NGModel $ unsafePerformIO $ do cFName - newCString fname let ng = c_blm (fromIntegral order) cFName return $ unsafePerformIO $ newForeignPtr c_dlm ng Now, I've defined a simple app that tries to use this: --- Main.hs - module Main where import SRILM.LM(scoreSequence, buildLM) main :: IO () main = do let lm = buildLM 5 eng.kn.5g.lm putStrLn $ show $ scoreSequence lm 5 [the, prime, minister, gave, a, speech, .] --- But when I try to compile it (after having successfully compiled the C code with g++), I get: $ ghc --make Main.hs Linking Main ... LM.o: In function `r18k_info': (.text+0x122): undefined reference to `bldLM' LM.o: In function `r18m_info': (.text+0x14e): undefined reference to `deleteLM' LM.o: In function `r18o_info': (.text+0x28b): undefined reference to `getSeqProb' collect2: ld returned 1 exit status Any ideas? Note that I'm not confident that everything on the Haskell side is correct, but it seems that ghc can't find my C
Re: [Haskell-cafe] FFI, C/C++ and undefined references
Which is weird, because 'srilm.o'/'srilm.h' are the files that define the mysterious undefined references. I'll keep plugging away and report back when (or whether) I make some progress. In the meanwhile, if anyone has a clue, I'm all ears. Best, D.N. Malcolm Wallace wrote: However, if you are unsure of which Haskell packages are needed, it is wise to let ghc work out the dependencies for you, e.g. with ghc --make Main.hs slirm.o It cannot work out the C/C++ dependencies though, so every time you get undefined reference linking errors, you must discover which C code provides those symbols, and add its object file to the commandline by hand. -- View this message in context: http://old.nabble.com/FFI%2C-C-C%2B%2B-and-undefined-references-tp27139612p27167019.html Sent from the Haskell - Haskell-Cafe mailing list archive at Nabble.com. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] FFI, C/C++ and undefined references
Am Donnerstag 14 Januar 2010 20:42:42 schrieb DNM: Which is weird, because 'srilm.o'/'srilm.h' are the files that define the mysterious undefined references. I'll keep plugging away and report back when (or whether) I make some progress. In the meanwhile, if anyone has a clue, I'm all ears. Best, D.N. Just an idea. Are you on windows? If so, then your foreign calls would probably have to be foreign import stdcall srilm.h whatever ... instead of foreign import ccall ... Malcolm Wallace wrote: However, if you are unsure of which Haskell packages are needed, it is wise to let ghc work out the dependencies for you, e.g. with ghc --make Main.hs slirm.o It cannot work out the C/C++ dependencies though, so every time you get undefined reference linking errors, you must discover which C code provides those symbols, and add its object file to the commandline by hand. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] FFI, C/C++ and undefined references
On Thu, Jan 14, 2010 at 2:08 PM, Daniel Fischer daniel.is.fisc...@web.de wrote: Just an idea. Are you on windows? If so, then your foreign calls would probably have to be foreign import stdcall srilm.h whatever ... instead of foreign import ccall ... Yes, I came here to say that too. I was getting those errors on Windows. Paulo ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] FFI, C/C++ and undefined references
Hello Daniel On Windows, isn't stdcall vs ccall still dependent on the actual library and what compiled it - commonly MSVC (stdcall) or gcc (ccall) of course? I could very easily be wrong... Best wishes Stephen 2010/1/14 Daniel Fischer daniel.is.fisc...@web.de: Am Donnerstag 14 Januar 2010 20:42:42 schrieb DNM: Just an idea. Are you on windows? If so, then your foreign calls would probably have to be foreign import stdcall srilm.h whatever ... instead of foreign import ccall ... ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re[2]: [Haskell-cafe] FFI, C/C++ and undefined references
Hello Daniel, Thursday, January 14, 2010, 11:08:24 PM, you wrote: i think you are wrong. stdcall used for std windows dlls, but gcc by default generates ccall things. and cl anyway useless here Just an idea. Are you on windows? If so, then your foreign calls would probably have to be foreign import stdcall srilm.h whatever ... instead of foreign import ccall ... Malcolm Wallace wrote: However, if you are unsure of which Haskell packages are needed, it is wise to let ghc work out the dependencies for you, e.g. with ghc --make Main.hs slirm.o It cannot work out the C/C++ dependencies though, so every time you get undefined reference linking errors, you must discover which C code provides those symbols, and add its object file to the commandline by hand. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe -- Best regards, Bulatmailto:bulat.zigans...@gmail.com ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] FFI, C/C++ and undefined references
Nope. Ubuntu Linux (Intrepid Ibex). I wish it were that simple. --D.N. Daniel Fischer-4 wrote: Am Donnerstag 14 Januar 2010 20:42:42 schrieb DNM: Which is weird, because 'srilm.o'/'srilm.h' are the files that define the mysterious undefined references. I'll keep plugging away and report back when (or whether) I make some progress. In the meanwhile, if anyone has a clue, I'm all ears. Best, D.N. Just an idea. Are you on windows? If so, then your foreign calls would probably have to be foreign import stdcall srilm.h whatever ... instead of foreign import ccall ... Malcolm Wallace wrote: However, if you are unsure of which Haskell packages are needed, it is wise to let ghc work out the dependencies for you, e.g. with ghc --make Main.hs slirm.o It cannot work out the C/C++ dependencies though, so every time you get undefined reference linking errors, you must discover which C code provides those symbols, and add its object file to the commandline by hand. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe -- View this message in context: http://old.nabble.com/FFI%2C-C-C%2B%2B-and-undefined-references-tp27139612p27167751.html Sent from the Haskell - Haskell-Cafe mailing list archive at Nabble.com. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re[2]: [Haskell-cafe] FFI, C/C++ and undefined references
Hello DNM, Thursday, January 14, 2010, 10:42:42 PM, you wrote: there is better way rather than playing with random bits. just find tutorial on FFI, and try it. once this example works, start modifying it to learn various aspects of ffi and add functionality you need it's one thing i've learned in those 20 years - go forward in small steps keeping working code instead of jumping at large distance and then spending days without any clue Which is weird, because 'srilm.o'/'srilm.h' are the files that define the mysterious undefined references. I'll keep plugging away and report back when (or whether) I make some progress. In the meanwhile, if anyone has a clue, I'm all ears. Best, D.N. Malcolm Wallace wrote: However, if you are unsure of which Haskell packages are needed, it is wise to let ghc work out the dependencies for you, e.g. with ghc --make Main.hs slirm.o It cannot work out the C/C++ dependencies though, so every time you get undefined reference linking errors, you must discover which C code provides those symbols, and add its object file to the commandline by hand. -- Best regards, Bulatmailto:bulat.zigans...@gmail.com ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] FFI, C/C++ and undefined references
Am Donnerstag 14 Januar 2010 21:39:57 schrieb DNM: Nope. Ubuntu Linux (Intrepid Ibex). I wish it were that simple. --D.N. Okay, so it's not a borken OS 8-) Can you post ought to be compiling code? That might help locate the problem. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: Re[2]: [Haskell-cafe] FFI, C/C++ and undefined references
2010/1/14 Bulat Ziganshin bulat.zigans...@gmail.com: there is better way rather than playing with random bits. just find tutorial on FFI, and try it. once this example works, start modifying it to learn various aspects of ffi and add functionality you need Also binding to a C library is easier than binding to a C++ one, if you can think of another library rather than SRILM that will meet your needs... Best wishes Stephen ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] FFI, C/C++ and undefined references
Works fine here (Mac OS X 10.5): MigMit:ngram MigMit$ ghc --make Main.hs srilm.o [1 of 2] Compiling LM ( LM.hs, LM.o ) LM.hs:9:0: Warning: possible missing in foreign import of FunPtr [2 of 2] Compiling Main ( Main.hs, Main.o ) Linking Main ... MigMit:ngram MigMit$ ls Main* Main* Main.hi Main.hs Main.hs~ Main.o MigMit:ngram MigMit$ cat Main.hs module Main where import LM(scoreSequence, buildLM) main :: IO () main = do let lm = buildLM 5 eng.kn.5g.lm putStrLn $ show $ scoreSequence lm 5 [the, prime, minister, gave,a, speech, .] MigMit:ngram MigMit$ cat LM.hs {-# INCLUDE srilm.h #-} {-# LANGUAGE ForeignFunctionInterface, EmptyDataDecls #-} module LM where import Foreign import Foreign.C data Ngram data NGModel = NGModel {ng :: !(ForeignPtr Ngram)} foreign import ccall srilm.h bldLM c_blm :: CInt - CString - Ptr Ngram foreign import ccall srilm.h deleteLM c_dlm :: FunPtr ((Ptr Ngram) - IO ()) foreign import ccall srilm.h getSeqProb c_ngramProb :: Ptr Ngram - CString - CUInt - CUInt - CFloat scoreSequence :: NGModel - Int - [String] - Float scoreSequence ngram order seq = unsafePerformIO $ do stringSeq - newCString (unwords seq) let sc = c_ngramProb (unsafeForeignPtrToPtr $ ng ngram) stringSeq (fromIntegral order) (fromIntegral $ length seq) return (realToFrac sc) buildLM :: Int - String - NGModel buildLM order fname = NGModel $ unsafePerformIO $ do cFName - newCString fname let ng = c_blm (fromIntegral order) cFName return $ unsafePerformIO $ newForeignPtr c_dlm ng MigMit:ngram MigMit$ cat srilm.h #ifdef __cplusplus extern C { class Ngram{}; #else typedef struct Ngram Ngram; #endif Ngram* bldLM(int order, const char* filename); void deleteLM(Ngram* ngram); float getSeqProb(Ngram* ngram, const char* ngramstr, unsigned order, unsigned length); #ifdef __cplusplus } #endif MigMit:ngram MigMit$ cat srilm.c #include srilm.h Ngram* bldLM(int order, const char* filename) { return 0; } void deleteLM(Ngram* ngram) {} float getSeqProb(Ngram* ngram, const char* ngramstr, unsigned order, unsigned length) { return 0;} MigMit:ngram MigMit$ Maybe you just need to recompile srilm.c or something. On 14 Jan 2010, at 23:39, DNM wrote: Nope. Ubuntu Linux (Intrepid Ibex). I wish it were that simple. --D.N. Daniel Fischer-4 wrote: Am Donnerstag 14 Januar 2010 20:42:42 schrieb DNM: Which is weird, because 'srilm.o'/'srilm.h' are the files that define the mysterious undefined references. I'll keep plugging away and report back when (or whether) I make some progress. In the meanwhile, if anyone has a clue, I'm all ears. Best, D.N. Just an idea. Are you on windows? If so, then your foreign calls would probably have to be foreign import stdcall srilm.h whatever ... instead of foreign import ccall ... Malcolm Wallace wrote: However, if you are unsure of which Haskell packages are needed, it is wise to let ghc work out the dependencies for you, e.g. with ghc --make Main.hs slirm.o It cannot work out the C/C++ dependencies though, so every time you get undefined reference linking errors, you must discover which C code provides those symbols, and add its object file to the commandline by hand. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe -- View this message in context: http://old.nabble.com/FFI%2C-C-C%2B%2B-and-undefined-references-tp27139612p27167751.html Sent from the Haskell - Haskell-Cafe mailing list archive at Nabble.com. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] FFI, C/C++ and undefined references
Am Donnerstag 14 Januar 2010 22:19:08 schrieb Miguel Mitrofanov: Works fine here (Mac OS X 10.5): MigMit:ngram MigMit$ ghc --make Main.hs srilm.o [1 of 2] Compiling LM ( LM.hs, LM.o ) LM.hs:9:0: Warning: possible missing in foreign import of FunPtr [2 of 2] Compiling Main ( Main.hs, Main.o ) Linking Main ... Thanks Miguel. Yes, works here (openSuse 11.1), too (kind of): (move the typedef out of the #else clause in srilm.h, because my g++ doesn't know Ngram) $ g++ -c srilm.c $ ghc --make Main.hs srilm.o [1 of 2] Compiling LM ( LM.hs, LM.o ) LM.hs:1:11: Warning: -#include is deprecated: No longer has any effect LM.hs:13:0: Warning: possible missing in foreign import of FunPtr [2 of 2] Compiling Main ( Main.hs, Main.o ) Linking Main ... $ ./Main 0.0 Speicherzugriffsfehler Fixing the two warnings (removing the {-# INCLUDE #-} pragma and changing the declaration of deleteLM to foreign import ccall srilm.h deleteLM c_dlm :: FunPtr ((Ptr Ngram) - IO ()) ), I get $ ghc -fforce-recomp --make Main.hs srilm.o [1 of 2] Compiling LM ( LM.hs, LM.o ) [2 of 2] Compiling Main ( Main.hs, Main.o ) Linking Main ... $ ./Main 0.0 $ ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] FFI, C/C++ and undefined references
But when I try to compile it (after having successfully compiled the C code with g++), I get: $ ghc --make Main.hs You are not telling ghc to link against the C/C++ code, e.g. ghc --make Main.hs srilm.o Regards, Malcolm ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] FFI, C/C++ and undefined references
Hello DNM, Wednesday, January 13, 2010, 8:57:45 AM, you wrote: Note: I'm relatively new to Haskell, and my knowledge of C and C++ is basically pretty minimal -- I can read, modify and compile C/C++ programs (usually). 1. you use too much unsafePerformIO. since you need newCString, i suggest you to declare C functions as returning IO a so your code will be unsafePerformIO$ do withCString str $ \c_str - do c_function c_str ... 2. if your function returns Ptr a - then hold in haskell types this Ptr a. no need to convert it back and forth to ForeignPtr 3. why c_dlm is FunPtr in your definition? it should be foreign import ccall srilm.h deleteLM c_dlm :: Ptr Ngram - IO () 4. i don't looked in your code but if C functions defines *modifiable* datastructure - you should use it at Haskell side via imperatiove functions, i.e. those with return type IO a. using unsafePerformIO in this case will lead to Haskell compiler will consider this datatype as permanent and reorder operations on the will so, data NGModel = NGModel {ng :: !(Ptr Ngram)} foreign import ccall srilm.h bldLM c_blm :: CInt - CString - IO (Ptr Ngram) foreign import ccall srilm.h deleteLM c_dlm :: Ptr Ngram - IO () foreign import ccall srilm.h getSeqProb c_ngramProb :: Ptr Ngram - CString - CUInt - CUInt - IO CFloat scoreSequence :: NGModel - Int - [String] - IO Float scoreSequence ngram order seq = do withCString (unwords seq) $ \stringSeq - do sc - c_ngramProb (ng ngram) stringSeq (fromIntegral order) (fromIntegral $ length seq) return (realToFrac sc) and so on -- Best regards, Bulatmailto:bulat.zigans...@gmail.com ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] FFI, C/C++ and undefined references
Bulat, Some very good suggestions. I will try to appease Ceiling Cat and reduce my (perhaps gratuitous) use of unsafePerformIO. I'm going to have to use it somewhere, since I want referentially transparent code (and I try to avoid the IO monad when possible, anyway). 2. if your function returns Ptr a - then hold in haskell types this Ptr a. no need to convert it back and forth to ForeignPtr Yes, I thought of doing this, but then thought it was better to use a so-called managed foreign pointer via newForeignPtr. I thought this was the best way to have a foreign pointer that the Haskell garbage collector would eat up when it was no longer in use. I could be wrong. I convert from a ForeignPtr to a Ptr, because the FFI code wasn't compiling at all (nevermind the missing C/C++ reference problem), as apparently a ForeignPtr isn't the sort of thing that an imported foreign function can take as an argument (or so said GHC). I just assumed that the back-and-forth between Ptr and ForeignPtr would be compiled away by GHC. I could be wrong, though. If performance starts to suffer, I'll manage the Ptr memory in my code directly. 4. i don't looked in your code but if C functions defines *modifiable* datastructure - you should use it at Haskell side via imperatiove functions, i.e. those with return type IO a. using unsafePerformIO in this case will lead to Haskell compiler will consider this datatype as permanent and reorder operations on the will Good point. I would do this if I planned to train or update the language model from within Haskell, but, as it stands, I just want to train it once (at the command line, using the built-in mechanisms of SRILM) and then read in the ARPA-formatted language model file for use in Haskell. 3. why c_dlm is FunPtr in your definition? it should be foreign import ccall srilm.h deleteLM c_dlm :: Ptr Ngram - IO () No reason. Just because I don't know what I'm doing yet. Thanks for the correction. Thanks for the help, Bulat. Much appreciated. Best, Dennis -- View this message in context: http://old.nabble.com/FFI%2C-C-C%2B%2B-and-undefined-references-tp27139612p27156139.html Sent from the Haskell - Haskell-Cafe mailing list archive at Nabble.com. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] FFI, C/C++ and undefined references
Malcolm, I saw this suggestion somewhere else. Unfortunately, it didn't help either. I still get the undefined reference errors. I did eventually get ghc to compile Main.hs by putting the -c and -cpp flags after --make Main.hs. Then it produces a Main.o file which (even with +x permissions on my Linux box) will not run. I just get the message cannot run binary file, or some such message. No explanation given. Any ideas? Best, Dennis Malcolm Wallace wrote: But when I try to compile it (after having successfully compiled the C code with g++), I get: $ ghc --make Main.hs You are not telling ghc to link against the C/C++ code, e.g. ghc --make Main.hs srilm.o Regards, Malcolm ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe -- View this message in context: http://old.nabble.com/FFI%2C-C-C%2B%2B-and-undefined-references-tp27139612p27156254.html Sent from the Haskell - Haskell-Cafe mailing list archive at Nabble.com. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] FFI, C/C++ and undefined references
Sorry. In my haste to paste in the .c file, I left out all the include statements. I do have #include srilm.h there (which to my non- C/C++ mind seems stupid -- why the hell would you need to import the header file for the code that it's a header *for*?) Still no dice. Thanks for your time, though. Sorry to waste it. --D.N. -- View this message in context: http://old.nabble.com/FFI%2C-C-C%2B%2B-and-undefined-references-tp27139612p27156267.html Sent from the Haskell - Haskell-Cafe mailing list archive at Nabble.com. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] FFI, C/C++ and undefined references
On Jan 13, 2010, at 23:28 , DNM wrote: Sorry. In my haste to paste in the .c file, I left out all the include statements. I do have #include srilm.h there (which to my non- C/C++ mind seems stupid -- why the hell would you need to import the header file for the code that it's a header *for*?) Really, the only reason in this case is that there is no equivalent for `extern C' that you can apply to a function definition, only to a declaration. The rationale is that everything that works with the function, including its definition, needs to see that declaration, so rather than repeat it in the definition you #include the declaration. In GHC, this is the kind of thing that lands in the .hi file; the tradeoff is you need to have up to date .hi files for everything that needs to see that information, which can lead to dependency loops. GHC has a .hs-boot hack to work around this. No free lunch -- brandon s. allbery [solaris,freebsd,perl,pugs,haskell] allb...@kf8nh.com system administrator [openafs,heimdal,too many hats] allb...@ece.cmu.edu electrical and computer engineering, carnegie mellon universityKF8NH PGP.sig Description: This is a digitally signed message part ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re[2]: [Haskell-cafe] FFI, C/C++ and undefined references
Hello DNM, Thursday, January 14, 2010, 7:07:43 AM, you wrote: Yes, I thought of doing this, but then thought it was better to use a so-called managed foreign pointer via newForeignPtr. i recommend to use Ptr and switch to ForeignPtr only when you will study how to use it. overall, unsafe* functions are really unsafe, and using them without learning will lead to mysterious problems. it's like painting with eyes closed Good point. I would do this if I planned to train or update the language model from within Haskell, but, as it stands, I just want to train it once (at the command line, using the built-in mechanisms of SRILM) and then read in the ARPA-formatted language model file for use in Haskell. you may add problems by using unsafePerformIO. i recommend you to learn first how to manage FFI without it, make program work, and only then try to use it. eat elephant in small pieces! look into http://haskell.org/haskellwiki/IO_inside -- Best regards, Bulatmailto:bulat.zigans...@gmail.com ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re[2]: [Haskell-cafe] FFI, C/C++ and undefined references
Hello Brandon, Thursday, January 14, 2010, 7:40:45 AM, you wrote: Really, the only reason in this case is that there is no equivalent for `extern C' that you can apply to a function definition, only to a declaration it works with GCC: extern C int c_szOpenArchive (TABI_ELEMENT* params) { } -- Best regards, Bulatmailto:bulat.zigans...@gmail.com ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] FFI, C/C++ and undefined references
Note: I'm relatively new to Haskell, and my knowledge of C and C++ is basically pretty minimal -- I can read, modify and compile C/C++ programs (usually). I'm trying to interface with some C++ code by writing a little bit of C code that uses that C++ code, and I'm getting undefined reference errors when I try to 'ghc --make' a client application to test it. Actually, I'm modifying Nitin Madnani's (freely available) Python SRILM toolkit wrapper code. (SRILM, by the bye, is a C++-based toolkit for training and using statistical n-gram language models. I was surprised that no-one has tried to do this yet -- or at least not that they have shared with the rest of us.) Anyhow, I've verified that my modification of Madnani's C code works by compiling it and running it through a SWIG interface in Madnani's Python code, so I'm pretty confident the C client of SRILM is solid. The culprit is either my Haskell FFI code or the client of that code. Without cooking up a microcosm of my problem with little Foo's and Bar's, I'll just give my actual C, header file and Haskell code (or at least the relevant bits), and then the error. - srilm.h #ifdef __cplusplus extern C { #else typedef struct Ngram Ngram; /* dummy type to stand in for class */ #endif Ngram* bldLM(int order, const char* filename); void deleteLM(Ngram* ngram); float getSeqProb(Ngram* ngram, const char* ngramstr, unsigned order, unsigned length); #ifdef __cplusplus } #endif - - srilm.c // Initialize and read in the ngram model Ngram* bldLM(int order, const char* filename) { ... } ... // Delete the ngram model void deleteLM(Ngram* ngram) { delete srilm_vocab; delete ngram; } ... // Get the ngram probability of the given string, given n-gram order 'order' and string length // 'length'. float getSeqProb(Ngram* ngram, const char* ngramstr, unsigned order, unsigned length) { ...} - Next, the Haskell FFI specs and code that marshals data between Haskell and C. LM.hs -- {-# INCLUDE srilm.h #-} {-# LANGUAGE ForeignFunctionInterface, EmptyDataDecls #-} ... module decl's, imports, etc. {- | A dummy placeholder for SRILM n-gram model thingies. -} data Ngram data NGModel = NGModel {ng :: !(ForeignPtr Ngram)} foreign import ccall srilm.h bldLM c_blm :: CInt - CString - Ptr Ngram foreign import ccall srilm.h deleteLM c_dlm :: FunPtr ((Ptr Ngram) - IO ()) foreign import ccall srilm.h getSeqProb c_ngramProb :: Ptr Ngram - CString - CUInt - CUInt - CFloat {- | Given an n-gram model, an Int representing the n-gram order and a list of strings (word sequence), compute the n-gram probability of the sequence. -} scoreSequence :: NGModel - Int - [String] - Float scoreSequence ngram order seq = unsafePerformIO $ do stringSeq - newCString (unwords seq) let sc = c_ngramProb (unsafeForeignPtrToPtr $ ng ngram) stringSeq (fromIntegral order) (fromIntegral $ length seq) return (realToFrac sc) ... buildLM :: Int - String - NGModel buildLM order fname = NGModel $ unsafePerformIO $ do cFName - newCString fname let ng = c_blm (fromIntegral order) cFName return $ unsafePerformIO $ newForeignPtr c_dlm ng Now, I've defined a simple app that tries to use this: --- Main.hs - module Main where import SRILM.LM(scoreSequence, buildLM) main :: IO () main = do let lm = buildLM 5 eng.kn.5g.lm putStrLn $ show $ scoreSequence lm 5 [the, prime, minister, gave, a, speech, .] --- But when I try to compile it (after having successfully compiled the C code with g++), I get: $ ghc --make Main.hs Linking Main ... LM.o: In function `r18k_info': (.text+0x122): undefined reference to `bldLM' LM.o: In function `r18m_info': (.text+0x14e): undefined reference to `deleteLM' LM.o: In function `r18o_info': (.text+0x28b): undefined reference to `getSeqProb' collect2: ld returned 1 exit status Any ideas? Note that I'm not confident that everything on the Haskell side is correct, but it seems that ghc can't find my C client of SRILM. As I said, I've compiled this code using g++, and it works when I interface with it through Python. Sorry for the long-windedness, but I figured I'd err on the side of TMI so that I don't have to keep posting more and more code snippets and error messages. Any help is greatly appreciated. (And I'd be happy to share my interface to SRILM to anyone who's interested, once I get it working -- and I get permission from Nitin Madnani to distribute a modified version of his code.) Thanks, Dennis -- View this message in context: http://old.nabble.com/FFI%2C-C-C%2B%2B-and-undefined-references-tp27139612p27139612.html Sent from the Haskell -
Re: [Haskell-cafe] FFI, C/C++ and undefined references
On Jan 13, 2010, at 00:57 , DNM wrote: - srilm.c // Initialize and read in the ngram model Ngram* bldLM(int order, const char* filename) { ... } ... // Delete the ngram model void deleteLM(Ngram* ngram) { delete srilm_vocab; delete ngram; } ... // Get the ngram probability of the given string, given n-gram order 'order' and string length // 'length'. float getSeqProb(Ngram* ngram, const char* ngramstr, unsigned order, unsigned length) { ...} - I think you need to `#include srilm.h' in the above, so C++ knows to export the functions with names callable from outside of C++. When you define a function in C++, the actual function symbol defined contains parameter type information unless previously declared in an extern C declaration.) While you've named the file with a .c extension, you have used C++-specific content (// comments, delete keyword) so I expect the file was compiled in C++ mode; otherwise it should have produced a syntax error from delete (// comments are a common enough extension that by themselves they probably work in much C code) and as a result the function symbols are mangled. If you add the #include, you bring the extern C declarations in scope, and C++ should produce non-mangled function definitions, which should be callable from Haskell. -- brandon s. allbery [solaris,freebsd,perl,pugs,haskell] allb...@kf8nh.com system administrator [openafs,heimdal,too many hats] allb...@ece.cmu.edu electrical and computer engineering, carnegie mellon universityKF8NH PGP.sig Description: This is a digitally signed message part ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe