From: "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de>
Subject: Re: How to access this package written in C?
Date: Fri, 23 Apr 2010 16:15:31 +0200
Date: 2010-04-23T16:15:31+02:00 [thread overview]
Message-ID: <5h5csoxoxqv7.1i6yifddkcfhi$.dlg@40tude.net> (raw)
In-Reply-To: e98bcf01-46cc-44dd-b57b-3cc7e273d9e2@j21g2000yqh.googlegroups.com
On Fri, 23 Apr 2010 05:58:05 -0700 (PDT), resander wrote:
> 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.
There is GNADE ODBC, Ada bindings to ODBC. So you can drop C/C++
altogether.
> 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.
Never use Unchecked_Conversion unless you exactly know what you are
doing... Address is modular, when bit-wise converted to a *signed* integer
the result is expectedly surprising.
> How do I output a System.Address?
The example above in legal Ada:
with Ada.Text_IO; use Ada.Text_IO;
with System.Storage_Elements; use System.Storage_Elements;
with Interfaces.C; use Interfaces.C;
procedure Test_Fields is
type Product is record
Code : int; -- Use only C-compatible types when you communicate
Bcode : char; -- to C
Ccode : char;
Third : int;
Descr : char_array (1..10);
Price : c_float;
end record;
pragma Convention (C, Product);
P : aliased Product;
begin
Put_Line ("P'Address:" & Integer_Address'Image (To_Integer
(P'Address)));
Put_Line ("P.Code'Address:" & Integer_Address'Image (To_Integer
(P.Code'Address)));
Put_Line ("P.Descr'Address:" & Integer_Address'Image (To_Integer
(P.Descr'Address)));
end Test_Fields;
gives:
P'Address: 38207168
P.Code'Address: 38207168
P.Descr'Address: 38207180
> 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.
Ada generic is roughly what C++ calls template.
> 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.
"aliased" means "dear compiler, I plan to take pointers (access type) to
this thing." The compiler will reject Data'Access otherwise, because
without your hint it is free to allocate it in a way that Data would have
no valid machine address at all.
> 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?
In general case no, because see above. However if you declare PRODUCT a
"limited type" it will be passed by reference. You also [worse] can
procedure getprod (p: access PRODUCT; ...);
BTW, your concern about copying records is absolutely ungrounded.
Especially because you are using ODBC + a relational DBMS! These are so
extraordinary slow, that you will note no difference even if you did
hundreds of copies.
> 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 );
The preferences are as follows:
in out >> access >>>>>>>>>>> address
> 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?
Yes, it is possible, you can have an array of access-to-procedure type. But
an OO way is preferable.
--
Regards,
Dmitry A. Kazakov
http://www.dmitry-kazakov.de
next prev parent reply other threads:[~2010-04-23 14:15 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
2010-04-23 14:15 ` Dmitry A. Kazakov [this message]
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