From mboxrd@z Thu Jan 1 00:00:00 1970 X-Spam-Checker-Version: SpamAssassin 3.4.4 (2020-01-24) on polar.synack.me X-Spam-Level: X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00,FREEMAIL_FROM autolearn=unavailable autolearn_force=no version=3.4.4 X-Received: by 10.224.29.76 with SMTP id p12mr25216631qac.5.1372677116019; Mon, 01 Jul 2013 04:11:56 -0700 (PDT) X-Received: by 10.49.30.105 with SMTP id r9mr648641qeh.4.1372677116004; Mon, 01 Jul 2013 04:11:56 -0700 (PDT) Path: eternal-september.org!reader01.eternal-september.org!reader02.eternal-september.org!news.eternal-september.org!news.eternal-september.org!mx05.eternal-september.org!feeder.eternal-september.org!de-l.enfer-du-nord.net!feeder1.enfer-du-nord.net!news.glorb.com!j2no3158223qak.0!news-out.google.com!f7ni121qai.0!nntp.google.com!j2no3158215qak.0!postnews.google.com!glegroupsg2000goo.googlegroups.com!not-for-mail Newsgroups: comp.lang.ada Date: Mon, 1 Jul 2013 04:11:55 -0700 (PDT) In-Reply-To: <1fxsf70zl2ckq.aysy7d9c8jkl$.dlg@40tude.net> Complaints-To: groups-abuse@google.com Injection-Info: glegroupsg2000goo.googlegroups.com; posting-host=155.253.16.227; posting-account=uPViEgkAAACC04vaTYL5Kyk76brV1MA_ NNTP-Posting-Host: 155.253.16.227 References: <1fxsf70zl2ckq.aysy7d9c8jkl$.dlg@40tude.net> User-Agent: G2/1.0 MIME-Version: 1.0 Message-ID: <40bf5a31-b09a-4106-a57a-7ac3dd5f951e@googlegroups.com> Subject: Re: Thick bindings to a C library and gnattest: suggestions? From: Maurizio Tomasi Injection-Date: Mon, 01 Jul 2013 11:11:56 +0000 Content-Type: text/plain; charset=ISO-8859-1 Content-Transfer-Encoding: quoted-printable Xref: news.eternal-september.org comp.lang.ada:16004 Date: 2013-07-01T04:11:55-07:00 List-Id: Hi Dmitry, Many thanks for your suggestions. You gave me a lot of things to think ab= out. I have a few questions about what you wrote. > > First question: the vectors used by the CFITSIO library are sometimes > > huge (millions of elements), sometimes very small (~ 10 elements). > > I decided to always allocate them on the heap, using declarations like > > these: >=20 > Why should bindings care about that? Shouldn't they care? Perhaps I am missing something regarding the Ada langu= age, in fact C++ does not care about whether an array is allocated on the s= tack or on the heap. But if I declare a function like the following: function Read_Double_Array_From_FITS (File_Name : String) return Double_Arr= ay; and I implement it in the following way: -- Call the C functions that returns the number of rows in the file Num_Of_Elements :=3D Get_Number_Of_Elements(FITS_File); declare Vector_To_Return : Double_Array (1 .. Num_Of_Elements); begin -- Call the C function that fills Vector_To_Return ... return Vector_To_Return; end; then every time I read some huge array I will get a STORAGE_ERROR near the = declaration of "Vector_To_Return". This is the reason why I declared the re= turn type of "Read_Data_From_FITS" as a Double_Array_Ptr instead of a Doubl= e_Array, and implemented it as: Num_Of_Elements :=3D Get_Number_Of_Elements(FITS_File); declare Vector_To_Return : Double_Array_Ptr; begin Vector_To_Return :=3D new Double_Array (1 .. Num_Of_Elements); -- Call the C function that fills Vector_To_Return ... return Vector_To_Return; end; Your answer makes me think there is a smarter way of avoiding the distincti= on between Double_Array_Ptr and Double_Array. (This would in fact make Ada = much more like C++, where this distinction does not exist.) Is this the rea= son why in your example you declared Double_Array an array of *aliased* dou= bles? Or was your point just to use the address of its first member? > Using unconstrained arrays could be troublesome because they contain > bounds. You may consider the package B.3.2 >=20 > Interfaces.C.Pointers >=20 > But normally you do not need array pointers in bindings except for the > cases when the C library stores the pointer to keep it after returning fr= om > the subprogram. I need the C library only in those cases where I need to save/retrieve arra= ys of data from disk in binary format. But 100% of the calculations on the = values stored in these arrays will be done using Ada code (e.g., loops...).= The point of rewriting my C++ program in Ada is because my codes need to w= ork with very large arrays (I am part of a large astrophysics project), and= I find Ada arrays much more appealing than C++ vectors. The fact that Ada = arrays can have arbitrary bounds whom they carry is one of the things that = made me interested towards Ada at the beginning. Why did you say this might= be "troublesome"? Given this context, is your suggestion of using Interfaces.C.Pointers still= valid? > Why don't you simply pass the array down to the C subprogram? You can do > something like: >=20 > type Double_Array is array (Positive range <>) > of aliased Interfaces.C.double; > pragma Convention (C, Double_Array); > procedure Foo (A : Double_Array); >=20 > Implementation: >=20 > type Double_Ptr is access all Interfaces.C.double; > pragma Convention (C, Double_Ptr); >=20 > procedure Foo (A : Double_Array) is > -- > -- Assuming foo's signature in C: > -- > -- foo (double * a, unsigned n); > -- > procedure Internal (A : Double_Ptr; N : Interfaces.C.unsigned); > pragma Import (C, Internal, "foo"); > begin > Internal (A (A'First)'Access, A'Length); > end Foo; But what if A'Length is so large that the array does not fit into the stack= ? Increasing the stack to a good value would be better than allocating obje= cts on the heap? I would have problems in determining what size to use, as = my code should work on a variety of systems (my laptop, supercomputing faci= lities...) and the amount of data it needs to load depends on the context. > > I am sure there is some clever way to solve these two minor points, > > but so far I have not been able to find it. I tried e.g. to put > > "-lcfitsio" in the project file of the AdaFITS library, but with no > > success. >=20 > Make a library project file for cfitsio instead. "with" it from your > project. GNAT knows how to handle it and will add appropriate linker > switches to any project using it directly or indirectly. A library projec= t > file could look like: >=20 > project cfitsio is > for Externally_Built use "true"; -- Do not bother to compile me > for Source_Files use (); -- No sources > for Library_Dir use "."; -- Where .llb, .a, .dll, .so are > for Library_Name use "cfitsio"; -- Without "lib" prefix! > for Library_Kind use "dynamic"; -- A DLL > end cfitsio; This is really a good idea, I did not think about this! There are only two = problems with this approach: 1. The CFITSIO library is often compiled using ad-hoc flags in supercomputi= ng facilities, in order to make it work better with the storage systems. I = need to use the library provided by the system, not my own. But... 2. ...the system library is not always available as a dynamic .so file: in = some cases I must statically link CFITSIO (the libcfitsio.so library is not= available on every node of the cluster: when I discovered this, the system= admin told me to link statically). Is there no other option? I searched the "gnattest" documentation for some = way to prevent it from overwriting some parts of the files, but with no suc= cess. Again, many thanks for your answers. Maurizio.