home *** CD-ROM | disk | FTP | other *** search
/ Solo Programadores 22 / SOLO_22.iso / docs / lovelace / lesson16.les < prev    next >
Encoding:
Text File  |  1995-11-21  |  15.0 KB  |  373 lines

  1. <COMMENT This is a lesson file for the Lovelace Ada tutorial>
  2. <COMMENT A program called genlesson is used to transform this file into a set>
  3. <COMMENT of useful HTML files for use by Mosaic & other WWW browsers.>
  4.  
  5. <COMMENT  Edit the following lines. >
  6. <TUTOR NAME="Lovelace">
  7. <LESSON NUMBER=16>
  8. <AUTHOR NAME="David A. Wheeler" EMAIL="wheeler@ida.org">
  9. <AUTHOR ADDRESS="<A HREF="dwheeler.htm">David A. Wheeler (wheeler@ida.org)</A>">
  10. <COMMENT $Id$ >
  11.  
  12. <COMMENT  You'll probably want to uncomment and edit these lines: >
  13. <COMMENT  <PREVIOUS_LESSON LOCATION="URL_of_directory/" >
  14. <COMMENT  <NEXT_LESSON LOCATION="URL_of_directory/" >
  15.  
  16. <COMMENT A lesson is divided into 1 or more "sections".>
  17. <COMMENT Each section has a title; SECTION starts a new section.>
  18.  
  19. <SECTION NAME="General Information on Interfacing to Other Languages">
  20. Ada 95 provides a set of packages and some
  21. special pragmas to interface with other computer languages.
  22. The three most useful pragmas are called Import, Export, and Convention:
  23. <OL>
  24. <LI>Pragma import "imports" a subprogram from another ("foreign") language
  25. into an Ada program.
  26. Use pragma import if you want to call,
  27. for example, an existing C function.
  28. <LI>Pragma export "exports" an Ada subprogram to a "foreign" language.
  29. For example, if you've written an Ada procedure and want to call it from
  30. C, use pragma export.
  31. <LI>Pragma Convention specifies that a specified type should
  32. use the storage conventions of a given "foreign" language.
  33. It is also used on subprograms if they are "callback" subprograms
  34. (described below).
  35. </OL>
  36. <P>
  37. Here's an example of each:
  38. <P>
  39. <PRE>
  40.   pragma Import(C, getenv);  -- Use the C program getenv in my Ada program.
  41.   pragma Export(COBOL, Read_Sensor); -- Provide Ada procedure "Read_Sensor"
  42.                                      -- to the COBOL compiler.
  43.   pragma Convention(Fortran, State_Vector) -- Read and write State_Vector
  44.                                      -- using Fortran storage conventions
  45.                                      -- (e.g. column-major format)
  46. </PRE>
  47. <P>
  48. Here is the <A HREF="bnf.htm">BNF</A> for these pragmas:
  49. <PRE>
  50.   import_pragma ::= "pragma Import("
  51.                         [ "Convention =>" ] language ","
  52.                         [ "Entity =>" ] unit
  53.                         [ "," [ "Link_Name =>" ] link_name ]  ");"
  54.  
  55.   export_pragma ::= "pragma Export("
  56.                         [ "Convention =>" ] language ","
  57.                         [ "Entity =>" ] unit 
  58.                         [ "," [ "Link_Name =>" ] link_name ]  ");"
  59.  
  60.   convention_pragma ::= "pragma Convention("
  61.                         [ "Convention =>" ] language ","
  62.                         [ "Entity =>" ] unit ");"
  63. </PRE>
  64. <P>
  65. Ada compilers always support the Convention (language) Ada, naturally enough.
  66. Your Ada compiler probably also supports the languages C, Fortran,
  67. and possibly COBOL.
  68. GNAT supports C++ as the language name CPP, and you can also interface
  69. Ada and C++ programs by having both use the C convention to send
  70. information to each other.
  71. For assembly language modules, use the name of the high level language
  72. that the module's interface mimics.
  73. <P>
  74. The "Link_Name" parameter often isn't necessary, but it's useful in
  75. some circumstances, for example,
  76. if you need access to an object whose name has been "mangled"
  77. in a way the Ada compiler doesn't know about or if the name is not
  78. a legal Ada identifier (such as names with leading underscores).
  79. <P>
  80. "Callback" subprograms are subprograms which have access (pointer)
  81. values held in some external location and are then called later using
  82. that external value. If you have an Ada subprogram that will be called
  83. this way, use pragma Convention on both the subprogram and on the
  84. access type used.
  85. This is useful, for example, in dealing with the X window graphical
  86. user interface (GUI).
  87. <P>
  88. <COMMENT Should add a link to the Ada LRM from below>
  89. If the "main" subprogram is not in Ada, there is an additional
  90. issue to consider called "elaboration".
  91. The actual main subprogram should make sure that the environment
  92. for Ada is correctly set up.
  93. This is done automatically if the main subprogram is in Ada, but if
  94. it isn't, you have to do it yourself.
  95. The
  96. <A HREF="http://lglwww.epfl.ch/Ada/LRM/9X/rm9x/rm9x-B-01.html">Ada LRM
  97. section B.1(39)</A>
  98. suggests that compilers provide
  99. subprograms called "adainit" to start up the Ada environment and
  100. "adafinal" to clean it up after the Ada subprograms have stopped running.
  101. If you need to have a non-Ada main subprogram,
  102. check your compiler manual to see if
  103. it supports this and if there are any restrictions on what is and is
  104. not permitted.
  105.  
  106. <QUESTION Type=Multiple-Choice>
  107. You're writing an Ada program and want to directly
  108. call an existing C function
  109. called <EM>display</EM>. Which of the following pragmas should you use?
  110. <CHOICES>
  111. <CHOICE ANS=1>pragma Import(C, display);
  112. <CHOICE ANS=2>pragma Export(C, display);
  113. <CHOICE ANS=3>pragma Convention(C, display);
  114. </CHOICES>
  115. <ANSWER ANS=1>
  116. <RESPONSES>
  117. <WHEN ANS=1>
  118. Right.
  119. In addition to the pragma, you'd also need to tell Ada what
  120. display's parameters were, so the complete form would probably
  121. look something like this:
  122. <P>
  123. <PRE>
  124.   procedure display(Value : Integer);
  125.   pragma Import(C, display);
  126. </PRE>
  127. <P>
  128. I say "something like this" because we haven't talked about how
  129. to send data types between languages.
  130. Let's do that now for C, a very common language;
  131. handling data types for other languages is handled similarly.
  132. <WHEN ANS=2>
  133. No, sorry.
  134. Export would send an <EM>Ada</EM> subprogram out so that a <EM>C</EM>
  135. program could call it.
  136. <WHEN ANS=3>
  137. Close, but not quite.
  138. Convention would make it possible to use an Ada subprogram called
  139. display out to C so that C could call it back.
  140. Try again.
  141. </RESPONSES>
  142. <SECTION NAME="Interfacing with C">
  143. Since there are many useful utilities that can be called from C
  144. it's a good idea to know how to call them from Ada.
  145. This section assumes you know the C language to some basic level;
  146. if you don't know C you can skim this section.
  147. <P>
  148. First, here are some general rules on how Ada and C correspond, based on
  149. the
  150. <A HREF="http://lglwww.epfl.ch/Ada/LRM/9X/rm9x/rm9x-B-03.html">LRM B.3(63):</A>
  151. <OL>
  152. <LI>An Ada procedure corresponds to a void-returning C function.
  153. <LI>An Ada function corresponds to a non-void-returning C function.
  154. <LI>An Ada array corresponds to a C pointer to the first element.
  155. <LI>Simple scalar types (integers, floats, and access/pointer types) correspond
  156. to the obvious type in the other language.
  157. </OL>
  158. <P>
  159. Ada 95 provides a set of predefined packages that make it easier to
  160. interface with C.
  161. The primary package is named "Interfaces.C", which contains definitions
  162. for C types in Ada.
  163. These include C's types int, long, unsigned, and double.
  164. The C type float is called "C_float" in Ada so that it isn't
  165. confused with Ada's type Float (Ada Float and C float are probably identical,
  166. but that's not necessarily true).
  167. <P>
  168. The type "char_array" mimics C character arrays.
  169. Many C functions assume that character arrays are terminated with
  170. the special character "nul" (written in C as '\0').
  171. Since Ada strings aren't normally nul-terminated, functions
  172. To_C and To_Ada convert between Ada String types and C char_array types.
  173. <P>
  174. There are additional packages called Interfaces.C.Strings and
  175. Interfaces.C.Pointers that provide additional types and
  176. operations on C-style strings and C pointers.
  177. In particular, package "Interfaces.C.Strings" defines the type "chars_ptr",
  178. which corresponds to the typical C type "char*" when used to point to
  179. a C string (i.e. a pointer to an array of characters).
  180. The package also defines:
  181. <OL>
  182. <LI>constant <EM>Null_Ptr</EM>, which corresponds to C's <EM>(char*)NULL</EM>,
  183. <LI>procedure <EM>Free</EM>, which corresponds to C's <EM>free()</EM>, and
  184. <LI>function <EM>Value</EM>, which takes a chars_ptr and returns a
  185. normal Ada String. This function raises an exception Dereference_Error
  186. if passed a null pointer.
  187. </OL>
  188. <P>
  189. Let's work through a real-life example so you can see how this really works.
  190. This example is from
  191. <A HREF="http://wuarchive.wustl.edu/languages/ada/swcomps/cgi/cgi.html">"package
  192. CGI"</A>, an Ada binding to the World Wide Web
  193. Common Gateway Interface (CGI).
  194. Let's say that you want to get the value of an environment variable
  195. from the Operating System, and you want to get this value via a
  196. pre-existing C function that does this.
  197. In C this function is called "getenv" and it has the following C definition
  198. (see [Kernighan and Ritchie 1988, edition 2, page 253]):
  199. <P>
  200. <PRE>
  201.   char *getenv(char *name);
  202. </PRE>
  203. <P>
  204. This can be pretty straightforwardly translated into Ada as:
  205. <P>
  206. <PRE>
  207.   function getenv(Variable : chars_ptr) return chars_ptr;
  208.   pragma Import(C, getenv);
  209. </PRE>
  210. <P>
  211. That works, but it's inconvenient to have to keep translating
  212. values in and out of type "chars_ptr" in an Ada program.
  213. It's probably better to write a wrapper program that translates the Ada
  214. Strings to C strings (chars_ptr) and back for us.
  215. Let's define an Ada function to do that for us:
  216. <P>
  217. <PRE>
  218. with Interfaces.C.Strings; use Interfaces.C.Strings;
  219. -- ...
  220.  
  221.  function Get_Environment(Variable : String) return String is
  222.  -- Return the value of the given environment variable.
  223.  -- If there's no such environment variable, return an empty string.
  224.  
  225.    function getenv(Variable : chars_ptr) return chars_ptr;
  226.    pragma Import(C, getenv);
  227.    -- getenv is a standard C library function; see K&R 2, 1988, page 253.
  228.    -- it returns a pointer to the first character; do NOT free its results.
  229.  
  230.    Variable_In_C_Format : chars_ptr := New_String(Variable);
  231.    Result_Ptr : chars_ptr := getenv(Variable_In_C_Format);
  232.    Result : String := Value_Without_Exception(Result_Ptr);
  233.  
  234.  begin
  235.   Free(Variable_In_C_Format);
  236.   return Result;
  237.  end Get_Environment;
  238. </PRE>
  239. <P>
  240. Notice that a lot of string manipulation is happening in the declaration
  241. section.
  242. That's an easy way to get things done,
  243. because simple Ada Strings have a fixed length once they're declared.
  244. There's a call to some function called Value_Without_Exception;
  245. that's because normally an attempt to turn a C pointer into a string will
  246. raise an exception, and we just want to turn it into an empty string instead.
  247. That means we'll have to define such a function; here's a definition:
  248. <P>
  249. <PRE>
  250.  function Value_Without_Exception(S : chars_ptr) return String is
  251.  -- Translate S from a C-style char* into an Ada String.
  252.  -- If S is Null_Ptr, return "", don't raise an exception.
  253.  begin
  254.    if S = Null_Ptr then return "";
  255.     else return Value(S);
  256.    end if;
  257.  end Value_Without_Exception;
  258.  pragma Inline(Value_Without_Exception);
  259. </PRE>
  260. <P>
  261. Now we can easily get environment variables in Ada. For example, to get
  262. the value of environment variable REQUEST_METHOD, use:
  263. <P>
  264. <PRE>
  265.   Request_Method_Text : String := Get_Environment("REQUEST_METHOD");
  266. </PRE>
  267. <P>
  268. One thing we haven't covered are C <EM>struct</EM>s.
  269. Ada records and C structs clearly correspond, but how exactly should
  270. they correspond?
  271. The Ada LRM advises, but does not require, that
  272. Ada records always be passed to C as pointers to the beginning of the
  273. corresponding C struct.
  274. For those (relatively rare) cases where a C function expects to be passed
  275. a structure by value (a copy instead of the more common pointer-to-structure),
  276. you could create a new C function that converts a pointer into the
  277. actual structure and then call that new C function from Ada.
  278. However, this is simply advice, and
  279. the GNAT compiler does not follow this advice - instead, GNAT sends
  280. Ada records by value (copies).
  281. Both approaches are reasonable, but unfortunately they are different.
  282. The safest approach for passing Ada records is to always pass
  283. "access to record" values - since they are scalar, they are guaranteed
  284. to pass correctly in all Ada compilers.
  285.  
  286. <SECTION NAME="Ada Bindings">
  287. The previous material should help you develop a "binding" (interface)
  288. between software components, where one component is written in Ada
  289. and another component is written in another language.
  290. Naturally, it's easier if someone else or a tool
  291. does the job for you.
  292. <P>
  293. Before you can evaluate what someone else has done, you need to
  294. understand the major types of bindings between an Ada program and another
  295. program.
  296. These types are called "direct" and "abstract":
  297. <P>
  298. <UL>
  299. <LI>A "direct" (also called "thin") binding
  300. provides a one-to-one mapping to Ada
  301. of whatever interface the foreign program provides.
  302. Direct bindings are easy to understand if you understand the foreign
  303. program's interface, and direct bindings for Ada are easy to create.
  304. In particular, you can use the existing documentation, which is a very
  305. important advantage for complex interfaces (like windowing systems).
  306. Unfortunately, direct bindings are often a little clumsy to work with and
  307. often don't provide the protection usually provided by Ada interfaces.
  308. Thus, it's often nicer to work with "abstract" bindings.
  309. <LI>An "abstract" (also called "thick") binding provide a more
  310. abstract, Ada-like view of the foreign program.
  311. Unfortunately, while "abstract" bindings are nicer to work with, it takes
  312. work and time to create the right abstractions.
  313. Thus abstract bindings are harder to create.
  314. </UL>
  315. <P>
  316. Here are some other things you need to know about bindings:
  317. <UL>
  318. <LI>"Direct" and "abstract" are really extremes on a continuum;
  319. there are bindings that are "mostly direct" but have been abstracted a
  320. little, and there are "abstract" bindings that have some direct
  321. one-to-one mappings.
  322. <LI>The terms "thick" and "thin" have other
  323. related meanings (involving how a standard is written),
  324. which is why I've used the terms "direct" and "abstract" here.
  325. </UL>
  326. <P>
  327. Now that you understand these basic issues, you can go hunt for
  328. ways to make this interfacing job easier.
  329. <A HREF="ftp://sw-eng.falls-church.va.us/public/AdaIC/tools/bindings/">The
  330. Ada Information Clearinghouse maintains a document listing existing
  331. Ada bindings for other products and standards.</A>
  332. Their list is incomplete, but it's a good starting point, especially
  333. for common products or standards such as POSIX, X windows, Microsoft Windows,
  334. or SQL databases.
  335. If you're interfacing with a commercial product, ask the vendor
  336. to supply you with an Ada interface.
  337. You could also post a request to
  338. <A HREF="news:comp.lang.ada">comp.lang.ada</A>
  339. if you can't find what you're looking for.
  340. <P>
  341. There are also tools to automatically generate direct (thin)
  342. Ada bindings to C libraries.
  343. Here are two tools (there are others as well):
  344. <OL>
  345. <LI>Cbind translates C declarations and C preprocessor definitions
  346. into Ada package(s).
  347. Its strength is in ease-of-use; just type:
  348. <PRE>
  349.    "cbind file.h > file.ads".
  350. </PRE>
  351. Cbind is available via
  352. <A HREF="ftp://rational.com/public/tools/cbind">Rational</A>
  353. and
  354. <A HREF="http://www.cdrom.com/pub/ada/swtools/cbind">Walnut Creek.</A>
  355. <P>
  356. <LI><A HREF="ftp://cs.nyu.edu/pub/gnat/contrib/forest/">CtoAda
  357. translates declarations from C to Ada.</A>
  358. CtoAda's strength is that it provides many "hooks" to allow a programmer
  359. to control the translation.
  360. This gives more control at the expense
  361. of requiring more work by the programmer.
  362. </OL>
  363.  
  364. <QUESTION Type=Multiple-Choice>
  365. If you want to quickly create a binding to another language
  366. and don't mind that it might be a little clumsy to use,
  367. what kind of binding would you create?
  368. <CHOICES>
  369. <CHOICE ANS=1>Direct ("thin") binding
  370. <CHOICE ANS=2>Abstract ("thick") binding
  371. </CHOICES>
  372. <ANSWER ANS=1>
  373.