problems with FFI including h files
Hi all! I'm hoping someone with more FFI experience than me (pretty much anyone who's done anything with FFI) can help me out. Basically, I'm trying to include an h file and gcc is telling me that there are parse errors in it. However, when I write a c program that includes that h file, it don't get such errors. Here is an example C program: 12:52pm moussor:ATLAS/ cat TestAtlas.c #include "cblas.h" int main() { double x = cblas_ddot(0,0,0,0,0); } And, I can compile it: 1:39pm moussor:ATLAS/ /nfs/isd/hdaume/bin/gcc TestAtlas.c -B/nfs/isd/hdaume/download/ATLAS -L/nfs/isd/hdaume/download/ATLAS/lib/SunOS_SunUS2 -llapack -lcblas -lf77blas -latlas 1:39pm moussor:ATLAS/ ./a.out 1:39pm moussor:ATLAS/ The h file I'm including, "cblas.h" is located in /nfs/isd/hdaume/download/ATLAS/include and all the libraries are the the specified lib directory (though those aren't really relevant at this point). Moving on to the haskell side of things, I have a module: 1:37pm moussor:~/projects/ cat HBlas/Level1GC2.hs {-# OPTIONS -#include "cblas.h" #-} -- run with: module HBlas.Level1GC2 where 1:41pm moussor:~/projects/ that contains no definitions (obviously my real one has definitions, but it makes no difference at this point). so, i try to compile with ghc using: ghco HBlas/Level1GC2.hs -cpp -L/nfs/isd/hdaume/download/ATLAS/lib/SunOS_SunUS2 -llapack -lcblas -lf77blas -latlas -iHBlas -pgmc/nfs/isd/hdaume/bin/gcc -optc-B/nfs/isd/hdaume/download/ATLAS so, basically, i'm including the same -L and -B directives to gcc, using the same version of gcc (3.1), same libraries and everything but now it complains and says: Compiling HBlas.Level1GC2 ( HBlas/Level1GC2.hs, HBlas/Level1GC2.sun4.o ) In file included from /tmp/ghc3741.hc:7: /nfs/isd/hdaume/download/ATLAS/include/cblas.h:444: parse error before numeric constant /nfs/isd/hdaume/download/ATLAS/include/cblas.h:449: parse error before numeric constant /nfs/isd/hdaume/download/ATLAS/include/cblas.h:453: parse error before numeric constant /nfs/isd/hdaume/download/ATLAS/include/cblas.h:458: parse error before numeric constant /nfs/isd/hdaume/download/ATLAS/include/cblas.h:474: parse error before numeric constant /nfs/isd/hdaume/download/ATLAS/include/cblas.h:479: parse error before numeric constant /nfs/isd/hdaume/download/ATLAS/include/cblas.h:483: parse error before numeric constant /nfs/isd/hdaume/download/ATLAS/include/cblas.h:488: parse error before numeric constant /nfs/isd/hdaume/download/ATLAS/include/cblas.h:504: parse error before numeric constant /nfs/isd/hdaume/download/ATLAS/include/cblas.h:509: parse error before numeric constant /nfs/isd/hdaume/download/ATLAS/include/cblas.h:513: parse error before numeric constant /nfs/isd/hdaume/download/ATLAS/include/cblas.h:518: parse error before numeric constant /nfs/isd/hdaume/download/ATLAS/include/cblas.h:534: parse error before numeric constant /nfs/isd/hdaume/download/ATLAS/include/cblas.h:539: parse error before numeric constant /nfs/isd/hdaume/download/ATLAS/include/cblas.h:543: parse error before numeric constant /nfs/isd/hdaume/download/ATLAS/include/cblas.h:548: parse error before numeric constant /nfs/isd/hdaume/download/ATLAS/include/cblas.h:568: parse error before numeric constant /nfs/isd/hdaume/download/ATLAS/include/cblas.h:572: parse error before numeric constant /nfs/isd/hdaume/download/ATLAS/include/cblas.h:577: parse error before numeric constant /nfs/isd/hdaume/download/ATLAS/include/cblas.h:582: parse error before numeric constant /nfs/isd/hdaume/download/ATLAS/include/cblas.h:586: parse error before numeric constant /nfs/isd/hdaume/download/ATLAS/include/cblas.h:591: parse error before numeric constant if I look at cblas.h, line 444 is the last line of this definition: void cblas_sgemm(const enum CBLAS_ORDER Order, const enum CBLAS_TRANSPOSE TransA, const enum CBLAS_TRANSPOSE TransB, const int M, const int N, const int K, const float alpha, const float *A, const int lda, const float *B, const int ldb, const float beta, float *C, const int ldc); i really have *no* idea what's going on. if i compile the c and the haskell with -v, the lines leading up to the errors on the haskell side read: *** C Compiler /nfs/isd/hdaume/bin/gcc -x c /tmp/ghc3749.hc -o /tmp/ghc3749.raw_s -w -v -S -Wimplicit -O -D__GLASGOW_HASKELL__=502 -B/nfs/isd/hdaume/download/ATLAS -ffloat-store -I . -I /nfs/isd/hdaume/lib/ghc-5.02.3/include Reading specs from /nfs/isd/hdaume/lib/gcc-lib/sparc-sun-solaris2.8/3.1/specs Configured with: /nfs/isd/hdaume/download/gcc-3.1/configure --prefix=/nfs/isd/hdaume --with-cpu=ultrasparc --enable-languages=c,c++,f77,java Thread model: posix gcc version 3.1 /nfs/isd/hdaume/lib/gcc-lib/sparc-sun-solaris2.8/3.1/cc1 -lang-c -v -I . -I /nfs/isd/hdaume/lib/ghc-5.02.3/include -isystem /nfs/isd/hdaume/download/ATLAS/include -D__GNUC__=3 -D__GNUC_MINOR__=1 -D__GNUC_PATCHLEVEL__=0 -Dsparc -Dsun -Dunix -D__svr4__ -D__SVR4 -D__PRAGMA_REDEFINE_EXTNAME -D__sparc__ -D__sun__ -D__unix__ -D__svr4__ -D__SVR4 -D__PRAGMA_REDEFINE_EXTNAME -D__sparc -D__sun -D__unix -Asystem=unix -Asystem=svr4 -D__OPTIMIZE__ -D__STDC_HOSTED__=1 -D__SIZE_TYPE__=unsigned int -D__PTRDIFF_TYPE__=int -D__WCHAR_TYPE__=long int -D__WINT_TYPE__=long int -D__GCC_NEW_VARARGS__ -Acpu=sparc -Amachine=sparc -D__GLASGOW_HASKELL__=502 /tmp/ghc3749.hc -quiet -dumpbase ghc3749.hc -O -Wimplicit -w -version -ffloat-store -o /tmp/ghc3749.raw_s GNU CPP version 3.1 (cpplib) (sparc ELF) GNU C version 3.1 (sparc-sun-solaris2.8) compiled by GNU C version 2.95.2 19991024 (release). ignoring nonexistent directory "/nfs/isd/hdaume/sparc-sun-solaris2.8/include" #include "..." search starts here: #include <...> search starts here: . /nfs/isd/hdaume/lib/ghc-5.02.3/include /nfs/isd/hdaume/download/ATLAS/include /usr/local/include /nfs/isd/hdaume/include /nfs/isd/hdaume/lib/gcc-lib/sparc-sun-solaris2.8/3.1/include /usr/include End of search list. In file included from /tmp/ghc3749.hc:7: /nfs/isd/hdaume/download/ATLAS/include/cblas.h:444: parse error before numeric constant and the entire transcript of just compiling the c program with gcc is: 1:41pm moussor:ATLAS/ /nfs/isd/hdaume/bin/gcc TestAtlas.c -B/nfs/isd/hdaume/download/ATLAS -L/nfs/isd/hdaume/download/ATLAS/lib/SunOS_SunUS2 -llapack -lcblas -lf77blas -latlas -v Reading specs from /nfs/isd/hdaume/lib/gcc-lib/sparc-sun-solaris2.8/3.1/specs Configured with: /nfs/isd/hdaume/download/gcc-3.1/configure --prefix=/nfs/isd/hdaume --with-cpu=ultrasparc --enable-languages=c,c++,f77,java Thread model: posix gcc version 3.1 /nfs/isd/hdaume/lib/gcc-lib/sparc-sun-solaris2.8/3.1/cc1 -lang-c -v -isystem /nfs/isd/hdaume/download/ATLAS/include -D__GNUC__=3 -D__GNUC_MINOR__=1 -D__GNUC_PATCHLEVEL__=0 -Dsparc -Dsun -Dunix -D__svr4__ -D__SVR4 -D__PRAGMA_REDEFINE_EXTNAME -D__sparc__ -D__sun__ -D__unix__ -D__svr4__ -D__SVR4 -D__PRAGMA_REDEFINE_EXTNAME -D__sparc -D__sun -D__unix -Asystem=unix -Asystem=svr4 -D__NO_INLINE__ -D__STDC_HOSTED__=1 -D__SIZE_TYPE__=unsigned int -D__PTRDIFF_TYPE__=int -D__WCHAR_TYPE__=long int -D__WINT_TYPE__=long int -D__GCC_NEW_VARARGS__ -Acpu=sparc -Amachine=sparc TestAtlas.c -quiet -dumpbase TestAtlas.c -version -o /var/tmp//cc1I7kU6.s GNU CPP version 3.1 (cpplib) (sparc ELF) GNU C version 3.1 (sparc-sun-solaris2.8) compiled by GNU C version 2.95.2 19991024 (release). ignoring nonexistent directory "/nfs/isd/hdaume/sparc-sun-solaris2.8/include" #include "..." search starts here: #include <...> search starts here: /nfs/isd/hdaume/download/ATLAS/include /usr/local/include /nfs/isd/hdaume/include /nfs/isd/hdaume/lib/gcc-lib/sparc-sun-solaris2.8/3.1/include /usr/include End of search list. /usr/ccs/bin/as -V -Qy -s -xarch=v8plusa -o /var/tmp//cc1wEdD7.o /var/tmp//cc1I7kU6.s /usr/ccs/bin/as: Sun WorkShop 6 99/08/18 /nfs/isd/hdaume/lib/gcc-lib/sparc-sun-solaris2.8/3.1/collect2 -V -Y P,/usr/ccs/lib:/usr/lib -Qy /nfs/isd/hdaume/lib/gcc-lib/sparc-sun-solaris2.8/3.1/crt1.o /nfs/isd/hdaume/lib/gcc-lib/sparc-sun-solaris2.8/3.1/crti.o /usr/ccs/lib/values-Xa.o /nfs/isd/hdaume/lib/gcc-lib/sparc-sun-solaris2.8/3.1/crtbegin.o -L/nfs/isd/hdaume/download/ATLAS/lib/SunOS_SunUS2 -L/nfs/isd/hdaume/download/ATLAS -L/nfs/isd/hdaume/lib/gcc-lib/sparc-sun-solaris2.8/3.1 -L/usr/ccs/bin -L/usr/ccs/lib -L/nfs/isd/hdaume/lib/gcc-lib/sparc-sun-solaris2.8/3.1/../../.. /var/tmp//cc1wEdD7.o -llapack -lcblas -lf77blas -latlas -lgcc -lgcc_eh -lc -lgcc -lgcc_eh -lc /nfs/isd/hdaume/lib/gcc-lib/sparc-sun-solaris2.8/3.1/crtend.o /nfs/isd/hdaume/lib/gcc-lib/sparc-sun-solaris2.8/3.1/crtn.o ld: Software Generation Utilities - Solaris-ELF (4.0) so yeah, i'm completely at a loss here. i really don't know very much about gcc and why it would be doing this; i notice there are a few command line options passed to cc1 in the haskell version that don't exist on the c side. to make sure it wasn't a problem with the .hc extension, i renamed TestAtlas.c to TestAtlas.hc and compiled with "gcc -x c TestAtlas.hc ..." and the rest the same and it still works fine. please please please help :) thanks! - Hal -- Hal Daume III "Computer science is no more about computers | hdaume@isi.edu than astronomy is about telescopes." -Dijkstra | www.isi.edu/~hdaume
On Friday 31. May 2002 22:47, Hal Daume III wrote:
[...] /nfs/isd/hdaume/download/ATLAS/include/cblas.h:591: parse error before numeric constant
if I look at cblas.h, line 444 is the last line of this definition:
void cblas_sgemm(const enum CBLAS_ORDER Order, const enum CBLAS_TRANSPOSE TransA, const enum CBLAS_TRANSPOSE TransB, const int M, const int N, const int K, const float alpha, const float *A, const int lda, const float *B, const int ldb, const float beta, float *C, const int ldc);
Just a guess, GHC somewhere #define's beta to a numeric constant? Can you tell GHC to dump the preprocessed C code and see what the line in question becomes?
Well, I'm not sure exactly how to do this -- i can dump hspp and hc files from the haskell source, but I don't think from the h. *HOWEVER*, i modified cblas.h on line 444 because of your guess and found out that the problem wasn't with the beta, but with float *C. If I changed "C" to "bC", as in: void cblas_sgemm(const enum CBLAS_ORDER Order, const enum CBLAS_TRANSPOSE TransA, const enum CBLAS_TRANSPOSE TransB, const int M, const int N, const int K, const float alpha, const float *A, const int lda, const float *B, const int ldb, const float beta, float *bC, const int ldc); everything works (well, at least i no longer get an error on *that* line -- the other errors are still there). So it looks like you were right. How can I get ghc to *not* do this? :) -- Hal Daume III "Computer science is no more about computers | hdaume@isi.edu than astronomy is about telescopes." -Dijkstra | www.isi.edu/~hdaume On Fri, 31 May 2002, Sven Moritz Hallberg wrote:
On Friday 31. May 2002 22:47, Hal Daume III wrote:
[...] /nfs/isd/hdaume/download/ATLAS/include/cblas.h:591: parse error before numeric constant
if I look at cblas.h, line 444 is the last line of this definition:
void cblas_sgemm(const enum CBLAS_ORDER Order, const enum CBLAS_TRANSPOSE TransA, const enum CBLAS_TRANSPOSE TransB, const int M, const int N, const int K, const float alpha, const float *A, const int lda, const float *B, const int ldb, const float beta, float *C, const int ldc);
Just a guess, GHC somewhere #define's beta to a numeric constant? Can you tell GHC to dump the preprocessed C code and see what the line in question becomes?
_______________________________________________ Glasgow-haskell-users mailing list Glasgow-haskell-users@haskell.org http://www.haskell.org/mailman/listinfo/glasgow-haskell-users
On Friday 31. May 2002 23:15, Hal Daume III wrote:
Well, I'm not sure exactly how to do this -- i can dump hspp and hc files
from the haskell source, but I don't think from the h. *HOWEVER*, i
modified cblas.h on line 444 because of your guess and found out that the problem wasn't with the beta, but with float *C. If I changed "C" to "bC", as in:
void cblas_sgemm(const enum CBLAS_ORDER Order, const enum CBLAS_TRANSPOSE TransA, const enum CBLAS_TRANSPOSE TransB, const int M, const int N, const int K, const float alpha, const float *A, const int lda, const float *B, const int ldb, const float beta, float *bC, const int ldc);
everything works (well, at least i no longer get an error on *that* line -- the other errors are still there).
So it looks like you were right. How can I get ghc to *not* do this? :)
:) Oh, I don't know that, unfortunately, because I've never looked under the hood of GHC. But I've encountered quite a lot of errors in C source... and these kinds of things are the reason why everybody shamelessly (and quite reasonably) hates cpp. But a one-character (!) preprocessor macro #defined within a user-#included file is definately a bug. *wink* *wink* Greetings, Sven Moritz
So it looks like you were right. How can I get ghc to *not* do this? :)
Any time you take two large C programs/libraries and try to merge them, you're likely to run into preprocessor (or compiler) related errors like those you describe. How many libraries provide something like the following: #define TRUE 1 #define proto(x) x etc.? I don't use GHC's ffi often enough to know the exact fix but things to try are: 1) If using Greencard, use the ffi target instead of the ghc target. Both ought to work but the ffi target hopefully doesn't involve so much of GHC's header files. 2) Write a thin veneer over the library with its own header file. Take care that the header file _does not_ pull in anything other than standard header files (i.e., what GHC already pulls in). Since you control the header file, you can resolve all conflicts yourself. 3) Submit bug reports to ghc team. Probably requires you to grok the ghc header files well enough that you can submit decent quality reports. There ought to be a way to tell ghc to tell gcc to generate dependency files (as used by many Make systems) and/or to keep the preprocessor output (-i on gcc I think) - so you could see just where everything comes from. -- Alastair Reid reid@cs.utah.edu http://www.cs.utah.edu/~reid/
Alastair Reid wrote:
Any time you take two large C programs/libraries and try to merge them, you're likely to run into preprocessor (or compiler) related errors like those you describe. [...]
Sad, but very true! And GHC's headers are not very nice in this respect: panne@jeanluc:~> grep '#define [^ \t][^ \t] ' /usr/lib/ghc-5.03/include/* /usr/lib/ghc-5.03/include/PrimOps.h:#define C 0 /usr/lib/ghc-5.03/include/PrimOps.h:#define R 1 /usr/lib/ghc-5.03/include/PrimOps.h:#define C 1 /usr/lib/ghc-5.03/include/PrimOps.h:#define R 0 panne@jeanluc:~> grep '#define [^ \t][^ \t] ' /usr/lib/ghc-5.03/include/* /usr/lib/ghc-5.03/include/Regs.h:#define R1 (BaseReg->rR1) /usr/lib/ghc-5.03/include/Regs.h:#define R2 (BaseReg->rR2) /usr/lib/ghc-5.03/include/Regs.h:#define F1 (BaseReg->rF1) /usr/lib/ghc-5.03/include/Regs.h:#define F2 (BaseReg->rF2) /usr/lib/ghc-5.03/include/Regs.h:#define F3 (BaseReg->rF3) /usr/lib/ghc-5.03/include/Regs.h:#define F4 (BaseReg->rF4) /usr/lib/ghc-5.03/include/Regs.h:#define D1 (BaseReg->rD1) /usr/lib/ghc-5.03/include/Regs.h:#define D2 (BaseReg->rD2) /usr/lib/ghc-5.03/include/Regs.h:#define L1 (BaseReg->rL1) /usr/lib/ghc-5.03/include/Regs.h:#define Sp (BaseReg->rSp) /usr/lib/ghc-5.03/include/Regs.h:#define Su (BaseReg->rSu) /usr/lib/ghc-5.03/include/Regs.h:#define Hp (BaseReg->rHp) And so on... SimonM: What about a "poor man's" namespace, i.e. prefixing every macro, type, etc. with "GHC"/"ghc"? OpenGL, GLUT, GTK, etc. do a similar thing, and although it's a primitive measure, it's very effective. Cheers, S.
On Saturday 01. June 2002 12:43, Sven Panne wrote:
Alastair Reid wrote:
Any time you take two large C programs/libraries and try to merge them, you're likely to run into preprocessor (or compiler) related errors like those you describe. [...]
Sad, but very true! And GHC's headers are not very nice in this respect:
panne@jeanluc:~> grep '#define [^ \t][^ \t] ' /usr/lib/ghc-5.03/include/* /usr/lib/ghc-5.03/include/PrimOps.h:#define C 0 /usr/lib/ghc-5.03/include/PrimOps.h:#define R 1 /usr/lib/ghc-5.03/include/PrimOps.h:#define C 1 /usr/lib/ghc-5.03/include/PrimOps.h:#define R 0
*gulp*
SimonM: What about a "poor man's" namespace, i.e. prefixing every macro, type, etc. with "GHC"/"ghc"? OpenGL, GLUT, GTK, etc. do a similar thing, and although it's a primitive measure, it's very effective.
Are these macros of interest outside the GHC headers themselves? If not, they should be #undef'ed as early as possible. Regards, Sven Moritz
participants (4)
-
Alastair Reid -
Hal Daume III -
Sven Moritz Hallberg -
Sven Panne