comp.lang.ada
 help / color / mirror / Atom feed
From: resander <kresander@gmail.com>
Subject: Re: How to access this package written in C?
Date: Fri, 23 Apr 2010 05:58:05 -0700 (PDT)
Date: 2010-04-23T05:58:05-07:00	[thread overview]
Message-ID: <e98bcf01-46cc-44dd-b57b-3cc7e273d9e2@j21g2000yqh.googlegroups.com> (raw)
In-Reply-To: lnd3xrqji8.fsf@nuthaus.mib.org

On Apr 22, 10:12 pm, Keith Thompson <ks...@mib.org> wrote:
> resander <kresan...@gmail.com> writes:
> > I am working on software that manipulates SQL databases via a GUI. It
> > is written in C or C++ without classes and compiled on Linux. Would
> > also want it to run on Windows eventually. This software has
> > essentially one entry procedure:
>
> >   int guidb ( int appno , int recaddress );  // in C
>
> > which returns an outcome as an int, takes an int appno which specifies
> > application and an address of a record in recaddress. The latter is
> > used for passing the memory address of any recordtype variable and is
> > cast to a byte address inside guidb.
>
> [...]
>
> As others have mentioned, this is bad C.
>
> There is no guarantee that an int can hold the value of an address,
> and there are common systems (including Linux systems) where it
> can't.  Worse, you're not likely to get a warning if you convert
> a pointer to int, even if there's a loss of information.
>
> The right type for this parameter is void* (which is roughly
> analogous to Ada's System.Address).
>
> --
> Keith Thompson (The_Other_Keith) ks...@mib.org  <http://www.ghoti.net/~kst>
> Nokia
> "We must do something.  This is something.  Therefore, we must do this."
>     -- Antony Jay and Jonathan Lynn, "Yes Minister"




Thank you all for your concerns about using an int for passing an
address. The interface actually uses a void * (could also be char * as
that is what is needed), but I changed it for the post because I
thought an all-int interface would be easier to handle at the Ada-to-C
boundary. That seems to have backfired!

It may help if I give some background info, so just briefly the
program (with guidb as the main entry routine) moves record data to/
from GUI dialogs and to and from SQL databases via ODBC. A record in
host language may be passed in or in-and-out. The guidb is not
compiled with host language units and would exist as a dll, shared
object or a static library. It uses a record memory address, record
length and field offsets and field types/length in order to access a
record and move the record around. This information is held in tables
local to guidb. The record length and field data are passed accross
via another entry point:

 void givefldinfo ( int recordtypeid ,  -- key
                    int recordlength ,
                    int numflds ,
                    int fldoffsets[] ,
                    int typeinfo[] );

The givefldinfo is called for each record type by initialisation
routines that are generated automatically from design-time or
repository information. They are compiled and linked with the host
application and called behind the scenes.

Usually GUI events are handled internally, but may also be handled by
event procedures in the host language. Host language handlers have
signatures ( bool valin ),( int valin ), ( char valin[] ) and
( RECORDTP * valinout ). There are four additional entry points, one
for each event handler signature to get the proc address across from
host language. These are called in a manner similar to givefldinfo.

I am on Linux and installed Ada GPS yesterday. Experimented a bit and
found that X.fld'Position gave me the field offsets and X'Size the
record size. I also tried getting the address of a record and its
fields using X'Address and X.fld'Address, but they all came out
negative.

Prodrecord address: -1079352648
 code field address: -1079352648
 bcode field address: -1079352644
 ccode field address: -1079352643
 third field address: -1079352640
 descr field address: -1079352636
 price field address: -1079352624

for record
   code : integer; bcode : character;
   ccode : character; third : integer;
   descr : String(1..10); price : float;
by:
 prod : PRODUCT;
 a: System.Address;
   function Conv is new Ada.Unchecked_Conversion (
                     Source => System.Address,
                     Target => Integer);
  ...
  a := prod'Address;
  put( "Prodrecord address: " );
  s := conv ( a ) ;
  put(s);
  new_line;

  a := prod.code'Address;
  put( " code field address: " );
  s := conv ( a ) ;
  put(s);
  new_lin
  ...
Q1.
Addresses are not negative. How do I output a System.Address?


Dmitri:
Many thanks for showing how to code the generic Get routine. I have
never used generics or interfaced to C before and it was so long time
ago I used Ada (where is my walking stick?) so I don't understand it
well enough.

Q2.
What is the effect of aliased in 'Data : aliased Data_Type;'?

Data is a local variable. I am confused by the aliased keyword, but it
would seem guidb copies the record into this and then the record value
is copied once more into final location (X:Product). If so, one copy
operation is redundant.

Q3.
The wrapper:
procedure getprod (p:out PRODUCT;res:out int) is
begin
   result = guidb ( 0 , addrin(p)??? ) ;
end

hides the details of calling the C function and returns data to the
record variable in the calling program if the address carried by the
formal parameter can be obtained inside the wrapper. Using p'Address
for the second actual parameter of guidb would probably just give the
address of the formal (will check when I know how to output a
System.Address).
Is it possible to obtain the memory address of the record variable via
formal parameter p?

Q4.
Would it be easier to implement this if the wrapper was changed to:

procedure getprod (p: in System.Address; res:out int) is
begin
   result = guidb ( 0 , what goes here??? ) ;
end

with user calling it as:

  getprod ( recordvar'Address , result );


Q5.
Host language event handler procedures are stored as an array of
procedure addresses which is local to guidb. A procedure is called
indirectly via this array. This was designed for C/C++, but it would
be nice to use the same or similar mechanism for Ada.
Is this going to be possible?


I think interfacing to Ada can be done, but my knowledge about this is
still very limited. Your help would be most appreciated.

Regards
Ken




  reply	other threads:[~2010-04-23 12:58 UTC|newest]

Thread overview: 19+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2010-04-21 16:43 How to access this package written in C? resander
2010-04-21 17:39 ` Dmitry A. Kazakov
2010-04-22 20:12 ` Björn Persson
2010-04-22 21:12 ` Keith Thompson
2010-04-23 12:58   ` resander [this message]
2010-04-23 14:15     ` Dmitry A. Kazakov
2010-04-23 14:44     ` John B. Matthews
2010-04-23 15:39       ` John B. Matthews
2010-04-26 18:16     ` Robert A Duff
2010-04-26 19:57       ` Keith Thompson
2010-04-26 21:20         ` Maciej Sobczak
2010-04-27  6:52           ` Alex R. Mosteo
2010-04-27 22:29             ` Randy Brukardt
2010-05-03  8:12               ` Alex R. Mosteo
2010-04-27  0:20         ` Robert A Duff
2010-04-27  1:01           ` Keith Thompson
2010-04-27 16:07             ` Robert A Duff
2010-04-27 22:29               ` Randy Brukardt
2010-04-27  1:31           ` Randy Brukardt
replies disabled

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