* How to access this package written in C? @ 2010-04-21 16:43 resander 2010-04-21 17:39 ` Dmitry A. Kazakov ` (2 more replies) 0 siblings, 3 replies; 19+ messages in thread From: resander @ 2010-04-21 16:43 UTC (permalink / raw) 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. guidb uses appno to locate field-offsets and length of the recordtype in tables built by initialisation functions for all recordtypes that take part. Typical use in C/C++: typedef struct { int prodcode; float price; char descr [50]... } PRODUCT; typedef struct { bool bitesyou; int speciescode; char name[20] ... } ANIMAL ; void getproduct ( PRODUCT * pout , int * resultout ) { *resultout = guidb ( 0 , (int)pout ) ; } void addtozoo ( ANIMAL * a , int * resultout ) { *resultout = guidb ( 1 , (int)a ) ; } PRODUCT prod ; ANIMAL addthis ; int outcome ; // use as... getproduct ( &prod , &outcome ); // get addthis animal data then addtozoo ( &addthis , &outcome ); All wrappers like getproduct and addtozoo are automatically generated from other specs. That is easy in C by using fldoffset macro to get field offsets and sizeof(rectypename) to get record length and a cast that changes the interpretation of address to an int. Desired use in Ada (same as above): type PRODUCT is RECORD int prodcode; float price; char descr [50]...END RECORD; procedure getproduct ( p : out PRODUCT ; result : out int ) is begin result = guidb ( 0 , address_of(p) how ??? ) ; end prod : PRODUCT; outcome : int ; getproduct ( prod , outcome ); To be able to use the guidb with Ada I need to know how to: - get the memory address carried (how?) by the record formal parameter - obtain field offsets for a record type - obtain length of a record object/variable How to do this in in Ada? If it cannot be done, can the interface above be changed to make it possible? Ken ^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: How to access this package written in C? 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 2 siblings, 0 replies; 19+ messages in thread From: Dmitry A. Kazakov @ 2010-04-21 17:39 UTC (permalink / raw) On Wed, 21 Apr 2010 09:43:02 -0700 (PDT), resander wrote: > 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 This is awful even on C standards. > 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. [...] > Desired use in Ada (same as above): > > type PRODUCT is RECORD int prodcode; float price; char descr > [50]...END RECORD; > > procedure getproduct ( p : out PRODUCT ; result : out int ) is > begin > result = guidb ( 0 , address_of(p) how ??? ) ; > end > > prod : PRODUCT; > outcome : int ; [...] > How to do this in in Ada? If it cannot be done, can the interface > above be changed to make it possible? Make it a generic function: SQL_Error : exception; generic type Data_Type is private; function Generic_Get (No : Integer) return Data_Type; The implementation of: with Ada.Exceptions; use Ada.Exceptions; with Interfaces.C; use Interfaces.C; function Generic_Get (No : Integer) return Data_Type is function Internal (No : int; Data : access Data_Type) return int; pragma Import (C, Internal, "guilib"); Data : aliased Data_Type; Result : int; begin Result := Internal (int (No), Data'Access); if Result /= 0 then Raise_Exception (SQL_Error'Identity, "Error code:" & int'Image (Result)); else return Data; end if; end Generic_Get; Declare a type you need, e.g. Product: type Product is record Code : int; Price : float; Descr : char_array (1..50); end record; pragma Convention (C, Product); -- Note this pragma! Instantiate the function: function Get is new Generic_Get (Product); Use it as: X : Product := Get (0); -- Regards, Dmitry A. Kazakov http://www.dmitry-kazakov.de ^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: How to access this package written in C? 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 2 siblings, 0 replies; 19+ messages in thread From: Björn Persson @ 2010-04-22 20:12 UTC (permalink / raw) resander wrote: > void getproduct ( PRODUCT * pout , int * resultout ) > { > *resultout = guidb ( 0 , (int)pout ) ; > } Who is forcing you to cast pointers to int? I recommend applying a clue-by- four to that person's head. That code is broken on 64-bit GNU/Linux. Good luck porting that program to Windows if what you have shown is representative of its quality. Before you write the Ada binding you should fix the interface so that it's sane according to the C standard. -- Bj�rn Persson PGP key A88682FD ^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: How to access this package written in C? 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 2 siblings, 1 reply; 19+ messages in thread From: Keith Thompson @ 2010-04-22 21:12 UTC (permalink / raw) resander <kresander@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) kst-u@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" ^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: How to access this package written in C? 2010-04-22 21:12 ` Keith Thompson @ 2010-04-23 12:58 ` resander 2010-04-23 14:15 ` Dmitry A. Kazakov ` (2 more replies) 0 siblings, 3 replies; 19+ messages in thread From: resander @ 2010-04-23 12:58 UTC (permalink / raw) 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 ^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: How to access this package written in C? 2010-04-23 12:58 ` resander @ 2010-04-23 14:15 ` Dmitry A. Kazakov 2010-04-23 14:44 ` John B. Matthews 2010-04-26 18:16 ` Robert A Duff 2 siblings, 0 replies; 19+ messages in thread From: Dmitry A. Kazakov @ 2010-04-23 14:15 UTC (permalink / raw) 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 ^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: How to access this package written in C? 2010-04-23 12:58 ` resander 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 2 siblings, 1 reply; 19+ messages in thread From: John B. Matthews @ 2010-04-23 14:44 UTC (permalink / raw) In article <e98bcf01-46cc-44dd-b57b-3cc7e273d9e2@j21g2000yqh.googlegroups.com>, resander <kresander@gmail.com> wrote: > 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 > ... > Q1. > Addresses are not negative. How do I output a System.Address? -1079352648 = 0xBFAA62B8 -1079352644 = 0xBFAA62BC ... This recent thread discusses several ways to display hexadecimal: <http://groups.google.com/group/comp.lang.ada/browse_frm/thread/f3514db0a21f9b44> A.10.8 Input-Output for Integer Types may be the most straightforward: <http://www.adaic.com/standards/05rm/html/RM-A-10-8.html> -- John B. Matthews trashgod at gmail dot com <http://sites.google.com/site/drjohnbmatthews> ^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: How to access this package written in C? 2010-04-23 14:44 ` John B. Matthews @ 2010-04-23 15:39 ` John B. Matthews 0 siblings, 0 replies; 19+ messages in thread From: John B. Matthews @ 2010-04-23 15:39 UTC (permalink / raw) In article <nospam-84056C.10444823042010@news.aioe.org>, "John B. Matthews" <nospam@nospam.invalid> wrote: > In article > <e98bcf01-46cc-44dd-b57b-3cc7e273d9e2@j21g2000yqh.googlegroups.com>, > resander <kresander@gmail.com> wrote: > > > 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 > > ... > > Q1. > > Addresses are not negative. How do I output a System.Address? > > -1079352648 = 0xBFAA62B8 > -1079352644 = 0xBFAA62BC > ... > > This recent thread discusses several ways to display hexadecimal: > > <http://groups.google.com/group/comp.lang.ada/browse_frm/thread/f3514db0a21f9b > 44> > > A.10.8 Input-Output for Integer Types may be the most straightforward: > > <http://www.adaic.com/standards/05rm/html/RM-A-10-8.html> For example, with Ada.Text_IO; with System.Storage_Elements; procedure Modular is package Memory renames System.Storage_Elements; package Address_IO is new Ada.Text_IO.Modular_IO(Memory.Integer_Address); begin Ada.Text_IO.Put("Address of procedure Modular: "); Address_IO.Put( Item => Memory.To_Integer(Modular'Address), Width => 0, Base => 16); Ada.Text_IO.New_Line; end Modular; -- John B. Matthews trashgod at gmail dot com <http://sites.google.com/site/drjohnbmatthews> ^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: How to access this package written in C? 2010-04-23 12:58 ` resander 2010-04-23 14:15 ` Dmitry A. Kazakov 2010-04-23 14:44 ` John B. Matthews @ 2010-04-26 18:16 ` Robert A Duff 2010-04-26 19:57 ` Keith Thompson 2 siblings, 1 reply; 19+ messages in thread From: Robert A Duff @ 2010-04-26 18:16 UTC (permalink / raw) resander <kresander@gmail.com> writes: > On Apr 22, 10:12�pm, Keith Thompson <ks...@mib.org> wrote: >> 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. Why? I'd think if int is smaller than whatever*, then a cast to int clearly deserves a warning. >> The right type for this parameter is void* (which is roughly >> analogous to Ada's System.Address). Yeah, roughly. System.Address is somewhat lower level than C's void*. > 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! You should look at section B (especially B.3) of the Ada RM. There's a type char_star you can use. There's no void_star. I'm not sure why -- probably this part of Ada predates void* in C, and nobody bothered to upgrade Ada to match the new C. > Q1. > Addresses are not negative. How do I output a System.Address? In GNAT, there is a function System.Address_Image. Look at the file s-addima.ads in your GNAT distribution. Beware: this is not portable to other Ada compilers. - Bob ^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: How to access this package written in C? 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 0:20 ` Robert A Duff 0 siblings, 2 replies; 19+ messages in thread From: Keith Thompson @ 2010-04-26 19:57 UTC (permalink / raw) Robert A Duff <bobduff@shell01.TheWorld.com> writes: > resander <kresander@gmail.com> writes: > >> On Apr 22, 10:12 pm, Keith Thompson <ks...@mib.org> wrote: >>> 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. > > Why? I'd think if int is smaller than whatever*, then > a cast to int clearly deserves a warning. I made an assumption, thereby making an ass out of me and umption. In fact gcc does warn about converting a pointer to a smaller integer type: warning: cast from pointer to integer of different size As the wording implies, it produces the same warning for a cast from a pointer to a larger integer type. I haven't checked other C compilers. In many cases, though, C compilers tend to take a cast operator to mean "do this conversion and don't bother me, I know what I'm doing". [...] >> 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! > > You should look at section B (especially B.3) of the Ada RM. > There's a type char_star you can use. > > There's no void_star. I'm not sure why -- probably this > part of Ada predates void* in C, and nobody bothered > to upgrade Ada to match the new C. As I recall, Ada 83 didn't have any of this; it was introduced in Ada 95. void* was introduced in the ANSI C standard in 1989 (reissued with cosmetic changes as the ISO C standard in 1990). But C still requires char* and void* to have the same representation. But in the Ada RM, I only see char_star in an example: subtype Char_Star is Char_Ptrs.Pointer; [snip] The document I'm looking at is "Ada Reference Manual, ISO/IEC 8652:2007(E) Ed. 3", "ISO/IEC 8652:1995(E) with Technical Corrigendum 1 and Amendment 1". Is that the most current version? A few comments on Interfaces.C: plain_char is a subtype of either unsigned_char or signed_char. In C, plain char is actually a distinct type, though it has the same representation as either unsigned char or signed char. It would be more consistent to have either type plain_char is new signed_char; or type plain_char is new unsigned_char; depending on the implementation. There's no need for nul, wide_nul, and char32_nul to be implementation-defined; they're all zero by definition: nul : constant char := char'val(0); ... wide_nul : constant wchar_t := wchar_t'val(0); ... char32_nul : constant char32_t := char32_t'val(0); C doesn't actually have a type corresponding to char32_t; it has wchar_t, but its size is implementation-defined. Execution of Free(X) is also erroneous if the chars_ptr X was not returned by New_Char_Array or New_String. It should also be mentioned that calling Free twice on the same pointer value is erroneous (you can do this by saving a copy of the pointer before the first call to Free). -- Keith Thompson (The_Other_Keith) kst-u@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" ^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: How to access this package written in C? 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 0:20 ` Robert A Duff 1 sibling, 1 reply; 19+ messages in thread From: Maciej Sobczak @ 2010-04-26 21:20 UTC (permalink / raw) On 26 Kwi, 21:57, Keith Thompson <ks...@mib.org> wrote: > But C still requires char* and void* to have the same representation. > > But in the Ada RM, I only see char_star in an example: > > subtype Char_Star is Char_Ptrs.Pointer; I use this: subtype Void_Ptr is System.Address; It works like a charm. Please note that in order to link Ada with C there is a need for a *pair* of *compatible* compilers - you cannot compile the Ada part with a random Ada compiler and a C part with a random C compiler and expect them to work together. There is a lot of hand-waving in the multilanguage development, which means lots of under-the-table assumptions can be taken for granted even though they are not explicitly covered by any of the language standards. -- Maciej Sobczak * http://www.inspirel.com YAMI4 - Messaging Solution for Distributed Systems http://www.inspirel.com/yami4 ^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: How to access this package written in C? 2010-04-26 21:20 ` Maciej Sobczak @ 2010-04-27 6:52 ` Alex R. Mosteo 2010-04-27 22:29 ` Randy Brukardt 0 siblings, 1 reply; 19+ messages in thread From: Alex R. Mosteo @ 2010-04-27 6:52 UTC (permalink / raw) Maciej Sobczak wrote: > On 26 Kwi, 21:57, Keith Thompson <ks...@mib.org> wrote: > >> But C still requires char* and void* to have the same representation. >> >> But in the Ada RM, I only see char_star in an example: >> >> subtype Char_Star is Char_Ptrs.Pointer; > > I use this: > > subtype Void_Ptr is System.Address; I have sometimes used type Void is null record; pragma Convention (Void, C); type Void_Ptr is access all Void; pragma Convention (Void_Ptr, C); Curious here about any implications of using the different approaches. When doing bindings I tend to avoid 'Access and 'Address whenever possible, though; using in out parameters seems to be sufficient in the 99% of cases. On the one hand I like to remain as high-level as possible; on the other I could see that System.Address leaves less room for compiler fancies... > It works like a charm. Please note that in order to link Ada with C > there is a need for a *pair* of *compatible* compilers - you cannot > compile the Ada part with a random Ada compiler and a C part with a > random C compiler and expect them to work together. There is a lot of > hand-waving in the multilanguage development, which means lots of > under-the-table assumptions can be taken for granted even though they > are not explicitly covered by any of the language standards. > > -- > Maciej Sobczak * http://www.inspirel.com > > YAMI4 - Messaging Solution for Distributed Systems > http://www.inspirel.com/yami4 ^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: How to access this package written in C? 2010-04-27 6:52 ` Alex R. Mosteo @ 2010-04-27 22:29 ` Randy Brukardt 2010-05-03 8:12 ` Alex R. Mosteo 0 siblings, 1 reply; 19+ messages in thread From: Randy Brukardt @ 2010-04-27 22:29 UTC (permalink / raw) ... >> I use this: >> >> subtype Void_Ptr is System.Address; > > I have sometimes used > > type Void is null record; > pragma Convention (Void, C); > type Void_Ptr is access all Void; > pragma Convention (Void_Ptr, C); Most of the time, I've avoided any version of void* and simply written overloadings for each type that I needed (using in out parameters if possible, or access parameters if I needed the function result). That only works of course when the number of types that you need is limited, and it's not as flexible as some more direct mapping. But void* is exactly the opposite of strong typing, and it simply doesn't fit well into the Ada type model. So avoiding it if possible is the best approach. Randy. ^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: How to access this package written in C? 2010-04-27 22:29 ` Randy Brukardt @ 2010-05-03 8:12 ` Alex R. Mosteo 0 siblings, 0 replies; 19+ messages in thread From: Alex R. Mosteo @ 2010-05-03 8:12 UTC (permalink / raw) Randy Brukardt wrote: > ... >>> I use this: >>> >>> subtype Void_Ptr is System.Address; >> >> I have sometimes used >> >> type Void is null record; >> pragma Convention (Void, C); >> type Void_Ptr is access all Void; >> pragma Convention (Void_Ptr, C); > > Most of the time, I've avoided any version of void* and simply written > overloadings for each type that I needed (using in out parameters if > possible, or access parameters if I needed the function result). That only > works of course when the number of types that you need is limited, and > it's not as flexible as some more direct mapping. > > But void* is exactly the opposite of strong typing, and it simply doesn't > fit well into the Ada type model. So avoiding it if possible is the best > approach. I've lived both ways, and I understand your point. In the particular case I had in mind, the C side changed too frequently for my own good, so using an opaque type and passing the pointer to it to C-side routines was the less maintenance-intensive approach. Massaging the C data returns into my own set of Ada types worked well, since the trick is hidden from user code. This reminds me of another thing that bores me about bindings, which is that even if you mimic C types with Ada types using convention C, these types are not always nice to propagate to client code, so in the end I find myself with even more duplicated types. ^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: How to access this package written in C? 2010-04-26 19:57 ` Keith Thompson 2010-04-26 21:20 ` Maciej Sobczak @ 2010-04-27 0:20 ` Robert A Duff 2010-04-27 1:01 ` Keith Thompson 2010-04-27 1:31 ` Randy Brukardt 1 sibling, 2 replies; 19+ messages in thread From: Robert A Duff @ 2010-04-27 0:20 UTC (permalink / raw) Keith Thompson <kst-u@mib.org> writes: > Robert A Duff <bobduff@shell01.TheWorld.com> writes: >> resander <kresander@gmail.com> writes: >> >>> On Apr 22, 10:12�pm, Keith Thompson <ks...@mib.org> wrote: >>>> 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. >> >> Why? I'd think if int is smaller than whatever*, then >> a cast to int clearly deserves a warning. > > I made an assumption, thereby making an ass out of me and umption. ;-) > In fact gcc does warn about converting a pointer to a smaller integer > type: > > warning: cast from pointer to integer of different size > > As the wording implies, it produces the same warning for a cast from a > pointer to a larger integer type. As well it should. Thanks for checking gcc. Of course I have a gcc at hand (which compiles both Ada and C), but I was too lazy to try it. Thanks! > I haven't checked other C compilers. > > In many cases, though, C compilers tend to take a cast operator to mean > "do this conversion and don't bother me, I know what I'm doing". Ada is somewhat better, here, in that safer conversions have a different syntax from unsafer conversions. A cast, in C, might mean something fairly innocuous, or it might mean "damn the torpedoes, full speed ahead!", and it's hard for a C compiler to know which is which. > [...] > >>> 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! >> >> You should look at section B (especially B.3) of the Ada RM. >> There's a type char_star you can use. >> >> There's no void_star. I'm not sure why -- probably this >> part of Ada predates void* in C, and nobody bothered >> to upgrade Ada to match the new C. > > As I recall, Ada 83 didn't have any of this; it was introduced in Ada > 95. Right. Ada 83 just had pragma Interface (now called pragma Import), and it just let implementations provide whatever interface-to-C or interface-to-whatever they liked. Ada 95, 2005, and 2012 offer much more. > void* was introduced in the ANSI C standard in 1989 (reissued with > cosmetic changes as the ISO C standard in 1990). > > But C still requires char* and void* to have the same representation. > > But in the Ada RM, I only see char_star in an example: > > subtype Char_Star is Char_Ptrs.Pointer; Yes, you're right. My mistake -- there's no char_star in Ada. You have to instantiate the C.Pointers generic package, which is a bit of a pain. On the other hand, Ada has the Interfaces.C.Strings package, which has convenient things like char_array_access and chars_ptr. Note that GNAT tries pretty hard to make Ada types match C types in representation, so if you're willing to stick with gcc to compile your Ada and C programs, it works nicely. > [snip] > > The document I'm looking at is "Ada Reference Manual, ISO/IEC > 8652:2007(E) Ed. 3", "ISO/IEC 8652:1995(E) with Technical Corrigendum 1 > and Amendment 1". Is that the most current version? No. The most current standard is here: http://www.ada-auth.org/ after you rummage aroung a bit. Look for the Ada 2005 version. The most current future to-be-standardized version (for Ada 2012) is here: http://www.adaic.org/standards/ada1z.html Note that this one has no official ISO status yet. > A few comments on Interfaces.C: Note that you can send comments on the Ada standard to ada-comment@ada-auth.org. I know you are an expert on both C and Ada, so I think your comments about Ada-interfacing-to-C should be taken very seriously. > plain_char is a subtype of either unsigned_char or signed_char. In C, > plain char is actually a distinct type, though it has the same > representation as either unsigned char or signed char. It would be more > consistent to have either > type plain_char is new signed_char; > or > type plain_char is new unsigned_char; > depending on the implementation. I think I disagree with that, because "distinct type" means different things in C versus Ada, because there are different implicit conversions in the two languages. In C, you can freely assign amongst these types (I think), whereas Ada is more strict. I'm not sure about that, but in any case, we're not going to make incompatible changes (as subtype --> type surely would be). > There's no need for nul, wide_nul, and char32_nul to be > implementation-defined; they're all zero by definition: > > nul : constant char := char'val(0); > ... > wide_nul : constant wchar_t := wchar_t'val(0); > ... > char32_nul : constant char32_t := char32_t'val(0); Yes, I think that makes sense. See also AI95-00037. > C doesn't actually have a type corresponding to char32_t; it has > wchar_t, but its size is implementation-defined. So what do you think it should say? > Execution of Free(X) is also erroneous if the chars_ptr X was not > returned by New_Char_Array or New_String. > > It should also be mentioned that calling Free twice on the same > pointer value is erroneous (you can do this by saving a copy of the > pointer before the first call to Free). Yes, I agree. - Bob ^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: How to access this package written in C? 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 1:31 ` Randy Brukardt 1 sibling, 1 reply; 19+ messages in thread From: Keith Thompson @ 2010-04-27 1:01 UTC (permalink / raw) Robert A Duff <bobduff@shell01.TheWorld.com> writes: > Keith Thompson <kst-u@mib.org> writes: >> Robert A Duff <bobduff@shell01.TheWorld.com> writes: >>> resander <kresander@gmail.com> writes: >>>> On Apr 22, 10:12 pm, Keith Thompson <ks...@mib.org> wrote: >>>>> 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. >>> >>> Why? I'd think if int is smaller than whatever*, then >>> a cast to int clearly deserves a warning. >> >> I made an assumption, thereby making an ass out of me and umption. > > ;-) > >> In fact gcc does warn about converting a pointer to a smaller integer >> type: >> >> warning: cast from pointer to integer of different size >> >> As the wording implies, it produces the same warning for a cast from a >> pointer to a larger integer type. > > As well it should. > > Thanks for checking gcc. Of course I have a gcc at hand (which compiles > both Ada and C), but I was too lazy to try it. Thanks! > >> I haven't checked other C compilers. >> >> In many cases, though, C compilers tend to take a cast operator to mean >> "do this conversion and don't bother me, I know what I'm doing". > > Ada is somewhat better, here, in that safer conversions > have a different syntax from unsafer conversions. > > A cast, in C, might mean something fairly innocuous, or it might mean > "damn the torpedoes, full speed ahead!", and it's hard for a C compiler > to know which is which. Casts (i.e., explicit conversions) are rarely necessary in well-written C. (They're unfortunately common in C in general.) Most conversions in C are performed implicitly. All arithmetic types are implicitly convertible to each other, and all pointer-to-object types are implicitly convertible to and from void*. Casts are useful when you need to override the default conversions in an arithmetic expression, for certain kinds of arguments to variadic functions such as printf, and when you need to play games with pointers in non-portable code. (That's probably more information about C than most people here are interested in, so I'll stop now.) >> The document I'm looking at is "Ada Reference Manual, ISO/IEC >> 8652:2007(E) Ed. 3", "ISO/IEC 8652:1995(E) with Technical Corrigendum 1 >> and Amendment 1". Is that the most current version? > > No. The most current standard is here: > > http://www.ada-auth.org/ > > after you rummage aroung a bit. Look for the Ada 2005 version. I did. <http://www.ada-auth.org/arm.html> has links to several versions of the Ada 2005 RM. "RM-Final.pdf" is byte-for-byte identical to the version I'm using, and has the above-quoted text on the title page. > The most current future to-be-standardized version (for Ada 2012) is > here: > > http://www.adaic.org/standards/ada1z.html > > Note that this one has no official ISO status yet. I'll check that out, thanks. >> A few comments on Interfaces.C: > > Note that you can send comments on the Ada standard to > ada-comment@ada-auth.org. I know you are an expert on > both C and Ada, so I think your comments about Ada-interfacing-to-C > should be taken very seriously. Thanks, I'll do that. I seem to recall they expect some particular format for comments (it's been a long time since I've submitted any); is that still the case, or should I just send free-form English text? >> plain_char is a subtype of either unsigned_char or signed_char. In C, >> plain char is actually a distinct type, though it has the same >> representation as either unsigned char or signed char. It would be more >> consistent to have either >> type plain_char is new signed_char; >> or >> type plain_char is new unsigned_char; >> depending on the implementation. > > I think I disagree with that, because "distinct type" > means different things in C versus Ada, because there > are different implicit conversions in the two languages. > > In C, you can freely assign amongst these types (I think), > whereas Ada is more strict. > > I'm not sure about that, but in any case, we're not going > to make incompatible changes (as subtype --> type surely > would be). Yeah, breaking compatibility would be bad. Still, the current situation means that this: P: plain_char := 0; S: signed_char := P; is either valid or illegal, depending on the implementation. It's also odd that char and plain_char are two distinct types, but there's only so much you can do to make C and Ada work together. >> There's no need for nul, wide_nul, and char32_nul to be >> implementation-defined; they're all zero by definition: >> >> nul : constant char := char'val(0); >> ... >> wide_nul : constant wchar_t := wchar_t'val(0); >> ... >> char32_nul : constant char32_t := char32_t'val(0); > > Yes, I think that makes sense. See also AI95-00037. > >> C doesn't actually have a type corresponding to char32_t; it has >> wchar_t, but its size is implementation-defined. > > So what do you think it should say? I don't know. C201X might have some additional support in this area (but since even C99 isn't universally supported, I'm not sure how useful that is). [...] -- Keith Thompson (The_Other_Keith) kst-u@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" ^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: How to access this package written in C? 2010-04-27 1:01 ` Keith Thompson @ 2010-04-27 16:07 ` Robert A Duff 2010-04-27 22:29 ` Randy Brukardt 0 siblings, 1 reply; 19+ messages in thread From: Robert A Duff @ 2010-04-27 16:07 UTC (permalink / raw) Keith Thompson <kst-u@mib.org> writes: > I did. <http://www.ada-auth.org/arm.html> has links to several versions > of the Ada 2005 RM. "RM-Final.pdf" is byte-for-byte identical to the > version I'm using, and has the above-quoted text on the title page. Sorry for the misinformation. > Thanks, I'll do that. I seem to recall they expect some particular > format for comments (it's been a long time since I've submitted any); is > that still the case, or should I just send free-form English text? I think there are instructions near the beginning of the RM. I think if you disobey those instructions, your comment will still get processed and shipped out to the mailing list. I think you're not supposed to cc: other addresses when sending to ada-comment@ada-auth.org. But Randy is the expert on these procedures. - Bob ^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: How to access this package written in C? 2010-04-27 16:07 ` Robert A Duff @ 2010-04-27 22:29 ` Randy Brukardt 0 siblings, 0 replies; 19+ messages in thread From: Randy Brukardt @ 2010-04-27 22:29 UTC (permalink / raw) "Robert A Duff" <bobduff@shell01.TheWorld.com> wrote in message news:wccbpd4x4j9.fsf@shell01.TheWorld.com... > Keith Thompson <kst-u@mib.org> writes: > >> I did. <http://www.ada-auth.org/arm.html> has links to several versions >> of the Ada 2005 RM. "RM-Final.pdf" is byte-for-byte identical to the >> version I'm using, and has the above-quoted text on the title page. > > Sorry for the misinformation. > >> Thanks, I'll do that. I seem to recall they expect some particular >> format for comments (it's been a long time since I've submitted any); is >> that still the case, or should I just send free-form English text? > > I think there are instructions near the beginning of the RM. > I think if you disobey those instructions, your comment > will still get processed and shipped out to the mailing > list. > > I think you're not supposed to cc: other addresses > when sending to ada-comment@ada-auth.org. > > But Randy is the expert on these procedures. Bob got these right this time. :-) Randy. ^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: How to access this package written in C? 2010-04-27 0:20 ` Robert A Duff 2010-04-27 1:01 ` Keith Thompson @ 2010-04-27 1:31 ` Randy Brukardt 1 sibling, 0 replies; 19+ messages in thread From: Randy Brukardt @ 2010-04-27 1:31 UTC (permalink / raw) "Robert A Duff" <bobduff@shell01.TheWorld.com> wrote in message news:wcceii1g308.fsf@shell01.TheWorld.com... > Keith Thompson <kst-u@mib.org> writes: ... >> The document I'm looking at is "Ada Reference Manual, ISO/IEC >> 8652:2007(E) Ed. 3", "ISO/IEC 8652:1995(E) with Technical Corrigendum 1 >> and Amendment 1". Is that the most current version? > > No. The most current standard is here: > > http://www.ada-auth.org/ Actually, the title Keith gives is that of the most recent "official" consolidated edition. And the on-line versions of the Ada 2005 stuff are found in http://www.adaic.org/standards/ada05.html (You can get the source and tools for generating the standard from www.ada-auth.org, but that is something that very few people need.) > after you rummage aroung a bit. Look for the Ada 2005 version. The > most current future to-be-standardized version (for Ada 2012) is here: > > http://www.adaic.org/standards/ada1z.html > > Note that this one has no official ISO status yet. Note that the above URL is going to change drastically when the next draft version is posted (probably next week). It is going to move to www.ada-auth.org and will be named Ada 2012 (instead of the "1z"). I'll try to maintain some sort of forwarding, but it is best to change you bookmarks then. So to sum up, Bob got it exactly backwards. ;-) ... >> There's no need for nul, wide_nul, and char32_nul to be >> implementation-defined; they're all zero by definition: >> >> nul : constant char := char'val(0); >> ... >> wide_nul : constant wchar_t := wchar_t'val(0); >> ... >> char32_nul : constant char32_t := char32_t'val(0); > > Yes, I think that makes sense. See also AI95-00037. > >> C doesn't actually have a type corresponding to char32_t; it has >> wchar_t, but its size is implementation-defined. I believe that the char16 and char32 types were to match some proposed C update; not sure if that was ever adopted. Ah, here's what AI95-00285-1 has to say on the subject: -- SC22/WG14 is planning to include support for Unicode 16- and 32-bit characters -- in C. Their proposal is presented in ISO/IEC TR 19769:2004 -- (http://www.open-std.org/jtc1/sc22//WG14/www/docs/n1040.pdf). In order to -- provide compatibility with the upcoming C standard, new types are added to -- Interfaces.C that correspond to C char16_t and char32_t. It is recognized that -- adding new declarations to predefined units can cause incompatibilities, but it -- is thought that the new identifiers are unlikely to conflict with existing -- code. We may have jumped the gun on adding these, but as Bob noted, we're not going to remove them as the incompatibility would be significant and it's harmless to have them. Randy. ^ permalink raw reply [flat|nested] 19+ messages in thread
end of thread, other threads:[~2010-05-03 8:12 UTC | newest] Thread overview: 19+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 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 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
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox