I have been working on an Ada project and need to interface with a C library (fftw3). I used the command
gcc -c -fdump-ada-spec -C /usr/local/include/fftw3.h
to generate a preliminary binding (some tweaking required). I was able to get my code and the fftw3_h.ads to compile in gnat. However, the program crashes with
raised STORAGE_ERROR : fftw3_h.ads:733 object too large
When I run it through gdb, the code is crashing on a line that defines a version string,
fftw_version : aliased char_array (size_t); -- /usr/local/include/fftw3.h:457
pragma Import (C, fftw_version, "fftw_version");
My understanding of this is that Ada is trying to allocate space for the entire string all at once and is basing the storage space on the range of size_t. However, size_t in this case comes from interfaces.c.size_t which is defined as
type size_t is mod 2 ** System.Parameters.ptr_bits;
in i-c.ads while for C, size_t is defined as unsigned long in stddef.h. I am not sure how big 2**ptr_bits is, but I don't see any reason why the definition of size_t in i-c.ads should be expected to be limited to the size of C's unsigned long. If it is longer than C's unsigned long, then I suspect that the code is trying to create an array that uses more memory than I have. I have tried to just use interfaces.c.unsigned_long instead of size_t, but Ada does not like the type mismatch (which I should have know).
At this point, I have two questions. Firstly, is my understanding of the problem close (this is my first experience with interfacing to between Ada and C).
Secondly, assuming my understanding is correct, is there a way around the problem or do I need to take a completely different approach?
Thank you everybody. Simon's answer really helped. One problem is that fftw_version[] is set in the C code for fftw, not by me, and I cannot guarantee that the procedure will be called before something in the fftw library needs it (fftw3_h.ads is elaborated before any of my code). I also found an old FFTW_Ada binding online from 2004 by Stephen J. Sangwine. While I could not get his code to work, I combined how he dealt with the version string with Simon's suggestion and created a function that returns the string when needed by something else in the fftw library.
function FFTW_Version return String is
tmp_version : aliased char_array(size_t) ;
pragma Import(C, tmp_version, "fftw_version");
begin
return To_Ada(tmp_version, Trim_Nul => True) ;
end FFTW_Version;
This gives me something that produces the string when needed, but does not make assumptions about the size of the string (which the FFTW_Ada code did). This compiles and works nicely.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With