comp.lang.ada
 help / color / mirror / Atom feed
From: Jerry <lanceboyle@qwest.net>
Subject: Help with PLplot bindings: How to pass a record of function pointers to a procedure
Date: Wed, 13 Apr 2016 03:01:44 -0700 (PDT)
Date: 2016-04-13T03:01:44-07:00	[thread overview]
Message-ID: <bce29636-6148-4efa-a6d6-ca683e8cb74f@googlegroups.com> (raw)

Sorry for the long messy post.

I'm trying to update the Ada bindings for the PLplot plotter software (http://plplot.sourceforge.net/) and am stumped.

Background: The C version has added support for the 3D plotters for z = f(x, y) data where z can be stored in various ways--the usual pointer to an array of pointers, a struct with the same thing but adding the bounds as additional struct fields, or as a one-dimensional row-major or column-major arrays. One function call to the C 3D surface plotter works for all kinds of z storage.

The C code has these declarations (I have edited out additional fields for simplicity; PLFLT maps to Ada Long_Float and PLINT maps to Integer, PLPointer is a C pointer to the z data, here called p):

typedef struct
{
    PLFLT ( *get )( PLPointer p, PLINT ix, PLINT iy );
    PLFLT ( *set )( PLPointer p, PLINT ix, PLINT iy, PLFLT z );
} plf2ops_t;

typedef plf2ops_t * PLF2OPS;

I understand the struct to have fields that are pointers to get and set functions.

Then there is, for the case where z is stored as a pointer to an array of pointers (these declarations etc. are in multiple files),

static PLFLT
plf2ops_c_get( PLPointer p, PLINT ix, PLINT iy )
{
    return ( (PLFLT **) p )[ix][iy];
}

static PLFLT
plf2ops_c_set( PLPointer p, PLINT ix, PLINT iy, PLFLT z )
{
    return ( ( (PLFLT **) p )[ix][iy] = z );
}

(These "get" and "set" functions are later offered in forms suitable for the other forms of z storage, e.g., struct-with-bounds, row-major, and column-major.)

Then there is this, for the pointer-to-pointers form of data manipulation described above:

static plf2ops_t s_plf2ops_c = {
    plf2ops_c_get,
    plf2ops_c_set,
};

which I understand to be a variable of the struct declared with the fields filled in with the appropriate functions.

Then:

PLF2OPS
plf2ops_c()
{
    return &s_plf2ops_c;
}

This is then used in the 3D surface plotter call as such:

plfsurf3d(x, y, plf2ops_c(), (PLPointer) z, XPTS, YPTS);

where x and y are arrays (pointers again) where z is evaluated, mathematically, z = f(x, y), and XPTS and YPTS are the sizes of x (XPTS), y (YPTS), z (YPTS by XPTS).

I have tried to emulate this in Ada in part as follows, but I'm doing something seriously wrong.

type Function_To_Manipulate_Matrix_A_Type is
    access function (p : Real_Matrix; ix, iy : Integer)
        return Long_Float;
type Function_To_Manipulate_Matrix_B_Type is
    access function (p : in out Real_Matrix; ix, iy : Integer; z : Long_Float)
        return Long_Float;

(Don't worry about my use of Real_Matrix here--I have a function to convert it to a pointer to an array of pointers to make C happy.)

type PLf2ops_Type is
    record
        Get    : Function_To_Manipulate_Matrix_A_Type;
        Set    : Function_To_Manipulate_Matrix_B_Type;
    end record;

function plf2ops_c_get(p : Real_Matrix; ix, iy : Integer) return Long_Float;
pragma Import(C, plf2ops_c_get, "plf2ops_c_get");

function plf2ops_c_set(p : Real_Matrix; ix, iy : Integer; z : Long_Float) return Long_Float;
pragma Import(C, plf2ops_c_set, "plf2ops_c_set");

s_plf2ops_c : PLf2ops_Type :=
   (Get => plf2ops_c_get(p : Real_Matrix; ix, iy : Integer),
    Set => plf2ops_c_set(p : Real_Matrix; ix, iy : Integer; z : Long_Float));

but this doesn't compile, nor do some variations that I have tried. How do I get this done so that I can pass a record of function pointers to plfsurf3d that is compatible with how C does it (and actually compiles in Ada)? Remember that the functions plf2ops_c_get and plf2ops_c_set have differently-named and -implemented counterparts for other z-storage methods, e.g.

plf2ops_grid_row_major_get( PLPointer p, PLINT ix, PLINT iy )
{
    PLfGrid2 *g = (PLfGrid2 *) p;
    return ( (PLFLT *) g->f )[ix * g->ny + iy];
}

then e.g.

plfsurf3d(x, y, plf2ops_grid_row_major(), ( PLPointer ) & grid_row_major, XPTS, YPTS);

Jerry


             reply	other threads:[~2016-04-13 10:01 UTC|newest]

Thread overview: 3+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2016-04-13 10:01 Jerry [this message]
2016-04-13 16:43 ` Help with PLplot bindings: How to pass a record of function pointers to a procedure Jeffrey R. Carter
2016-04-15  8:08   ` Jerry
replies disabled

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox