* Help with PLplot bindings: How to pass a record of function pointers to a procedure
@ 2016-04-13 10:01 Jerry
2016-04-13 16:43 ` Jeffrey R. Carter
0 siblings, 1 reply; 3+ messages in thread
From: Jerry @ 2016-04-13 10:01 UTC (permalink / 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
^ permalink raw reply [flat|nested] 3+ messages in thread
* Re: Help with PLplot bindings: How to pass a record of function pointers to a procedure
2016-04-13 10:01 Help with PLplot bindings: How to pass a record of function pointers to a procedure Jerry
@ 2016-04-13 16:43 ` Jeffrey R. Carter
2016-04-15 8:08 ` Jerry
0 siblings, 1 reply; 3+ messages in thread
From: Jeffrey R. Carter @ 2016-04-13 16:43 UTC (permalink / raw)
On 04/13/2016 03:01 AM, Jerry wrote:
>
> 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;
>
> 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));
Only addressing this part, type PLf2ops_Type has 2 components, both of which are
of access types. A value (aggregate) of this type must therefore contain 2
access values. I suspect you want
S_Plf2ops_C : Plf2ops_Type :=
(Get => Plf2ops_C_Get'Access, Set => Plf2ops_C_Set'Access);
Depending on what you're doing with them, you might want the access types and
the record type declared Convention C.
--
Jeff Carter
"Violence is the last refuge of the incompetent."
Foundation
151
^ permalink raw reply [flat|nested] 3+ messages in thread
* Re: Help with PLplot bindings: How to pass a record of function pointers to a procedure
2016-04-13 16:43 ` Jeffrey R. Carter
@ 2016-04-15 8:08 ` Jerry
0 siblings, 0 replies; 3+ messages in thread
From: Jerry @ 2016-04-15 8:08 UTC (permalink / raw)
On Wednesday, April 13, 2016 at 9:43:58 AM UTC-7, Jeffrey R. Carter wrote:
<snip>
> Only addressing this part, type PLf2ops_Type has 2 components, both of which are
> of access types. A value (aggregate) of this type must therefore contain 2
> access values. I suspect you want
>
> S_Plf2ops_C : Plf2ops_Type :=
> (Get => Plf2ops_C_Get'Access, Set => Plf2ops_C_Set'Access);
>
> Depending on what you're doing with them, you might want the access types and
> the record type declared Convention C.
>
> --
> Jeff Carter
> "Violence is the last refuge of the incompetent."
> Foundation
> 151
Many thanks, Jeff. You are correct on both counts.
Jerry
^ permalink raw reply [flat|nested] 3+ messages in thread
end of thread, other threads:[~2016-04-15 8:08 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-04-13 10:01 Help with PLplot bindings: How to pass a record of function pointers to a procedure Jerry
2016-04-13 16:43 ` Jeffrey R. Carter
2016-04-15 8:08 ` Jerry
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox