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 Path: eternal-september.org!reader01.eternal-september.org!reader02.eternal-september.org!news.eternal-september.org!news.eternal-september.org!feeder.eternal-september.org!news.unit0.net!fu-berlin.de!uni-berlin.de!individual.net!not-for-mail From: hreba Newsgroups: comp.lang.ada Subject: Re: Interfaces.C questions Date: Sun, 19 Mar 2017 13:17:35 +0100 Message-ID: References: <403f77a2-992e-45b1-8f5d-a97143783130@googlegroups.com> Mime-Version: 1.0 Content-Type: text/plain; charset=utf-8; format=flowed Content-Transfer-Encoding: 7bit X-Trace: individual.net 09CVsjd2kiG02S4VYViSiARo1AgJQNOnEduakAfakRFu3lSLVd Cancel-Lock: sha1:rjsKp7lEUDUFLlg1xd04gvAA8NQ= User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:45.0) Gecko/20100101 Thunderbird/45.5.1 In-Reply-To: <403f77a2-992e-45b1-8f5d-a97143783130@googlegroups.com> Xref: news.eternal-september.org comp.lang.ada:46424 Date: 2017-03-19T13:17:35+01:00 List-Id: On 03/19/2017 12:24 AM, Leo Brewin wrote: > Hi Frank, > > I'd be really interested to see a minimal working example once you've got it running. > I'd like to be able to use GSL in my own codes. > > Cheers, > Leo > Ok, below follows my first working example, numerical quadrature. Any critics is welcome. Some remarks: 'void * params' in C can be a pointer to just anything, a number, an array, a record. The best solution probably would be a generic package where the actual type is passed as parameter (see type Element in Interfaces.C.Pointers). The quadrature algorithm I chose makes no use of these parameters, so in my example I translate the type to 'access all Integer' and pass null as value. As I am beginning to build a numerics library, I will now - make the package generic, with 2 type parameters, one for the reals (digits <>) and one for the parameters (private), - write wrappers so that the client needs no Interfaces.C, and that he can pass a function of 'type Real_Function is access function (x: Real) return Real;' to the quadrature procedure instead of a record. So here comes my example. The interface package is (no body): ----------------------------------------------------------------------- with Interfaces.C; package GSL is package C renames Interfaces.C; type Void_Ptr is access all Integer; type GSL_Function_Ptr is access function (x: C.double; params: Void_Ptr) return C.double; type GSL_Function is record func: GSL_Function_Ptr; params: Void_Ptr; end record; function Integration_QNG (f: access GSL_Function; a, b, epsabs, epsrel: C.double; result, abserr: out C.double; neval: out C.size_t) return C.int; private pragma Import (C, Integration_QNG, "gsl_integration_qng"); pragma Convention (C, Void_Ptr); pragma Convention (C, GSL_Function_Ptr); pragma Convention (C, GSL_Function); end GSL; ----------------------------------------------------------------------------- The main subprogram (client) is ----------------------------------------------------------------------------- with Ada.Text_IO; use Ada.Text_IO; with GSL; with Integ_Aux; procedure Test_Integration is use type GSL.C.double; a: GSL.C.double; abserr: GSL.C.double; neval: GSL.C.size_t; res: GSL.C.int; gslf: aliased GSL.GSL_Function; begin gslf.func:= Integ_Aux.Circle'Access; gslf.params:= null; res:= GSL.Integration_QNG (gslf'Access, 0.0, 1.0, 0.001, 0.001, a, abserr, neval); Put_Line("4*int_0^1 sqrt(1-x^2) dx = " & GSL.C.double'Image(4.0*a)); Put_Line(GSL.C.size_t'Image(neval) & " function evaluations, " & GSL.C.double'Image(abserr) & " abs. error"); end Test_Integration; ------------------------------------------------------------------------------ Because an access is passed to the function to be integrated it has to be in a separated package: ------------------------------------------------------------------------------ with GSL; package Integ_Aux is function Circle (x: GSL.C.double; pars: GSL.Void_Ptr) return GSL.C.double; private pragma Convention (C, Circle); end Integ_Aux; ------------------------------------------------------------------------------- ------------------------------------------------------------------------------- with Ada.Numerics.Generic_Elementary_Functions; with GSL; package body Integ_Aux is package Functions is new Ada.Numerics.Generic_Elementary_Functions (GSL.C.double); function Circle (x: GSL.C.double; pars: GSL.Void_Ptr) return GSL.C.double is use type GSL.C.double; begin return Functions.Sqrt(abs(1.0-x*x)); end Circle; end Integ_Aux; -------------------------------------------------------------------------------- The project files of the interface package are -------------------------------------------------------------------------------- -- External library "Gnu Scientific Library" with "gslcblas"; Project GSL is type OS_Type is ("linux", "linux-gnu", "windows", "unknown"); act_os: OS_Type:= external ("OSTYPE"); -- act_os: OS_Type:= external ("OS_TYPE"); For externally_built use "true"; For library_dir use "/usr/lib"; case act_os is when "linux"|"linux-gnu" => for library_dir use "/usr/lib"; when "windows" => for library_dir use "/Lib/GSL"; when "unknown" => for Source_Dirs use ("/"); -- just anything end case; For library_name use "gsl"; For source_dirs use (); -- no sources. -- For library_kind use "static"; -- if it is a static lib .a for library_kind use "dynamic"; -- if it is an so. end GSL; ------------------------------------------------------------------------- ------------------------------------------------------------------------- -- External library "Gnu Scientific Library" Project GSLCBLAS is type OS_Type is ("linux", "linux-gnu", "windows", "unknown"); act_os: OS_Type:= external ("OSTYPE"); -- act_os: OS_Type:= external ("OS_TYPE"); For externally_built use "true"; case act_os is when "linux"|"linux-gnu" => for library_dir use "/usr/lib"; when "windows" => for library_dir use "/Lib/GSL"; when "unknown" => for Source_Dirs use ("/"); -- just anything end case; For library_name use "gslcblas"; For source_dirs use (); -- no sources. -- For library_kind use "static"; -- if it is a static lib .a for library_kind use "dynamic"; -- if it is an so. end GSLCBLAS; ----------------------------------------------------------------------------- I tried to make these projects platform independent (Linux and Windows so far); only tested on Linux so far. The environment variable OSTYPE must exist. If you don't want to do this, just type for library_dir use "/usr/lib"; instead of the 'case' construct (on Linux). Finally the project file for the main program: ----------------------------------------------------------------------------- with "../../gsl.gpr"; project Test_Integration is for Source_Dirs use (".", "../../src"); -- test and interface sources for Object_Dir use "../obj"; for Exec_Dir use "."; for Main use ("test_integration.adb"); package Compiler is for Default_Switches ("ada") use ("-g", "-gnatf", "-gnat2012"); end Compiler; package Linker is for Default_Switches ("ada") use ("-g"); end Linker; package Builder is for Default_Switches ("ada") use ("-g"); end Builder; end Test_Integration; ------------------------------------------------------------------------------ The result is an approximation of the unit circle area, pi. -- Frank Hrebabetzky +49 / 6355 / 989 5070