* C array to ada record interface @ 2004-07-14 23:17 Francisco Javier Loma Daza 2004-07-15 0:36 ` Brian May 2004-07-15 1:23 ` Jeffrey Carter 0 siblings, 2 replies; 13+ messages in thread From: Francisco Javier Loma Daza @ 2004-07-14 23:17 UTC (permalink / raw) It may be a FAQ, but I had not succeed to find some info so ... I have a C struct like that struct { int a,b,c: int len; struct b* arr; } A; And I would love to interface in Ada with a record with a discriminant type B_array(len: Positive) is record arr: array of B(1..len); end record; type A(len: Positive) is a,b,c: Integer; arr: A(len); end record; What representation clauses and interfacing pragmas I need to use? Is there a repository of examples about C interfacing? Thanks in advance ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: C array to ada record interface 2004-07-14 23:17 C array to ada record interface Francisco Javier Loma Daza @ 2004-07-15 0:36 ` Brian May 2004-07-15 1:23 ` Jeffrey Carter 1 sibling, 0 replies; 13+ messages in thread From: Brian May @ 2004-07-15 0:36 UTC (permalink / raw) >>>>> "Francisco" == Francisco Javier Loma Daza <fjloma@andaluciajunta.es> writes: Francisco> It may be a FAQ, but I had not succeed to find some info so ... Francisco> I have a C struct like that Francisco> struct Francisco> { Francisco> int a,b,c: Francisco> int len; Francisco> struct b* arr; Francisco> } A; What is the b type? Francisco> And I would love to interface in Ada with a record with Francisco> a discriminant Francisco> type B_array(len: Positive) is record Francisco> arr: array of B(1..len); Francisco> end record; Francisco> type A(len: Positive) is Francisco> a,b,c: Integer; Francisco> arr: A(len); Did you really mean to create a recursive type here? Shouldn't this be B_Array? Francisco> end record; Francisco> What representation clauses and interfacing pragmas I Francisco> need to use? Is there a repository of examples about C Francisco> interfacing? -- Brian May <bam@snoopy.apana.org.au> ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: C array to ada record interface 2004-07-14 23:17 C array to ada record interface Francisco Javier Loma Daza 2004-07-15 0:36 ` Brian May @ 2004-07-15 1:23 ` Jeffrey Carter 2004-07-22 18:02 ` Francisco Javier Loma Daza 1 sibling, 1 reply; 13+ messages in thread From: Jeffrey Carter @ 2004-07-15 1:23 UTC (permalink / raw) Francisco Javier Loma Daza wrote: > struct > { > int a,b,c: > int len; > struct b* arr; > } A; > > And I would love to interface in Ada with a record with a discriminant > > type B_array(len: Positive) is record > arr: array of B(1..len); > end record; > > type A(len: Positive) is > a,b,c: Integer; > arr: A(len); > end record; Assuming you meant Arr : B_Array (Len => Len); this won't work. What you have from C is a pointer; the actual array may not even be contiguous with the struct. You'll have to do something like type B_Ptr is access all B; pragma Convention (C, B_Ptr); type A_Info is record A, B, C : Interfaces.C.Int; Len : Interfaces.C.Int; Arr : B_Ptr; end record; pragma Convention (C, A_Info); You only use these types when talking directly to C. For the rest of your application, you use something like the record you presented, and have your operations that talk to C convert between the 2. -- Jeff Carter "This trial is a travesty. It's a travesty of a mockery of a sham of a mockery of a travesty of two mockeries of a sham. ... Do you realize there's not a single homosexual on that jury?" Bananas 27 ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: C array to ada record interface 2004-07-15 1:23 ` Jeffrey Carter @ 2004-07-22 18:02 ` Francisco Javier Loma Daza 2004-07-24 18:48 ` Ludovic Brenta 0 siblings, 1 reply; 13+ messages in thread From: Francisco Javier Loma Daza @ 2004-07-22 18:02 UTC (permalink / raw) Jeffrey Carter <spam@spam.com> wrote in message news:<W%kJc.3320$Qu5.3121@newsread2.news.pas.earthlink.net>... > Francisco Javier Loma Daza wrote: > > > struct > > { > > int a,b,c: > > int len; > > struct b* arr; > > } A; > > > > And I would love to interface in Ada with a record with a discriminant > > > > type B_array(len: Positive) is record > > arr: array of B(1..len); > > end record; > > > > type A(len: Positive) is > > a,b,c: Integer; > > arr: A(len); > > end record; > > Assuming you meant > > Arr : B_Array (Len => Len); > > this won't work. What you have from C is a pointer; the actual array may > not even be contiguous with the struct. You'll have to do something like > > type B_Ptr is access all B; > pragma Convention (C, B_Ptr); > > type A_Info is record > A, B, C : Interfaces.C.Int; > Len : Interfaces.C.Int; > Arr : B_Ptr; > end record; > pragma Convention (C, A_Info); > > You only use these types when talking directly to C. For the rest of > your application, you use something like the record you presented, and > have your operations that talk to C convert between the 2. Thanks, I think you understood well I would want to use some more ada like array, you suggest to implement that with accesors functions ... I was just wondering if it can be done, the Len + Arr part, to be set up as an Ada array ... ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: C array to ada record interface 2004-07-22 18:02 ` Francisco Javier Loma Daza @ 2004-07-24 18:48 ` Ludovic Brenta 2004-07-25 17:26 ` Francisco Javier Loma Daza 2004-07-25 19:28 ` tmoran 0 siblings, 2 replies; 13+ messages in thread From: Ludovic Brenta @ 2004-07-24 18:48 UTC (permalink / raw) (Francisco Javier Loma Daza) writes: > Jeffrey Carter wrote in message Francisco Javier Loma Daza wrote: >> >> > struct >> > { >> > int a,b,c: >> > int len; >> > struct b* arr; >> > } A; >> > >> > And I would love to interface in Ada with a record with a discriminant >> > >> > type B_array(len: Positive) is record >> > arr: array of B(1..len); >> > end record; >> > >> > type A(len: Positive) is >> > a,b,c: Integer; >> > arr: A(len); >> > end record; >> >> Assuming you meant >> >> Arr : B_Array (Len => Len); >> >> this won't work. What you have from C is a pointer; the actual array may >> not even be contiguous with the struct. You'll have to do something like >> >> type B_Ptr is access all B; >> pragma Convention (C, B_Ptr); >> >> type A_Info is record >> A, B, C : Interfaces.C.Int; >> Len : Interfaces.C.Int; >> Arr : B_Ptr; >> end record; >> pragma Convention (C, A_Info); >> >> You only use these types when talking directly to C. For the rest of >> your application, you use something like the record you presented, and >> have your operations that talk to C convert between the 2. > > > Thanks, I think you understood well > > I would want to use some more ada like array, you suggest to implement > that with accesors functions ... I was just wondering if it can be > done, the Len + Arr part, to be set up as an Ada array ... Yes, it can be done: with Ada.Unchecked_Conversion; function To_Ada_Array (Arr : in B_Ptr; Len : in Interfaces.C.int) return B_Array is subtype Array_With_Known_Length is B_Array (1 .. Len); function To_Ada is new Ada.Unchecked_Conversion (Source => B_Ptr, Target => Array_With_Known_Length); begin -- ... end To_Ada_Array; In the begin/end block you have two possible strategies: return To_Ada (B_Ptr); will return a B_Array where the Arr member has the same address (in memory) as the original C array. If you deallocate the C array, you will get a Constraint_Error if you try to use the Ada array. If you want to avoid this, the other strategy is to return a copy: declare Input : Array_With_Known_Lengh := To_Ada (Arr); Result : B_Array (1 .. Len) := Input; begin return Result; end; The advantage of having a copy is that Result.Arr has a different address than the C array; thus you manage the memory separately for the C and Ada arrays. You can now safely deallocate the C array; the Ada compiler will manage the memory for the Ada array for you, since you declared it on the stack. The disadvantage of this approach is that it requires more memory to run; if the array is very large, it could become a problem. HTH (PS. I have not tried to compile my example code, so there may be errors in it) -- Ludovic Brenta. ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: C array to ada record interface 2004-07-24 18:48 ` Ludovic Brenta @ 2004-07-25 17:26 ` Francisco Javier Loma Daza 2004-07-25 19:28 ` tmoran 1 sibling, 0 replies; 13+ messages in thread From: Francisco Javier Loma Daza @ 2004-07-25 17:26 UTC (permalink / raw) Ludovic Brenta <ludovic.brenta@insalien.org> wrote in message news:<87iscdi6m5.fsf@insalien.org>... > (Francisco Javier Loma Daza) writes: > > Jeffrey Carter wrote in message Francisco Javier Loma Daza wrote: > >> > >> > struct > >> > { > >> > int a,b,c: > >> > int len; > >> > struct b* arr; > >> > } A; > >> > > >> > And I would love to interface in Ada with a record with a discriminant > >> > > >> > type B_array(len: Positive) is record > >> > arr: array of B(1..len); > >> > end record; > >> > > >> > type A(len: Positive) is > >> > a,b,c: Integer; > >> > arr: A(len); > >> > end record; > >> > >> Assuming you meant > >> > >> Arr : B_Array (Len => Len); > >> > >> this won't work. What you have from C is a pointer; the actual array may > >> not even be contiguous with the struct. You'll have to do something like > >> > >> type B_Ptr is access all B; > >> pragma Convention (C, B_Ptr); > >> > >> type A_Info is record > >> A, B, C : Interfaces.C.Int; > >> Len : Interfaces.C.Int; > >> Arr : B_Ptr; > >> end record; > >> pragma Convention (C, A_Info); > >> > >> You only use these types when talking directly to C. For the rest of > >> your application, you use something like the record you presented, and > >> have your operations that talk to C convert between the 2. > > > > > > Thanks, I think you understood well > > > > I would want to use some more ada like array, you suggest to implement > > that with accesors functions ... I was just wondering if it can be > > done, the Len + Arr part, to be set up as an Ada array ... > > Yes, it can be done: > > with Ada.Unchecked_Conversion; > function To_Ada_Array (Arr : in B_Ptr; Len : in Interfaces.C.int) > return B_Array is > subtype Array_With_Known_Length is B_Array (1 .. Len); > > function To_Ada is new Ada.Unchecked_Conversion > (Source => B_Ptr, Target => Array_With_Known_Length); > > begin > -- ... > end To_Ada_Array; > > > In the begin/end block you have two possible strategies: > > return To_Ada (B_Ptr); > > will return a B_Array where the Arr member has the same address (in > memory) as the original C array. If you deallocate the C array, you > will get a Constraint_Error if you try to use the Ada array. If you > want to avoid this, the other strategy is to return a copy: > > declare > Input : Array_With_Known_Lengh := To_Ada (Arr); > Result : B_Array (1 .. Len) := Input; > begin > return Result; > end; > > The advantage of having a copy is that Result.Arr has a different > address than the C array; thus you manage the memory separately for > the C and Ada arrays. You can now safely deallocate the C array; the > Ada compiler will manage the memory for the Ada array for you, since > you declared it on the stack. > > The disadvantage of this approach is that it requires more memory to > run; if the array is very large, it could become a problem. > > HTH > > (PS. I have not tried to compile my example code, so there may be > errors in it) Thanks to all. ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: C array to ada record interface 2004-07-24 18:48 ` Ludovic Brenta 2004-07-25 17:26 ` Francisco Javier Loma Daza @ 2004-07-25 19:28 ` tmoran 2004-07-26 21:42 ` Ludovic Brenta 1 sibling, 1 reply; 13+ messages in thread From: tmoran @ 2004-07-25 19:28 UTC (permalink / raw) > (PS. I have not tried to compile my example code, so there may be > errors in it) Could you post a complete, running, example please? I must have missed something. Here is my interpretation of such a thing, but, though it compiles on two out of three Ada compilers I tried, it generates (different) junk results on both. (The third compiler objects to the Unchecked_Conversion instantiation.) with ada.text_io, Ada.Unchecked_Conversion, interfaces.c; procedure testuc2 is type B is new integer; type B_Array is array(Interfaces.c.int range <>) of aliased B; type B_Ptr is access all B; pragma Convention (C, B_Ptr); function To_Ada_Array (Arr : in B_Ptr; Len : in Interfaces.C.int) return B_Array is subtype Array_With_Known_Length is B_Array (1 .. Len); function To_Ada is new Ada.Unchecked_Conversion (Source => B_Ptr, Target => Array_With_Known_Length); begin return To_Ada (Arr); end To_Ada_Array; procedure show(ba : in b_array) is begin ada.text_io.put_line("ba(3)="); ada.text_io.put_line(b'image(ba(3))); end show; x : b_array(1 .. 5) := (others=>17); begin show(to_ada_array(arr=>x(1)'access, len=>5)); end testuc2; ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: C array to ada record interface 2004-07-25 19:28 ` tmoran @ 2004-07-26 21:42 ` Ludovic Brenta 2004-07-27 21:04 ` tmoran 0 siblings, 1 reply; 13+ messages in thread From: Ludovic Brenta @ 2004-07-26 21:42 UTC (permalink / raw) tmoran writes: > Ludovic Brenta wrote: >> (PS. I have not tried to compile my example code, so there may be >> errors in it) > > Could you post a complete, running, example please? I must have missed > something. Here is my interpretation of such a thing, but, though it > compiles on two out of three Ada compilers I tried, it generates > (different) junk results on both. (The third compiler objects to the > Unchecked_Conversion instantiation.) > > with ada.text_io, > Ada.Unchecked_Conversion, > interfaces.c; > procedure testuc2 is > > type B is new integer; > > type B_Array is array(Interfaces.c.int range <>) of aliased B; > > type B_Ptr is access all B; > pragma Convention (C, B_Ptr); > > function To_Ada_Array (Arr : in B_Ptr; Len : in Interfaces.C.int) > return B_Array is > subtype Array_With_Known_Length is B_Array (1 .. Len); > > function To_Ada is new Ada.Unchecked_Conversion > (Source => B_Ptr, Target => Array_With_Known_Length); > > begin > return To_Ada (Arr); > end To_Ada_Array; > > procedure show(ba : in b_array) is > begin > ada.text_io.put_line("ba(3)="); > ada.text_io.put_line(b'image(ba(3))); > end show; > > x : b_array(1 .. 5) := (others=>17); > begin > > show(to_ada_array(arr=>x(1)'access, len=>5)); > > end testuc2; I am the one at fault. Converting the array does not work; converting the pointer to a System.Address, and using that in a representation clause, does work. Here is my fixed code: with Ada.Text_Io, Interfaces.C; with Ada.Unchecked_Conversion; with System; procedure Testuc2 is type B is new Integer; type B_Array is array (Interfaces.C.Int range <>) of aliased B; type B_Ptr is access all B; pragma Convention (C, B_Ptr); function To_Ada_Array (Arr : in B_Ptr; Len : in Interfaces.C.Int) return B_Array is subtype Array_With_Known_Length is B_Array (1 .. Len); pragma Convention (C, Array_With_Known_Length); -- not sure this pragma is necessary function To_Address is new Ada.Unchecked_Conversion (Source => B_Ptr, Target => System.Address); Result : Array_With_Known_Length; for Result'Address use To_Address (Arr); begin return Result; end To_Ada_Array; procedure Show (Ba : in B_Array) is begin Ada.Text_Io.Put_Line ("ba(3)="); Ada.Text_Io.Put_Line (B'Image (Ba (3))); end Show; X : B_Array (1 .. 5) := (others => 17); X_Pointer : B_Ptr := X (X'First)'Access; begin Show (To_Ada_Array (Arr => X_Pointer, Len => X'Length)); end Testuc2; The representation clause ("for Result'Address use ...") specifies that the Ada array starts at the same address as the C array. This makes it possible to use Ada constructs to access elements in Result. At this point, the two strategies I outlined earlier (copy or reference) are available. -- Ludovic Brenta. ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: C array to ada record interface 2004-07-26 21:42 ` Ludovic Brenta @ 2004-07-27 21:04 ` tmoran 2004-07-27 22:15 ` Martin Dowie 2004-07-28 2:42 ` Robert I. Eachus 0 siblings, 2 replies; 13+ messages in thread From: tmoran @ 2004-07-27 21:04 UTC (permalink / raw) > type B_Ptr is access all B; > pragma Convention (C, B_Ptr); > ... > function To_Address is new Ada.Unchecked_Conversion > (Source => B_Ptr, Target => System.Address); Interesting possible problem: One of the compilers I use rejected the Unchecked_Conversion because its System.Address is not the same size as B_Ptr. So I dropped the Unchecked programming and used instead package B_Ptr_Conversion is new System.Address_To_Access_Conversions(B); subtype B_Ptr is B_Ptr_Conversion.Object_Pointer; which works on three different compilers. But neither pragma Convention (C, B_Ptr); nor pragma Convention (C, B_Ptr_Conversion.Object_Pointer); is then legal. The program works without the pragma Convention on all three Ada compilers I tried, but it's not clear to me that's guaranteed to be OK, and if some system does need the pragma, is there a compiler-agnostic way to solve this problem? (Neither is pragma Convention (C, Array_With_Known_Length); legal but that seems even less likely to be necessary.) ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: C array to ada record interface 2004-07-27 21:04 ` tmoran @ 2004-07-27 22:15 ` Martin Dowie 2004-07-28 2:42 ` Robert I. Eachus 1 sibling, 0 replies; 13+ messages in thread From: Martin Dowie @ 2004-07-27 22:15 UTC (permalink / raw) <tmoran@acm.org> wrote in message news:KrzNc.180996$JR4.87585@attbi_s54... > The program works without the pragma Convention on all three Ada compilers > I tried, but it's not clear to me that's guaranteed to be OK, and if some > system does need the pragma, is there a compiler-agnostic way to solve > this problem? > > (Neither is pragma Convention (C, Array_With_Known_Length); > legal but that seems even less likely to be necessary.) Tom, this seems (on the face of it) to be a language whole - have you tried an email to ada-comment to get the definitive language-lawyer view on this? Cheers -- Martin ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: C array to ada record interface 2004-07-27 21:04 ` tmoran 2004-07-27 22:15 ` Martin Dowie @ 2004-07-28 2:42 ` Robert I. Eachus 2004-07-29 5:56 ` tmoran 1 sibling, 1 reply; 13+ messages in thread From: Robert I. Eachus @ 2004-07-28 2:42 UTC (permalink / raw) tmoran@acm.org wrote: > package B_Ptr_Conversion is new System.Address_To_Access_Conversions(B); > subtype B_Ptr is B_Ptr_Conversion.Object_Pointer; > which works on three different compilers. But neither > > pragma Convention (C, B_Ptr); > nor > pragma Convention (C, B_Ptr_Conversion.Object_Pointer); > is then legal. That is correct, see the limitations on where representation pragmas can appear in RM 13.1 as ammended. (The wordsmithing in the 2000 Ammendment in this area is extensive, but I don't think it affected this issue one way or the other.) > The program works without the pragma Convention on all three Ada compilers > I tried, but it's not clear to me that's guaranteed to be OK, and if some > system does need the pragma, is there a compiler-agnostic way to solve > this problem? No! But remember here that what can't be compiler agnostic is the choice of C compiler and options to match the Ada compiler (and options). If the Ada compiler uses the same type of addresses as the C compiler there is no problem. But if you have a 64-bit Ada compiler and a 32-bit C compiler (or vice-versa) it can't work. Well, not quite, but you know what I mean. For example, with the new AMD64 chips--including Intel's newest Xeon--you can have a library that is compiled for IA-32, and another library compiled in long mode, and the hardware will convert the addresses if possible on the calls and returns so that a program can use either one. But you can't link 32-bit code and long mode code into the same executable, you have to use .dlls. The best you can do is to specify the sizes of the addresses, so that the compiler will reject your program if they don't match. In fact a better example of why this is an insoluble problem is that the new Xeon (Nocona) does not have an IOMMU, while the Opteron and Athlon64 use the CPU's MMU for all memory references. The net effect is that I/O drivers have to be written differently for the two families. There is no magic wand that either a C compiler or an Ada compiler can wave to fix that semantic mismatch. -- Robert I. Eachus "The flames kindled on the Fourth of July, 1776, have spread over too much of the globe to be extinguished by the feeble engines of despotism; on the contrary, they will consume these engines and all who work them." -- Thomas Jefferson, 1821 ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: C array to ada record interface 2004-07-28 2:42 ` Robert I. Eachus @ 2004-07-29 5:56 ` tmoran 2004-07-29 19:58 ` Robert I. Eachus 0 siblings, 1 reply; 13+ messages in thread From: tmoran @ 2004-07-29 5:56 UTC (permalink / raw) >> package B_Ptr_Conversion is new System.Address_To_Access_Conversions(B); >> pragma Convention (C, B_Ptr_Conversion.Object_Pointer); >> is not legal. > If the Ada compiler uses the same type of addresses as the C >compiler there is no problem. But if you have a 64-bit Ada compiler and >a 32-bit C compiler (or vice-versa) it can't work. Presumably a 64 bit Ada compiler could be designed to work with a 32 bit C compiler, with pragma Convention(C, an_access_type) causing an_access_type to be a 32 bit pointer (with implied additional 32 bits from a segment or base or just zero, for instance) rather than a 64 bit pointer. Such a compiler ought to be able to do System.Address <-> access type conversions for 32 bit, as well as 64 bit, access types, but Ada's System.Address_To_Access_Conversions could only work for one of those, right? Perhaps the vendor of such a compiler would offer (non-standard) package System.Address_To_Access_Conversions.C for doing the (32 bit or convention C) conversions. ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: C array to ada record interface 2004-07-29 5:56 ` tmoran @ 2004-07-29 19:58 ` Robert I. Eachus 0 siblings, 0 replies; 13+ messages in thread From: Robert I. Eachus @ 2004-07-29 19:58 UTC (permalink / raw) tmoran@acm.org wrote: > Presumably a 64 bit Ada compiler could be designed to work with a 32 bit > C compiler, with pragma Convention(C, an_access_type) causing > an_access_type to be a 32 bit pointer (with implied additional 32 bits > from a segment or base or just zero, for instance) rather than a 64 bit > pointer. Such a compiler ought to be able to do System.Address <-> access > type conversions for 32 bit, as well as 64 bit, access types, but Ada's > System.Address_To_Access_Conversions could only work for one of those, > right? Perhaps the vendor of such a compiler would offer (non-standard) > package System.Address_To_Access_Conversions.C > for doing the (32 bit or convention C) conversions. Doesn't even have to be a non-standard mode. In theory you could validate a compiler in two modes that support different C compilers or different operating modes. Of course, a compiler that wants to support two different C calling conventions usually has two additional convention names, and probably a compiler switch that tells which one corresponds to convention C. The point I was trying to make was that which C compiler is chosen to bind to, and how it is chosen is outside the scope of the standard. So, in general, the code as written will work. But there is no implementation-independent way to guarantee it. -- Robert I. Eachus "The flames kindled on the Fourth of July, 1776, have spread over too much of the globe to be extinguished by the feeble engines of despotism; on the contrary, they will consume these engines and all who work them." -- Thomas Jefferson, 1821 ^ permalink raw reply [flat|nested] 13+ messages in thread
end of thread, other threads:[~2004-07-29 19:58 UTC | newest] Thread overview: 13+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2004-07-14 23:17 C array to ada record interface Francisco Javier Loma Daza 2004-07-15 0:36 ` Brian May 2004-07-15 1:23 ` Jeffrey Carter 2004-07-22 18:02 ` Francisco Javier Loma Daza 2004-07-24 18:48 ` Ludovic Brenta 2004-07-25 17:26 ` Francisco Javier Loma Daza 2004-07-25 19:28 ` tmoran 2004-07-26 21:42 ` Ludovic Brenta 2004-07-27 21:04 ` tmoran 2004-07-27 22:15 ` Martin Dowie 2004-07-28 2:42 ` Robert I. Eachus 2004-07-29 5:56 ` tmoran 2004-07-29 19:58 ` Robert I. Eachus
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox