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=-0.9 required=5.0 tests=BAYES_00,FORGED_GMAIL_RCVD, FREEMAIL_FROM autolearn=no autolearn_force=no version=3.4.4 X-Google-Thread: 103376,74bc23dcb20218db X-Google-NewGroupId: yes X-Google-Attributes: gida07f3367d7,domainid0,public,usenet X-Google-Language: ENGLISH,ASCII Path: g2news1.google.com!news2.google.com!postnews.google.com!j21g2000yqh.googlegroups.com!not-for-mail From: resander Newsgroups: comp.lang.ada Subject: Re: How to access this package written in C? Date: Fri, 23 Apr 2010 05:58:05 -0700 (PDT) Organization: http://groups.google.com Message-ID: References: <4e9d2aaf-c0a6-4798-b838-8f5b7c4a39d1@k33g2000yqc.googlegroups.com> NNTP-Posting-Host: 82.5.106.54 Mime-Version: 1.0 Content-Type: text/plain; charset=ISO-8859-1 Content-Transfer-Encoding: quoted-printable X-Trace: posting.google.com 1272027486 20168 127.0.0.1 (23 Apr 2010 12:58:06 GMT) X-Complaints-To: groups-abuse@google.com NNTP-Posting-Date: Fri, 23 Apr 2010 12:58:06 +0000 (UTC) Complaints-To: groups-abuse@google.com Injection-Info: j21g2000yqh.googlegroups.com; posting-host=82.5.106.54; posting-account=5kIDUAkAAACEMLy16tM5OtzZtznE-9-5 User-Agent: G2/1.0 X-HTTP-UserAgent: Mozilla/5.0 (X11; U; Linux i686; en-GB; rv:1.9.0.19) Gecko/2010040118 Ubuntu/8.10 (intrepid) Firefox/3.0.19,gzip(gfe) Xref: g2news1.google.com comp.lang.ada:10153 Date: 2010-04-23T05:58:05-07:00 List-Id: On Apr 22, 10:12=A0pm, Keith Thompson wrote: > resander 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: > > > =A0 int guidb ( int appno , int recaddress ); =A0// 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. =A0Worse, 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 =A0 > Nokia > "We must do something. =A0This is something. =A0Therefore, we must do thi= s." > =A0 =A0 -- 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 =3D> System.Address, Target =3D> Integer); ... a :=3D prod'Address; put( "Prodrecord address: " ); s :=3D conv ( a ) ; put(s); new_line; a :=3D prod.code'Address; put( " code field address: " ); s :=3D 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 =3D 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 =3D 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