home *** CD-ROM | disk | FTP | other *** search
/ Power GUI Programming with VisualAge C++ / powergui.iso / trialva / ibmcppw / help / cppwsomg.inf (.txt) < prev    next >
Encoding:
OS/2 Help File  |  1996-02-16  |  643.6 KB  |  18,974 lines

  1.  
  2. ΓòÉΓòÉΓòÉ 1. About This Book ΓòÉΓòÉΓòÉ
  3.  
  4. Before you begin to use this information, it would be helpful to understand how 
  5. to navigate through it. You can use the Table of Contents and Index facility to 
  6. locate topics and the Search facility to search the text of this document. You 
  7. can use hypertext links to acquire related information on the current topic. 
  8. Hypertext links appear in a different color. For example, here is a link to 
  9. another panel: Communicating Your Comments to IBM. By double-clicking on the 
  10. text of the link or by pressing Enter on a highlighted link, you will open a 
  11. panel of related information. When you open a panel, the first link has the 
  12. focus; to shift the focus to other links, use the Tab key. 
  13.  
  14. You should also understand: 
  15.  
  16.      How to Use the Contents 
  17.      How to Obtain Additional Information 
  18.      How to Use Menu Bar Choices 
  19.      How to Cut and Paste Examples 
  20.  
  21.  
  22. ΓòÉΓòÉΓòÉ 1.1. Notices ΓòÉΓòÉΓòÉ
  23.  
  24. (C) Copyright International Business Machines Corporation, 1995, 1996. All 
  25. rights reserved. 
  26.  
  27. Note to U.S. Government Users - Documentation related to restricted rights - 
  28. Use, duplication, or disclosure is subject to restrictions set forth in GSA ADP 
  29. Schedule Contract with IBM Corp. 
  30.  
  31. This edition applies to Version 3.5 of IBM VisualAge for C++ for Windows 
  32. (33H4979, 33H4980) and to all subsequent releases and modifications until 
  33. otherwise indicated in new editions.  Make sure you are using the correct 
  34. edition for the level of the product. 
  35.  
  36. This publication could include technical inaccuracies or typographical errors. 
  37. Changes are periodically made to the information herein; any such changes will 
  38. be reported in subsequent revisions. 
  39.  
  40. Requests for publications and for technical information about IBM products 
  41. should be made to your IBM Authorized Dealer or your IBM Marketing 
  42. Representative. 
  43.  
  44. When you send information to IBM, you grant IBM a nonexclusive right to use or 
  45. distribute the information in any ways it believes appropriate without 
  46. incurring any obligation to you. 
  47.  
  48. Any reference to an IBM licensed program in this publication is not intended to 
  49. state or imply that only IBM's licensed program may be used. Any functionally 
  50. equivalent product, program, or service that does not infringe any of IBM's 
  51. intellectual property rights may be used instead of the IBM product, program, 
  52. or service. Evaluation and verification of operation in conjunction with other 
  53. products, except  those expressly designated by IBM, is the user's 
  54. responsibility. 
  55.  
  56. IBM may have patents or pending patent applications covering subject matter in 
  57. this document.  The furnishing of this document does not give you any license 
  58. to these patents.  You can send license inquiries, in writing, to the IBM 
  59. Director of Licensing, IBM Corporation, 500 Columbus Avenue, Thornwood, NY, 
  60. 10594, USA. 
  61.  
  62. Licensees of this program who wish to have information about it for the purpose 
  63. of enabling: (i) the exchange of information between independent created 
  64. programs and other programs (including this one) and (ii) the mutual use of the 
  65. information which has been exchanged, should contact IBM Canada Ltd., 
  66. Department 071, 1150 Eglinton Avenue East, North York, Ontario M3C 1H7, Canada. 
  67. Such information may be available, subject to appropriate terms and conditions, 
  68. including in some cases payment of a fee. 
  69.  
  70. This publication contains examples of data and reports used in daily business 
  71. operations. To illustrate them as completely as possible, the examples include 
  72. the names of individuals, companies, brands, and products. All of these names 
  73. are fictitious and any similarity to the names and addresses used by an actual 
  74. business enterprise is entirely coincidental. 
  75.  
  76.  
  77. ΓòÉΓòÉΓòÉ 1.2. Trademarks and Service Marks ΓòÉΓòÉΓòÉ
  78.  
  79. The following terms used in this publication are trademarks or service marks of 
  80. IBM Corporation in the United States or other countries: 
  81.  
  82.       AIX 
  83.       IBM 
  84.       IBMLink 
  85.       OS/2 
  86.       SOMobjects 
  87.       System Object Model 
  88.       VisualAge 
  89.  
  90.  Windows is a trademark of Microsoft Corporation. 
  91.  
  92.  Other company, product, and service names, which may be denoted by a double 
  93.  asterisk(**), may be trademarks or service marks of others. 
  94.  
  95.  IBM's VisualAge products and services are not associated with or sponsored by 
  96.  Visual Edge Software, Ltd.. 
  97.  
  98.  
  99. ΓòÉΓòÉΓòÉ 1.3. How to Use the Contents ΓòÉΓòÉΓòÉ
  100.  
  101. When the Contents window first appears, some topics have a plus (+) sign beside 
  102. them. The plus sign indicates that additional topics are available. 
  103.  
  104. To expand the Contents if you are using a mouse, click on the plus sign. If you 
  105. are using the keyboard, use the Up or Down Arrow key to highlight the topic, 
  106. and press the Plus (+) key. For example, How to Use the Contents has a plus 
  107. sign beside it.  To see additional topics for that heading, click on the plus 
  108. sign or highlight that topic and press the Plus (+) key. 
  109.  
  110. To view a topic, double-click on the topic (or press the Up or Down Arrow key 
  111. to highlight the topic, and then press the Enter key). 
  112.  
  113.  
  114. ΓòÉΓòÉΓòÉ 1.4. How to Obtain Additional Information ΓòÉΓòÉΓòÉ
  115.  
  116. After you select a topic, the information for that topic appears in a window. 
  117. Highlighted words or phrases indicate that additional information is available. 
  118. Certain words and phrases are highlighted in a different color from the 
  119. surrounding text. These are called hypertext terms. 
  120.  
  121. If you are using a mouse, double-click on the highlighted word.  If you are 
  122. using a keyboard, press the Tab key to move to the highlighted word, and then 
  123. press the Enter key.  Additional information then appears in a window. 
  124.  
  125.  
  126. ΓòÉΓòÉΓòÉ 1.5. How to Use Menu Bar Choices ΓòÉΓòÉΓòÉ
  127.  
  128. Several choices are available for managing the information presented in this 
  129. document. There are three choices on the menu bar: the Services menu, the 
  130. Options menu, and the Help menu. 
  131.  
  132. Use the Services menu to operate the active window currently displayed on the 
  133. screen. Available actions include the following: 
  134.  
  135.  Placing Bookmarks 
  136.    You can set a placeholder so you can retrieve information of interest to 
  137.    you. 
  138.  
  139.  Searching for Information 
  140.    You can find occurrences of a word or phrase in the current topic, selected 
  141.    topics, or all topics. 
  142.  
  143.  Printing Information 
  144.    You can print one or more topics. You can also print a set of topics by 
  145.    first marking the topics in the Contents list. 
  146.  
  147.  Copying Information to a File 
  148.    You can copy a topic that you are viewing to the System Clipboard or to a 
  149.    file that you can edit. This method is particularly useful for copying 
  150.    syntax definitions and program samples into the application that you are 
  151.    developing. 
  152.  
  153.  Select actions from the Options menu, to change the way your Contents list is 
  154.  displayed. To expand the Contents and show all levels for all topics, choose 
  155.  Expand all from the Options pull-down. You can also press the Ctrl, Shift, and 
  156.  * keys together. 
  157.  
  158.  You can select various types of help information from the Help menu. 
  159.  
  160.  For information about any of the menu choices, highlight the choice in the 
  161.  menu and press F1. 
  162.  
  163.  
  164. ΓòÉΓòÉΓòÉ 1.5.1. Placing Bookmarks ΓòÉΓòÉΓòÉ
  165.  
  166. When you place a bookmark on a topic, it is added to a list of bookmarks you 
  167. have previously set.  You can view the list, and you can remove one or all 
  168. bookmarks from the list.  If you have not set any bookmarks, the list is empty. 
  169.  
  170. To set a bookmark, do the following: 
  171.  
  172.    1. Select a topic from the Contents. 
  173.    2. When that topic appears, select the Bookmark option from the Services 
  174.       menu. 
  175.    3. If you want to change the name used for the bookmark, type the new name 
  176.       in the field. 
  177.    4. Click on the Place radio button (or press the Up or Down Arrow key to 
  178.       select it). 
  179.    5. Click on OK (or select it and press Enter). The bookmark is then added to 
  180.       the bookmark list. 
  181.  
  182.  
  183. ΓòÉΓòÉΓòÉ 1.5.2. Searching for Information ΓòÉΓòÉΓòÉ
  184.  
  185. You can specify a word or phrase to be searched.  You can also limit the search 
  186. to a set of topics by first marking the topics in the Contents list. 
  187.  
  188. To search for a word or phrase in all topics, do the following: 
  189.  
  190.    1. Select the Search option from the Services menu. 
  191.    2. Type the word or words to be searched for. 
  192.    3. Click on All sections (or press the Up or Down Arrow keys to select it). 
  193.    4. Click on Search (or select it and press Enter) to begin the search. 
  194.    5. The list of topics where the word or phrase appears is displayed. 
  195.  
  196.  
  197. ΓòÉΓòÉΓòÉ 1.5.3. Printing Information ΓòÉΓòÉΓòÉ
  198.  
  199. You can print one or more topics, the index, or the table of contents.  Make 
  200. sure that your printer is connected to the serial port, configured correctly, 
  201. and ready for input. To print: 
  202.  
  203.    1. Select Print from the Services pull-down menu. 
  204.    2. Select what you want to print. Note that the This section and Marked 
  205.       sections choices are only available if you are viewing a topic or if you 
  206.       have marked topics, respectively.  To mark topics in the table of 
  207.       contents, press the Ctrl key and click on the topics, or use the arrow 
  208.       keys. 
  209.    3. Select Print to print what you've chosen. 
  210.  
  211.  
  212. ΓòÉΓòÉΓòÉ 1.5.4. Copying Information to a File ΓòÉΓòÉΓòÉ
  213.  
  214. You can copy a topic that you are viewing in two ways: 
  215.  
  216.      Copy copies the topic that you are viewing into the System Clipboard. 
  217.  
  218.      Copy to file copies the topic that you are viewing into a temporary file 
  219.       named text.tmp.  You can later edit that file by using any editor. The 
  220.       text.tmp file is placed in the directory where your viewable document 
  221.       resides. This copy function does not apply if you are viewing the 
  222.       document from the CD-ROM. 
  223.  
  224.  To copy a topic, do the following: 
  225.  
  226.    1. Expand the Contents list and select a topic. 
  227.    2. When the topic appears, select Copy to file from the Services menu. 
  228.    3. The system puts the text pertaining to that topic into the temporary file 
  229.       text.tmp. 
  230.  
  231.  
  232. ΓòÉΓòÉΓòÉ 1.6. How to Cut and Paste Examples ΓòÉΓòÉΓòÉ
  233.  
  234. You can copy examples (or information) from this reference/guide/book to 
  235. compile, link, and run them, or to paste them into your own code. 
  236.  
  237. To copy an example or information: 
  238.  
  239.    1. Make the topic you want to copy the active window. 
  240.  
  241.    2. From the Services menu, select Copy to file. The text in that topic is 
  242.       placed in the temporary file text.tmp, in the same directory as this 
  243.       reference. This copy function does not apply if you are viewing the 
  244.       document from the CD-ROM. 
  245.  
  246.    3. You can then modify or use text.tmp as you want. 
  247.  
  248.  Note:  Because the system copies the entire contents of the topic to the file, 
  249.  you may need to edit it to remove additional text. Most examples in this 
  250.  reference are ready to compile, link, and run as they appear, and do not 
  251.  require any editing. 
  252.  
  253.  
  254. ΓòÉΓòÉΓòÉ 1.7. Other Information You Might Find Helpful ΓòÉΓòÉΓòÉ
  255.  
  256. This product provides a number of online guides and references that we hope 
  257. you'll find helpful as you develop applications. This information includes 
  258. User's Guides, References, and How Do I help that gives you specific 
  259. instructions for performing common tasks. You can get to this online 
  260. information from the Information folder inside the main product folder.  You 
  261. can also get to it from the Help menu in any of the components of the product. 
  262.  
  263.  
  264. ΓòÉΓòÉΓòÉ 1.8. Communicating Your Comments to IBM ΓòÉΓòÉΓòÉ
  265.  
  266. If there is something you like, or dislike, about this book, please let us 
  267. know.  You can use one of the methods listed below to send your comments to 
  268. IBM.  Please be sure to include the complete title of the publication that you 
  269. are commenting on. 
  270.  
  271. The comments you send should only pertain to the information in this document 
  272. and its presentation.  To request additional publications or to ask questions 
  273. or make comments about the functions of IBM products or systems, you should 
  274. talk to your IBM representative or your authorized IBM remarketer. 
  275.  
  276. When you send comments to IBM, you grant IBM a nonexclusive right to use or 
  277. distribute your comments in any way it believes appropriate without incurring 
  278. any obligation to you. 
  279.  
  280. You can send your comments to IBM in the following ways: 
  281.  
  282.      By mail to the following address: 
  283.  
  284.             IBM Canada Ltd. Laboratory
  285.             Information Development
  286.             2G/345/1150/TOR
  287.             1150 EGLINTON AVENUE EAST
  288.             NORTH YORK, ONTARIO
  289.             CANADA M3C 1H7
  290.  
  291.      By FAX to the following number: 
  292.  
  293.         -  United States and Canada: (416) 448-6161 
  294.         -  Other countries (+1) 416-448-6161 
  295.  
  296.      By electronic mail to one of the following IDs.  Be sure to include your 
  297.       entire network address if you wish to get a reply. 
  298.  
  299.         -  Internet: torrcf@vnet.ibm.com 
  300.         -  IBMLink: toribm(torrcf) 
  301.         -  IBM/PROFS: torolab4(torrcf) 
  302.         -  IBMMAIL: ibmmail(caibmwt9) 
  303.  
  304.  
  305. ΓòÉΓòÉΓòÉ 2. Introduction to the SOMobjects Developer Toolkit ΓòÉΓòÉΓòÉ
  306.  
  307. This section contains: 
  308.  
  309.      Background 
  310.      Introducing SOM and the SOMobjects Toolkit 
  311.      What's New in SOMobjects Version 2.1 
  312.      Overview of this book 
  313.  
  314.  
  315. ΓòÉΓòÉΓòÉ 2.1. Background ΓòÉΓòÉΓòÉ
  316.  
  317. Object-oriented programming(OOP) is an important new programming technology 
  318. that offers expanded opportunities for software reuse and extensibility. 
  319. Object-oriented programming shifts the emphasis of software development away 
  320. from functional decomposition and toward the recognition of units (called 
  321. objects) that encapsulate both code and data.  As a result, programs become 
  322. easier to maintain and enhance. Object-oriented programs are typically more 
  323. impervious to the ripple effects of subsequent design changes than their 
  324. non-object-oriented counterparts. This, in turn, leads to improvements in 
  325. programmer productivity. 
  326.  
  327. Despite its promise, penetration of object-oriented technology to major 
  328. commercial software products has progressed slowly because of certain 
  329. obstacles.  This is particularly true of products that offer only a binary 
  330. programming interface to their internal object classes (Example: products that 
  331. do not allow access to source code). 
  332.  
  333. The first obstacle that developers must confront is the choice of an 
  334. object-oriented programming language. 
  335.  
  336. So-called pure object-oriented language (such as Smalltalk) presume a complete 
  337. run-time environment (sometimes known as a virtual machine), because their 
  338. semantics represent a major departure from traditional, procedure-oriented 
  339. system architectures.  So long as the developer works within the supplied 
  340. environment, everything works smoothly and consistently.  When the need arises 
  341. to interact with foreign environment, however (for example, to make an external 
  342. procedure call), the pure-object paradigm ends, and objects must be reduced to 
  343. data structures for external manipulation.  Unfortunately, data structures do 
  344. not retain the advantage that objects offer with regard to encapsulation and 
  345. code reuse. 
  346.  
  347. Hybrid languages such as C++ on the other hand, require less run-time support, 
  348. but sometimes result in tight bindings between programs that implement objects 
  349. (called "class libraries") and their clients (the programs that use them). That 
  350. is, implementation detail is often unavoidably compiled into the client 
  351. programs.  Tight binding between class libraries and their clients means that 
  352. client programs often must be recompiled whenever simple changes are made in 
  353. the library.  Furthermore, no binary standard exists for C++ objects, so the 
  354. C++ class libraries produced by one C++ compiler cannot (in general) be used 
  355. from C++ programs built with a different C++ compiler. 
  356.  
  357. The second obstacle developers of object-oriented software must confront is 
  358. that, because different object-oriented languages and toolkits embrace 
  359. incompatible models of what objects are and how they work, software developed 
  360. using a particular language or toolkit is naturally limited in scope.  Classes 
  361. implemented in one language cannot be readily used from another.  A C++ 
  362. programmer, for example, cannot easily use classes developed in Smalltalk, nor 
  363. can a Smalltalk programmer make effective use of C++ classes. Object-oriented 
  364. language and toolkit boundaries become, in effect, barriers to 
  365. interoperability. 
  366.  
  367. Ironically, no such barrier exists for ordinary procedure libraries. Software 
  368. developers routinely construct procedure libraries that can be shared across a 
  369. variety of languages, by adhering to standard linkage conventions. 
  370. Object-oriented class libraries are inherently different in that no binary 
  371. standards or conventions exist to derive a new class from an existing one,  or 
  372. even to invoke a method in a standard way.  Procedure libraries also have the 
  373. benefit that their implementations can be freely changed without requiring 
  374. client programs to be recompiled, unlike the situation for C++ class libraries. 
  375.  
  376. For developers who need to provide binary class libraries, these are serious 
  377. obstacles. In an era of open systems and heterogeneous networking, a 
  378. single-language solution is frequently not broad enough.  Certainly, mandating 
  379. a specific compiler from a specific vendor in order to use a class library 
  380. might be grounds not to include the class library with an operating system or 
  381. other general-purpose product. 
  382.  
  383. The System Objects Model (SOM) is IBM's solution to these problems. 
  384.  
  385.  
  386. ΓòÉΓòÉΓòÉ 2.2. Introducing SOM and the SOMobjects Toolkit ΓòÉΓòÉΓòÉ
  387.  
  388. The System Object Model (SOM) is a new object-oriented programming technology 
  389. for building, packaging, and manipulating binary class libraries. 
  390.  
  391.      With SOM, class implementers describe the interface for a class of 
  392.       objects (names of the methods it supports, the return types, parameter 
  393.       types, and so forth) in a standard language called the Interface 
  394.       Definition Language (IDL). 
  395.  
  396.      They then implement methods in their preferred programming language 
  397.       (which may be either an object-oriented programming language or a 
  398.       procedural language such as C). 
  399.  
  400.  This means that programmers can begin using SOM quickly, and also extends the 
  401.  advantages of OOP to programmers who use non-object-oriented programming 
  402.  languages. 
  403.  
  404.  A principal benefit of using SOM is that SOM accommodates changes in 
  405.  implementation details and even in certain facets of a class ' interface, 
  406.  without breaking the binary interface to a class library and without requiring 
  407.  recompilation of client programs.  As a rule of thumb , if changes to a SOM 
  408.  class do not require source-code changes in client programs, then those client 
  409.  programs will not need to be recompiled. This is not true of many 
  410.  object-oriented languages, and it is one of the chief benefits of using SOM. 
  411.  For instance, SOM classes can undergo structural changes such as the 
  412.  following, yet retain full backward, binary compatibility: 
  413.  
  414.      Adding new methods, 
  415.  
  416.      Changing the size of an object by adding or deleting instance variables, 
  417.  
  418.      Inserting new parent (base) classes above a class in the inheritance 
  419.       hierarchy, and 
  420.  
  421.      Relocating methods upward in the class hierarchy. 
  422.  
  423.  In short, implementers can make the typical kinds of changes to an 
  424.  implementation and its interfaces that evolving software systems experience 
  425.  over time. 
  426.  
  427.  Unlike the object models found in formal object-oriented programming 
  428.  languages, SOM is language-neutral.  It preserves the key OOP characteristics 
  429.  of encapsulation, inheritance, and polymorphism, without requiring that the 
  430.  user of a SOM class and the implementer of a SOM class use the same 
  431.  programming language.  SOM is said to be language-neutral for four reasons: 
  432.  
  433.    1. All SOM interactions consist of standard procedure calls. On systems that 
  434.       have a standard linkage convention for system calls, SOM interactions 
  435.       conform to those conventions. Thus, most programming languages that can 
  436.       make external procedure calls can use SOM. 
  437.  
  438.    2. The form of the SOM Application Programming Interface, or API (the way 
  439.       that programmers invoke methods, create objects, and so on) can vary 
  440.       widely from language to language, as a benefit of the SOM bindings. 
  441.       Bindings are a set of macros and procedure calls that make implementing 
  442.       and using SOM classes more convenient by tailoring the interface to a 
  443.       particular programming language. 
  444.  
  445.    3. SOM supports several mechanisms for method resolution that can be readily 
  446.       mapped into the semantics of a wide range of object-oriented programming 
  447.       languages. Thus, SOM class libraries can be shared across object-oriented 
  448.       languages that have differing object models.  A SOM object can 
  449.       potentially be accessed with three different forms of method resolution: 
  450.  
  451.           Offset resolution: roughly equivalent to the C++ virtual function 
  452.            concept. Offset resolution implies a static scheme for typing 
  453.            objects, with polymorphism based strictly on class derivation.  It 
  454.            offers the best performance characteristics for SOM method 
  455.            resolution.  Methods accessible through offset resolution are called 
  456.            static methods, because they are considered a fixed aspect of an 
  457.            object's interface. 
  458.  
  459.           Name-lookup resolution: similar to that employed by Objective-C and 
  460.            Smalltalk.  Name resolution supports untyped (sometimes called 
  461.            dynamically typed) access to objects, with polymorphism based on the 
  462.            actual protocols that objects honor. Name resolution offers the 
  463.            opportunity to write code to manipulate objects with little or no 
  464.            awareness of the type or shape of the object when the code is 
  465.            compiled. 
  466.  
  467.           Dispatch-function resolution: a unique feature of SOM that permits 
  468.            method resolution based on arbitrary rules known only in the domain 
  469.            of the receiving object. Languages that require special entry or 
  470.            exit sequences or local objects that represent distributed object 
  471.            domains are good candidates for using dispatch-function resolution. 
  472.            This technique offers the highest degree of encapsulation for the 
  473.            implementation of an object, with some cost in performance. 
  474.  
  475.    4. SOM conforms fully with the Object Management Group's (OMG) Common Object 
  476.       Request Broker Architecture (CORBA) standards. (OMG is an industry 
  477.       consortium founded to advance the use of object technology in 
  478.       distributed, heterogeneous environments.) In particular, 
  479.  
  480.           Interface to SOM classes are described in CORBA's Interface 
  481.            Definition Language, IDL, and the entire SOMobjects Toolkit supports 
  482.            all CORBA-defined data types. 
  483.  
  484.           The SOM bindings for the C language are compatible with the C 
  485.            bindings prescribed by CORBA. 
  486.  
  487.           All information about the interface to a SOM class is available at 
  488.            run time through a CORBA-defined Interface Repository. 
  489.  
  490.  SOM is not intended to replace existing object-oriented languages. Rather, it 
  491.  is intended to complement them so that application programs written in 
  492.  different programming languages can share common SOM class libraries. For 
  493.  example, SOM can be used with C++ to do the following: 
  494.  
  495.      Provide upwardly compatible class libraries, so that when a new version 
  496.       of a SOM class is released, client code needn't be recompiled, so long as 
  497.       no changes to the client's source code are required. 
  498.  
  499.      Allow other language users (and other C++ compiler users) to use SOM 
  500.       classes implemented in C++. 
  501.  
  502.      Allow C++ programs to use SOM classes implemented using other languages. 
  503.  
  504.      Allow other language users to implement SOM classes derived from SOM 
  505.       classes implemented in C++. 
  506.  
  507.      Allow C++ programmers to implement SOM classes derived from SOM classes 
  508.       implemented using other languages. 
  509.  
  510.      Allow encapsulation (implementation hiding) so that SOM class libraries 
  511.       can be shared without exposing private instance variables and methods. 
  512.  
  513.      Allow dynamic (run-time) method resolution in addition to static 
  514.       (compile-time) method resolution (on SOM objects). 
  515.  
  516.      Allow information about classes to be obtained and updated at run time. 
  517.       (C++ classes are compile-time structures that have no properties at run 
  518.       time.) 
  519.  
  520.  
  521. ΓòÉΓòÉΓòÉ 2.2.1. The SOM Compiler ΓòÉΓòÉΓòÉ
  522.  
  523. The SOMobjects Toolkit contains a tool called the SOM Compiler that enables 
  524. implementers to build classes in which interface and implementation are 
  525. decoupled. The SOM Compiler reads the IDL definition of a class interface and 
  526. generates: 
  527.  
  528.      an implementation skeleton for the class, 
  529.  
  530.      bindings for implementers, and 
  531.  
  532.      bindings for client programs. 
  533.  
  534.  Bindings are language-specific macros and procedures that make implementing 
  535.  and using SOM classes more convenient. These bindings offer a convenient 
  536.  interface to SOM that is tailored to a particular programming language.  For 
  537.  instance, C programmers can invoke methods in the same way they make ordinary 
  538.  procedure calls. The C++ bindings wrap SOM objects as C++ objects, so that C++ 
  539.  programmers can invoke methods on SOM objects in the same way they invoke 
  540.  methods on C++ objects. In addition, SOM objects receive full C++ 
  541.  typechecking, just as C++ objects do.  Currently, the SOM Compiler can 
  542.  generate both C and C++ language bindings for a class. The C and C++ bindings 
  543.  will work with a variety of commercial products available from IBM and others. 
  544.  Vendors of other programming languages may also offer SOM bindings.  Check 
  545.  with your language vendor about possible SOM support. 
  546.  
  547.  
  548. ΓòÉΓòÉΓòÉ 2.2.2. The SOM Run-Time Library ΓòÉΓòÉΓòÉ
  549.  
  550. In addition to the SOM Compiler, SOM includes a run-time library. This library 
  551. provides, among other things, a set of classes, methods, and procedures used to 
  552. create object and invoke methods on them.  The library allows any programming 
  553. language to use SOM classes (classes developed using SOM) if that language can: 
  554.  
  555.      Call external procedures, 
  556.  
  557.      Store a pointer to a procedure and subsequently invoke that procedure, 
  558.       and 
  559.  
  560.      Map IDL types onto the programming language's native types. 
  561.  
  562.  Thus, the user of a SOM class and the implementer of a SOM class needn't use 
  563.  the same programming language, and neither is required to use an 
  564.  object-oriented language.  The independence of client language and 
  565.  implementation language also extends to subclassing: a SOM class can be 
  566.  derived from other SOM classes, and the subclass may or may not be implemented 
  567.  in the same language as the parent class(es). Moreover, SOM's run-time 
  568.  environment allows applications to access information about classes 
  569.  dynamically (at run time). 
  570.  
  571.  
  572. ΓòÉΓòÉΓòÉ 2.2.3. Frameworks in the SOMobjects Toolkit ΓòÉΓòÉΓòÉ
  573.  
  574. In addition to SOM itself (the SOM compiler and the SOM run-time library), the 
  575. SOMobjects Developer Toolkit also provides a set of frameworks (class 
  576. libraries) that can be used in developing object-oriented applications.  These 
  577. include Distributed SOM, the Interface Repository Framework, and the Emitter 
  578. Framework, and the Metaclass Framework, described below. 
  579.  
  580. Note:  The SOMobjects Base Toolkit, the core version of SOMobject shipped with 
  581.        this documentation, contains only Distributed SOM, the Interface 
  582.        Repository, and the Metaclass frameworks. The complete SOMobjects 
  583.        Developer Toolkit can be ordered from IBM by calling 1-800-342-6672 in 
  584.        the U.S. or 1-800-465-7999 in Canada. The part number is 10H9767 for the 
  585.        CD-ROM containing SOMobjects for the AIX, OS/2,and Windows 3.x platforms 
  586.        (including online documentation). SOMobjects manuals are available 
  587.        individually. 
  588.  
  589.  
  590. ΓòÉΓòÉΓòÉ 2.2.3.1. Distributed SOM ΓòÉΓòÉΓòÉ
  591.  
  592. Distributed SOM (DSOM) allows application programs to access SOM objects across 
  593. address spaces. That is, application programs can access objects in other 
  594. processes. The location and implementation of the object are hidden from the 
  595. client, and the client accesses the object as if local.  The current release of 
  596. DSOM supports distribution of objects among processes within a workstation. 
  597.  
  598.  
  599. ΓòÉΓòÉΓòÉ 2.2.3.2. Interface Repository Framework ΓòÉΓòÉΓòÉ
  600.  
  601. The Interface Repository is a database, optionally created and maintained by 
  602. the SOM Compiler, that holds all the information contained in the IDL 
  603. description of a class of objects. The Interface Repository Framework consists 
  604. of the 11 classes defined in the CORBA standard for accessing the Interface 
  605. Repository. Thus, the Interface Repository Framework provides run-time access 
  606. to all information contained in the IDL description of a class of objects. Type 
  607. information is available as TypeCodes-a CORBA-defined way of encoding the 
  608. complete description of any data type that can be constructed in IDL. 
  609.  
  610.  
  611. ΓòÉΓòÉΓòÉ 2.2.3.3. Metaclass Framework ΓòÉΓòÉΓòÉ
  612.  
  613. Finally, the Metaclass Framework is a collection of SOM metaclasses that 
  614. provide functionality that can be useful to SOM class designers for modifying 
  615. the default semantics of method invocation and object creation. These 
  616. metaclasses are described in The Metaclass Framework. 
  617.  
  618.  
  619. ΓòÉΓòÉΓòÉ 2.3. What's New in SOMobjects Version 2.1 ΓòÉΓòÉΓòÉ
  620.  
  621. Version 2.1 of the SOMobjects Developer Toolkit provides enhanced capabilities 
  622. and improved performance for both SOM and DSOM. In addition, the Toolkit now 
  623. includes support for DirectToSOM (DTS) C++ compilers. New metaclasses in the 
  624. Metaclass Framework allow class implementors to define classes that 
  625. automatically possess certain convenience facilities. 
  626.  
  627. The enhancements provided with SOMobjects Version 2.1 are described in detail 
  628. in the following sections. 
  629.  
  630.  
  631. ΓòÉΓòÉΓòÉ 2.3.1. General Enhancements ΓòÉΓòÉΓòÉ
  632.  
  633. C++ programmers can use DirectToSOM (DTS) C++ compilers (available from 
  634. independent software vendors) as an alternative to the SOMobjects Toolkit's C++ 
  635. bindings. (A DTS C++ compiler uses SOM classes to implement C++ objects.) The 
  636. support provided by SOMobjects for DTS C++ consists of various enhancements to 
  637. the SOM API (useful to SOM programmers in general), and a new emitter that 
  638. produces DTS C++ header files corresponding to SOM IDL. DTS C++ programs 
  639. include ".hh" header files, which are emitted as described in Generating 
  640. binding files. 
  641.  
  642.  
  643. ΓòÉΓòÉΓòÉ 2.3.2. SOMobjects Enhancements ΓòÉΓòÉΓòÉ
  644.  
  645. A new default process enables SOMobjects to initialize and destroy objects more 
  646. efficiently (using the somDefaultInit and somDestruct methods). 
  647.  
  648. A new kind of method is supported, nonstatic, that is similar to a C++ 
  649. nonstatic member function. It is normally invoked using offset resolution but 
  650. can use any form of SOMobjects method resolution. For more information, see a 
  651. description of the nonstatic modifier in Modifier statements. 
  652.  
  653. A new kind of data, staticdata, is supported that is similar to C++ static data 
  654. members. A staticdata variable is not stored in an object; rather, the 
  655. ClassData structure of the implementing class contains a pointer to the 
  656. variable. For a description, see Modifier statements. 
  657.  
  658. Two new modifiers, somallocateand somdeallocate, can be used to indicate that a 
  659. user-written procedure should be executed to allocate or deallocate memory for 
  660. class instances when the somAllocate or somDeallocate method is invoked. For 
  661. descriptions of these modifiers, see Modifier statements. 
  662.  
  663. The capability to cast objects is added. See the methods somCastObj and 
  664. somResetObj. 
  665.  
  666. Support is provided for loading and unloading class libraries. This was first 
  667. introduced in SOMobjects for Windows 3.x and is now available for Windows NT 
  668. and Windows 95. See the SOM_ClassLibrary macro in the SOM Programming Reference 
  669.  
  670.  
  671. ΓòÉΓòÉΓòÉ 2.3.3. DSOM Enhancements ΓòÉΓòÉΓòÉ
  672.  
  673. New SOM IDL modifiers are provided for memory management of parameters: 
  674. memory_management= corba, caller_owns_parameters, caller_owns_result, 
  675. object_owns_parameters, and object_owns_result. The individual modifiers are 
  676. described in Modifier statements. For information about memory management, see 
  677. Memory management. This memory-management support also includes the new method 
  678. somdReleaseResources and the functions  somdExceptionFree and SOMD_NoORBfree, 
  679. described in the SOM Programming Reference. 
  680.  
  681. Support is added for the CORBA constant OBJECT_NIL. In addition, the is_nil 
  682. method of SOMDObject can now be used for local objects as well as NULL 
  683. pointers. 
  684.  
  685. Support is added for passing self-referential structs and unions (those valid 
  686. in IDL) in remote method calls. 
  687.  
  688. Support is added for local/remote transparency in DSOM's object-destruction 
  689. methods. See "Destroying remote objects." 
  690.  
  691. Users can now define customized base proxy classes. See "Customizing the 
  692. default base proxy class." 
  693.  
  694. Users can now specify an upper limit on the number of threads that a server can 
  695. spawn, using the SOMDNUMTHREADS environment variable. See this variable under 
  696. "Preparing the environment." 
  697.  
  698. Improvements have been made in error handling and performance. 
  699.  
  700. Additional sample programs are available with the SOMobjects Toolkit. 
  701.  
  702.  
  703. ΓòÉΓòÉΓòÉ 2.3.4. Metaclass Framework ΓòÉΓòÉΓòÉ
  704.  
  705. A SOMMBeforeAfter metaclass enables the programming of "before/after" 
  706. metaclasses, whose instances execute a particular method before and after each 
  707. method invocation. See The Metaclass Framework for information about the new 
  708. Metaclass Framework. Individual metaclasses, along with related classes and 
  709. methods, are documented in the SOM Programming Reference. 
  710.  
  711. A utility metaclass-SOMMTraced-is provided for tracing. 
  712.  
  713.  
  714. ΓòÉΓòÉΓòÉ 2.4. New Restrictions and Deprecated Methods ΓòÉΓòÉΓòÉ
  715.  
  716. While implementing the Metaclass Framework, IBM learned that metaclasses must 
  717. be programmed so that the capabilities they implement will be preserved when 
  718. various metaclasses are combined (using multiple inheritance) into a 
  719. SOM-derived metaclass. To assure this result, the Metaclass Framework 
  720. metaclasses have been programmed using a Cooperative Metaclass. However, IBM is 
  721. not yet ready to include the Cooperative Metaclass among the officially 
  722. supported features of SOMobjects. 
  723.  
  724. To prevent user-defined metaclasses from interfering with the operation of the 
  725. Cooperative Metaclass and consequently with the Metaclass Framework, SOMobjects 
  726. programmers are strongly urged to observe the following restriction when 
  727. programming new metaclasses: 
  728.  
  729.       User-defined metaclasses can introduce new class methods and class 
  730.       variables, but should not override any of the methods introduced by the 
  731.       SOMClass class. 
  732.  
  733.  SOMobjects users whose metaclass programming requirements cannot be met within 
  734.  the above restrictions will be given access to the Cooperative Metaclass and 
  735.  its documentation. Note, however, that metaclasses developed using the 
  736.  Cooperative Metaclass may require reprogramming when an officially supported 
  737.  Cooperative Metaclass is later introduced. 
  738.  
  739.  In addition, use of a number of (public) methods introduced by SOMClass is now 
  740.  deprecated because they are useful only from overridden SOMClass methods. 
  741.  These methods are listed under the heading "Deprecated methods" in the 
  742.  documentation for SOMClass within the SOM Programming Reference, until such 
  743.  time as SOMobjects is ready to officially provide a framework within which 
  744.  their use will not interfere with the internal operation of SOMobjects itself. 
  745.  
  746.  The aforementioned deprecated methods are not available in the Windows NT/95 
  747.  Version of SOMObjects. 
  748.  
  749.  
  750. ΓòÉΓòÉΓòÉ 3. Tutorial for Implementing SOM Classes ΓòÉΓòÉΓòÉ
  751.  
  752. This tutorial contains five examples showing how SOM classes can be implemented 
  753. to achieve various functionality. Obviously, for any person who wishes to 
  754. become a class implementor, this tutorial is essential. However, even for those 
  755. programmers who expect only to use SOM classes that were implemented by others, 
  756. the tutorial is also necessary, as it presents several concepts that will help 
  757. clarify the process of using SOM classes. 
  758.  
  759.  
  760. ΓòÉΓòÉΓòÉ 3.1. Basic Concepts of the System Object Model (SOM) ΓòÉΓòÉΓòÉ
  761.  
  762. The System Object Model (SOM), provided by the SOMobjects Developer Toolkit, is 
  763. a set of libraries, utilities, and conventions used to create binary class 
  764. libraries that can be used by application programs written in various 
  765. object-oriented programming languages, such as C++ and Smalltalk, or in 
  766. traditional procedural languages, such as C and Cobol. The following paragraphs 
  767. introduce some of the basic terminology used when creating classes in SOM: 
  768.  
  769.      An object is an OOP entity that has behavior (its methods or operations) 
  770.       and state (its data values).  In SOM, an object is a run-time entity with 
  771.       a specific set of methods and instance variables.  The methods are used 
  772.       by a client programmer to make the object exhibit behavior (that is, to 
  773.       do something), and the instance variables are used by the object to store 
  774.       its state.  (The state of an object can change over time, which allows 
  775.       the object's behavior to change.)  When a method is invoked on an object, 
  776.       the object is said to be the receiver or target of the method call. 
  777.  
  778.      An object's implementation is determined by the procedures that execute 
  779.       its methods, and by the type and layout of its instance variables.  The 
  780.       procedures and instance variables that implement an object are normally 
  781.       encapsulated  (hidden from the caller), so a program can use the object's 
  782.       methods without knowing anything about how those methods are implemented. 
  783.       Instead, a user is given access to the object's methods through its 
  784.       interface (a description of the methods in terms of the data elements 
  785.       required as input and the type of value each method returns). 
  786.  
  787.      An interface through which an object may be manipulated is represented by 
  788.       an object type.  That is, by declaring a type for an object variable, a 
  789.       programmer specifies the interface that is intended to be used to access 
  790.       that object.  SOM IDL (the SOM Interface Definition Language) is used to 
  791.       define object interfaces.  The interface names used in these IDL 
  792.       definitions are also the type names used by programmers when typing SOM 
  793.       object variables. 
  794.  
  795.      In SOM, as in most approaches to object-oriented programming, a class 
  796.       defines the implementation of objects. That is, the implementation of any 
  797.       SOM object (as well as its interface) is defined by some specific SOM 
  798.       class. A class definition begins with an IDL specification of the 
  799.       interface to its objects, and the name of this interface is used as the 
  800.       class name as well. Each object of a given class may also be called an 
  801.       instance of the class, or an instantiation of the class. 
  802.  
  803.      Inheritance, or class derivation, is a technique for developing new 
  804.       classes from existing classes. The original class is called the base 
  805.       class, or the parent class, or sometimes the direct ancestor class. The 
  806.       derived class is called a child class or a subclass.  The primary 
  807.       advantage of inheritance is that a derived class inherits all of its 
  808.       parent's methods and instance variables.  Also through inheritance, a new 
  809.       class can override (or redefine) methods of its parent, in order to 
  810.       provide enhanced functionality as needed.  In addition, a derived class 
  811.       can introduce new methods of its own. If a class results from several 
  812.       generations of successive class derivation, that class "knows" all of its 
  813.       ancestors's methods (whether overridden or not), and an object (or 
  814.       instance) of that class can execute any of those methods. 
  815.  
  816.      SOM classes can also take advantage of multiple inheritance, which means 
  817.       that a new class is jointly derived from two or more parent classes.  In 
  818.       this case, the derived class inherits methods from all of its parents 
  819.       (and all of its ancestors), giving it greatly expanded capabilities.  In 
  820.       the event that different parents have methods of the same name that 
  821.       execute differently, SOM provides ways for avoiding conflicts. 
  822.  
  823.      In the SOM run time, classes are themselves objects.  That is, classes 
  824.       have their own methods and interfaces, and are themselves defined by 
  825.       other classes. For this reason, a class is often called a class object. 
  826.       Likewise, the terms class methods and class variables are used to 
  827.       distinguish between the methods/variables of a class object vs. those of 
  828.       its instances.  (Note that the type of an object is not the same as the 
  829.       type of its class, which as a "class object" has its own type.) 
  830.  
  831.      A class that defines the implementation of class objects is called a 
  832.       metaclass.  Just as an instance of a class is an object, so an instance 
  833.       of a metaclass is a class object.  Moreover, just as an ordinary class 
  834.       defines methods that its objects respond to, so a metaclass defines 
  835.       methods that a class object responds to.  For example, such methods might 
  836.       involve operations that execute when a class (that is, a class object) is 
  837.       creating an instance of itself (an object).  Just as classes are derived 
  838.       from parent classes, so metaclasses can be derived from parent 
  839.       metaclasses, in order to define new functionality for class objects. 
  840.  
  841.      The SOM system contains three primitive classes that are the basis for 
  842.       all subsequent classes: 
  843.  
  844.       SOMObject           the root ancestor class for all SOM classes, 
  845.  
  846.       SOMClass            the root ancestor class for all SOM metaclasses, and 
  847.  
  848.       SOMClassMgr         the class of the SOMClassMgrObject, an object created 
  849.                           automatically during SOM initialization, to maintain 
  850.                           a registry of existing classes and to assist in 
  851.                           dynamic class loading/unloading. 
  852.  
  853.       SOMClass is defined as a subclass (or child) of SOMObject and inherits 
  854.       all generic object methods; this is why instances of a metaclass are 
  855.       class objects  (rather than simply classes) in the SOM run time. 
  856.  
  857.  SOM classes are designed to be language neutral. That is, SOM classes can be 
  858.  implemented in one programming language and used in programs of another 
  859.  language. To achieve language neutrality, the interface for a class of objects 
  860.  must be defined separately from its implementation. That is, defining 
  861.  interface and implementation requires two completely separate steps (plus an 
  862.  intervening compile), as follows: 
  863.  
  864.      An interface is the information that a program must know in order to use 
  865.       an object of a particular class. This interface is described in an 
  866.       interface definition (which is also the class definition), using a formal 
  867.       language whose syntax is independent of the programming language used to 
  868.       implement the class's methods. For SOM classes, this is the SOM Interface 
  869.       Definition Language (SOM IDL). The interface is defined in a file known 
  870.       as the IDL source file (or, using its extension, this is often called the 
  871.       .idl file). 
  872.  
  873.       An interface definition is specified within the interface declaration (or 
  874.       interface statement) of the .idl file, which includes: 
  875.  
  876.       (a)        the interface name (or class name) and the name(s) of the 
  877.                  class's parent(s), and 
  878.  
  879.       (b)        the names of the class's attributes and the signatures of its 
  880.                  new methods. (Recall that the complete set of available 
  881.                  methods also includes all inherited methods.) 
  882.  
  883.       Each method signature includes the method name, and the type and order of 
  884.       its arguments, as well as the type of its return value (if any). 
  885.       Attributes are instance variables for which "set" and "get" methods will 
  886.       automatically be defined, for use by the application program.  (By 
  887.       contrast, instance variables that are not attributes are hidden from the 
  888.       user.) 
  889.  
  890.      Once the IDL source file is complete, the SOM Compiler is used to analyze 
  891.       the .idl file and create the implementation template file, within which 
  892.       the class implementation will be defined. Before issuing the SOM Compiler 
  893.       command, sc, the class implementor can set an environment variable that 
  894.       determines which emitters (output-generating programs) the SOM Compiler 
  895.       will call and, consequently, which programming language and operating 
  896.       system the resulting binding files will relate to. (Alternatively, this 
  897.       emitter information can be placed on the command line for sc.)  In 
  898.       addition to the implementation template file itself, the binding files 
  899.       include two language-specific header files that will be #included in the 
  900.       implementation template file and in application program files. The header 
  901.       files define many useful SOM macros, functions, and procedures that can 
  902.       be invoked from the files that include the header files. 
  903.  
  904.      The implementation of a class is done by the class implementor in the 
  905.       implementation template file (often called just the implementation file 
  906.       or the template file).  As produced by the SOM Compiler, the template 
  907.       file contains stub procedures  for each method of the class.  These are 
  908.       incomplete method procedures that the class implementor uses as a basis 
  909.       for implementing the class by writing the corresponding code in the 
  910.       programming language of choice. 
  911.  
  912.  In summary, the process of implementing a SOM class includes using the SOM IDL 
  913.  syntax to create an IDL source file that specifies the interface to a class of 
  914.  objects - that is, the methods and attributes that a program can use to 
  915.  manipulate an object of that class.  The SOM Compiler is then run to produce 
  916.  an implementation template file and two binding (header) files that are 
  917.  specific to the designated programming language and operating system. Finally, 
  918.  the class implementor writes language-specific code in the template file to 
  919.  implement the method procedures. 
  920.  
  921.  At this point, the next step is to write the application (or client) 
  922.  program(s) that use the objects and methods of the newly implemented class. 
  923.  (Observe, here, that a programmer could write an application program using a 
  924.  class implemented entirely by someone else.)  If not done previously, the SOM 
  925.  compiler is run to generate usage bindings for the new class, as appropriate 
  926.  for the language used by the client program (which may be different from the 
  927.  language in which the class was implemented). After the client program is 
  928.  finished, the programmer compiles and links it using a language-specific 
  929.  compiler, and then executes the program. (Notice again, the client program can 
  930.  invoke methods on objects of the SOM class without knowing how those methods 
  931.  are implemented.) 
  932.  
  933.  
  934. ΓòÉΓòÉΓòÉ 3.1.1. Development of the Tutorial examples ΓòÉΓòÉΓòÉ
  935.  
  936.      Example 1-Implementing a simple class with one method 
  937.       Prints a default message when the "sayHello" method is invoked on an 
  938.       object of the "Hello" class. 
  939.  
  940.      Example 2-Adding an attribute to the Hello class 
  941.       Defines a "msg" attribute for the "sayHello" method to use. The client 
  942.       program "sets" a message; then the "sayHello" method "gets" the message 
  943.       and prints it. (There is no defined message when an object of the "Hello" 
  944.       class is first created.) 
  945.  
  946.      Example 3- Overriding an inherited method 
  947.       Overrides the SOMobjects method somPrintSelf so that invoking this method 
  948.       on an object of the "Hello" class will not only display the class name 
  949.       and the object's location, but will also include the object's message 
  950.       attribute. 
  951.  
  952.      Example 4-Initializing a SOM object. 
  953.       Overrides the default initialization method,  somDefaultInit, to 
  954.       illustrate how an object's instance variables can be initialized when the 
  955.       object is created. 
  956.  
  957.      Example 5-Using multiple inheritance 
  958.       Extends the "Hello" class to provide it with multiple inheritance (from 
  959.       the "Disk;" and "Printer" classes.) The "Hello" interface defines an enum 
  960.       and an "output" attribute that takes its value from the enum (either 
  961.       "screen," "printer," or "disk"). The client program "sets" the form of 
  962.       "output" before invoking the "sayHello" method to send a "msg"(defined as 
  963.       in Example 4). 
  964.  
  965.  
  966. ΓòÉΓòÉΓòÉ 3.2. Basic Steps for Implementing SOM Classes ΓòÉΓòÉΓòÉ
  967.  
  968. Implementing and using SOM classes in C or C++ involves the following steps, 
  969. which are explicitly illustrated in the examples of this tutorial: 
  970.  
  971.    1. Define the interface to objects of the new class (that is, the interface 
  972.       declaration), by creating a .idl file. 
  973.  
  974.    2. Run the SOM Compiler on the .idl file by issuing the sc command to 
  975.       produce the following binding files: 
  976.  
  977.           Template implementation file 
  978.  
  979.  
  980.            a .c file for C programmers, or 
  981.  
  982.  
  983.            a .cpp file for C++ programmers; 
  984.  
  985.           Header file to be included in the implementation file 
  986.  
  987.  
  988.            a .ih file for C programmers, or 
  989.  
  990.  
  991.            a .xih file for C++ programmers; and 
  992.  
  993.           Header file to be included in client programs that use the class 
  994.  
  995.  
  996.            a .h file for C clients, or 
  997.  
  998.  
  999.            a .xh file for C++ clients. 
  1000.  
  1001.       To specify whether the SOM Compiler should produce C or C++ bindings, set 
  1002.       the value of the SMEMIT environment variable or use the "-s" option of 
  1003.       the sc or somc command, as described in Section 4.3, "The SOM Compiler." 
  1004.       By default, the SOM Compiler produces C bindings. 
  1005.  
  1006.    3. Customize the implementation, by adding code to the template 
  1007.       implementation file. 
  1008.  
  1009.    4. Create a client program that uses the class. 
  1010.  
  1011.    5. Compile and link the client code with the class implementation, using a C 
  1012.       or C++ compiler. 
  1013.  
  1014.    6. Execute the client program. 
  1015.  
  1016.  The following examples illustrate appropriate syntax for defining interface 
  1017.  declarations in a .idl file, including designating the methods that the 
  1018.  class's instances will perform.  In addition, example template implementation 
  1019.  files contain typical code that the SOM Compiler produces. Explanations 
  1020.  accompanying each example discuss topics that are significant to the 
  1021.  particular example; full explanations of the SOM IDL syntax are contained in 
  1022.  Chapter 4, "SOM IDL and the SOM Compiler." Customization of each 
  1023.  implementation file (step 3) is illustrated in C and C++. 
  1024.  
  1025.  Note: 
  1026.  
  1027.    1. The Tutorial assumes you will work through the examples in order. If you 
  1028.       do not do so, the code that the SOM Compiler generates from your revised 
  1029.       .idl file may vary slightly from what you see in the Tutorial. 
  1030.  
  1031.    2. When the SOMobjects Toolkit is installed, a choice is made between 
  1032.       "somcorba" and "somstars" for the style of C bindings the SOM Compiler 
  1033.       will generate.  The Tutorial examples use the "somcorba" style, where an 
  1034.       interface name used as a type indicates a pointer to an object, as 
  1035.       required by strict CORBA bindings.  Consequently, as the examples show, a 
  1036.       "*" does not explicitly appear for types that are pointers to objects. 
  1037.       If your system was installed for "somstars" C bindings, you can set the 
  1038.       environment variable SMADDSTAR=1 or use the SOM Compiler option 
  1039.       "-maddstar" to request bindings that use explicit pointer stars. For more 
  1040.       information, see "Declaring object variables" in Chapter 3, "Using SOM 
  1041.       Classes in Client Programs" and "Object types" in Chapter 4, "SOM IDL and 
  1042.       the SOM Compiler." 
  1043.  
  1044.  
  1045. ΓòÉΓòÉΓòÉ 3.2.1. Example 1-Implementing a Simple Class with One Method ΓòÉΓòÉΓòÉ
  1046.  
  1047. Example 1 defines a class "Hello" which introduces one new method, "sayHello". 
  1048. When invoked from a client program, the "sayHello" method will print the fixed 
  1049. string "Hello, World!"  The example follows the six steps described in the 
  1050. preceding topic, "Basic Steps for Implementing SOM Classes." 
  1051.  
  1052.    1. Define the interface to class "Hello", which inherits methods from the 
  1053.       root class SOMObject and introduces one new method, "sayHello". Define 
  1054.       these IDL specifications in the file "hello.idl". 
  1055.  
  1056.       The "interface" statement introduces the name of a new class and any 
  1057.       parents (base classes) it may have (here, the root class SOMObject).  The 
  1058.       body of the interface declaration introduces the method "sayHello." 
  1059.       Observe that method declarations in IDL have syntax similar to C and C++ 
  1060.       function prototypes: 
  1061.  
  1062.             #include <somobj.idl>  //# Get the parent class definition.
  1063.  
  1064.             interface Hello : SOMObject
  1065.             /*  This is a simple class that demonstrates how to define the
  1066.              *  interface to a new class of objects in SOM IDL.
  1067.              */
  1068.             {
  1069.                 void sayHello();
  1070.                 // This method outputs the string "Hello, World!".
  1071.                    /* On Windows, use: string sayHello();
  1072.                     * This method returns the string "Hello, World!". */
  1073.             };
  1074.  
  1075.       Note that the method "sayHello" has no (explicit) arguments and returns 
  1076.       no value (except on Windows, which returns a string). The characters "//" 
  1077.       start a line comment, which finishes at the end of the line.  The 
  1078.       characters "/*" start a block comment which finishes with the "*/". Block 
  1079.       comments do not nest. The two comment styles can be used interchangeably. 
  1080.       Throw-away comments are also permitted in a .idl file; they are ignored 
  1081.       by the SOM Compiler.  Throw-away comments start with the characters "//#" 
  1082.       and terminate at the end of the line. 
  1083.  
  1084.       Note:  For simplicity, this IDL fragment does not include a releaseorder 
  1085.              modifier; consequently, the SOM Compiler will issue a warning for 
  1086.              the method "sayHello". For directions on using the releaseorder 
  1087.              modifier to remove this warning, see the topic "Modifier 
  1088.              statements" in Chapter 4, "Implementing Classes in SOM." 
  1089.  
  1090.    2. Run the SOM Compiler to produce binding files and an implementation 
  1091.       template (that is, issue the sc command): 
  1092.  
  1093.             > sc -s"c;h;ih" hello.idl      (for C bindings)
  1094.             > sc -s"xc;xh;xih" hello.idl   (for C++ bindings)       or OS/2)
  1095.  
  1096.       When set to generate C binding files, the SOM Compiler generates the 
  1097.       following implementation template file, named "hello.c". The template 
  1098.       implementation file contains stub procedures for each new method.  These 
  1099.       are procedures whose bodies are largely vacuous, to be filled in by the 
  1100.       implementor. (Unimportant details have been removed for this tutorial.) 
  1101.  
  1102.             #include <hello.ih>
  1103.             /*
  1104.              *  This method outputs the string "Hello, World!".
  1105.              */
  1106.  
  1107.             SOM_Scope  void   SOMLINK  sayHello(Hello somSelf, Environment *ev)
  1108.             {
  1109.                 /* HelloData *somThis = HelloGetData(somSelf); */
  1110.                 HelloMethodDebug("Hello", "sayHello");
  1111.             }
  1112.  
  1113.       The terms SOM_Scope and SOMLINK appear in the prototype for all stub 
  1114.       procedures, but they are defined by SOM and are not of interest to the 
  1115.       developer. In the method procedure for the "sayHello" method, "somSelf" 
  1116.       is a pointer to the target object (here, an instance of the class 
  1117.       "Hello") that will respond to the method. A "somSelf" parameter appears 
  1118.       in the procedure prototype for every method, since SOM requires every 
  1119.       method to act on some object. 
  1120.  
  1121.       The target object is always the first parameter of a method's procedure, 
  1122.       although it should not be included in the method's IDL specification. The 
  1123.       second parameter (which also is not included in the method's IDL 
  1124.       specification) is the parameter (Environment *ev).  This parameter can be 
  1125.       used by the method to return exception information if the method 
  1126.       encounters an error.  (Contrast the prototype for the "sayHello" method 
  1127.       in steps 1 and 2 above.) 
  1128.  
  1129.       The remaining lines of the template above are not pertinent at this 
  1130.       point.  (For those interested, they are discussed in Chapter 5, 
  1131.       "Implementing SOM Classes.")  The file is now ready for customization 
  1132.       with the C code needed to implement method "sayHello". 
  1133.  
  1134.       When set to generate C++ binding files, the SOM Compiler generates an 
  1135.       implementation template file, "hello.C" (on AIX) or "hello.cpp (on OS/2), 
  1136.       similar to the one above.  (Chapter 5 discusses the implementation 
  1137.       template in more detail.) 
  1138.  
  1139.       Recall that, in addition to generating a template implementation file, 
  1140.       the SOM Compiler also generates implementation bindings (in a header file 
  1141.       to be included in the implementation file) and usage bindings (in a 
  1142.       header file to be included in client programs).  These files are named 
  1143.       "hello.ih" and "hello.h" for C bindings, and are "hello.xih" and 
  1144.       "hello.xh" for C++ bindings. Notice that the "hello.c" file shown above 
  1145.       includes the "hello.ih" implementation binding file. 
  1146.  
  1147.    3. Customize the implementation, by adding code to the template 
  1148.       implementation file. 
  1149.  
  1150.       Modify the body of the "sayHello" method procedure in the "hello.c" (or, 
  1151.       for C++), implementation file so that the "sayHello"            o" method 
  1152.       prints "Hello, World!": 
  1153.  
  1154.             SOM_Scope void   SOMLINK sayHello(Hello somSelf, Environment *ev)
  1155.             {
  1156.                 /* HelloData *somThis = HelloGetData(somSelf); */
  1157.                 HelloMethodDebug("Hello","sayHello");
  1158.  
  1159.                 printf("Hello, World!\n");
  1160.             }
  1161.  
  1162.    4. Create a client program that uses the class. 
  1163.  
  1164.       Write a program "main" that creates an instance (object) of the "Hello" 
  1165.       class and invokes the method "sayHello" on that object. 
  1166.  
  1167.       A C programmer would write the following program in "main.c", using the 
  1168.       bindings defined in the "hello.h" header file: 
  1169.  
  1170.             #include <hello.h>
  1171.  
  1172.             int main(int argc, char *argv[])
  1173.             {
  1174.                 /* Declare a variable to point to an instance of Hello */
  1175.                 Hello obj;
  1176.  
  1177.                 /* Create an instance of the Hello class */
  1178.                 obj = HelloNew();
  1179.  
  1180.                 /* Execute the "sayHello" method */
  1181.                 _sayHello(obj, somGetGlobalEnvironment());
  1182.  
  1183.                 /* Free the instance: */
  1184.                 _somFree(obj);
  1185.                 return (0);
  1186.             }
  1187.  
  1188.       Notice the statement obj = HelloNew();  The "hello.h" header file 
  1189.       automatically contains the SOM-defined macro <className>New(), which is 
  1190.       used to create an instance of the <className> class (here, the "Hello" 
  1191.       class). 
  1192.  
  1193.       Also notice that, in C, a method is invoked on an object by using the 
  1194.       form: 
  1195.  
  1196.             _<methodName>(<objectName>, <environment_argument>, <other_method_arguments>)
  1197.  
  1198.       as used above in the statement _sayHello(obj, somGetGlobalEnvironment()). 
  1199.       As shown in this example, the SOM-provided somGetGlobalEnvironment 
  1200.       function can be used to supply the (Environment *) argument of the 
  1201.       method. 
  1202.  
  1203.       Finally, the code uses the method somFree, which SOM also provides, to 
  1204.       free the object created by HelloNew().  Notice that  somFree does not 
  1205.       require an (Environment *) argument. This is because the method 
  1206.       procedures for some of the classes in the SOMobjects Toolkit (including 
  1207.       SOMObject, SOMClass, and SOMClassMgr) do not have an Environment 
  1208.       parameter, to ensure compatibility with the previous release of SOM.  The 
  1209.       documentation for each SOM-kernel method in the SOMobjects Developer 
  1210.       Toolkit: Programmers Reference Manual indicates whether an Environment 
  1211.       parameter is used. 
  1212.  
  1213.       A C++ programmer would write the following program in "main.cpp", using 
  1214.       the bindings defined in the "hello.xh" header file: 
  1215.  
  1216.             #include <hello.xh>
  1217.  
  1218.             int main(int argc, char *argv╤ìΓêÖ)
  1219.             {
  1220.                 /* Declare a variable to point to an instance of Hello */
  1221.                 Hello *obj;
  1222.  
  1223.                 /* Create an instance of the Hello class */
  1224.                 obj = new Hello;
  1225.  
  1226.                 /* Execute the "sayHello" method */
  1227.                 obj->sayHello(somGetGlobalEnvironment());
  1228.  
  1229.                 obj->somFree();
  1230.                 return (0);
  1231.             }
  1232.  
  1233.       Notice that the only argument passed to the "sayHello" method by a C++ 
  1234.       client program is the Environment pointer.  (Contrast this with the 
  1235.       invocation of "sayHello" in the C client program, above. 
  1236.  
  1237.    5. Compile and link the client code with the class implementation. 
  1238.  
  1239.       Note: The environment variable SOMBASE represents the directory in which 
  1240.       SOM has been installed. 
  1241.  
  1242.       For C programmers: 
  1243.  
  1244.             > set LIB=%SOMBASE%\lib;%LIB%
  1245.             > icc -I. -I%SOMBASE%\include -Fe hello main.c hello.c  somtk.lib
  1246.  
  1247.       For C++ programmers: 
  1248.  
  1249.             > set LIB=%SOMBASE%\lib;%LIB%
  1250.             > icc -I. -I\%SOMBASE%\include -Fe hello main.cpp hello.cpp  somtk.lib
  1251.  
  1252.    6. Execute the client program. 
  1253.  
  1254.             > hello
  1255.             Hello, World!
  1256.  
  1257.       Example 2 will extend the "Hello" class to introduce an "attribute." 
  1258.  
  1259.       File Extensions for SOM Files 
  1260.  
  1261.             ΓöîΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÉ
  1262.             Γöé IDL source file:           Γöé .idl   Γöé for all users        Γöé
  1263.             Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  1264.             Γöé Implementation template file:    Γöé .c    Γöé for C, all systems      Γöé
  1265.             Γöé                   Γöé      Γöé               Γöé
  1266.             Γöé                   Γöé      Γöé               Γöé
  1267.             Γöé                   Γöé      Γöé               Γöé
  1268.             Γöé                   Γöé .cpp   Γöé for C++           Γöé
  1269.             Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  1270.             Γöé Header file for implementation    Γöé .ih    Γöé for C            Γöé
  1271.             Γöé file:                Γöé      Γöé               Γöé
  1272.             Γöé                   Γöé .xih   Γöé for C++           Γöé
  1273.             Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  1274.             Γöé Header file for program file:    Γöé .h    Γöé for C            Γöé
  1275.             Γöé                   Γöé      Γöé               Γöé
  1276.             Γöé                   Γöé .xh    Γöé for C++           Γöé
  1277.             ΓööΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÿ
  1278.  
  1279.  
  1280. ΓòÉΓòÉΓòÉ 3.2.2. Example 2-Adding an Attribute to the Hello class ΓòÉΓòÉΓòÉ
  1281.  
  1282. Example 1 introduced a class "Hello" which has a method "sayHello" that prints 
  1283. the fixed string "Hello, World!"  Example 2 extends the "Hello" class so that 
  1284. clients can customize the output from the method "sayHello". 
  1285.  
  1286.    1. Modify the interface declaration for the class definition in "hello.idl." 
  1287.  
  1288.       Class "Hello" is extended by adding an attribute that we call "msg". 
  1289.       Declaring an attribute is equivalent to defining "get" and "set" methods. 
  1290.       For example, specifying: 
  1291.  
  1292.                attribute string msg;
  1293.  
  1294.       is equivalent to defining the two methods: 
  1295.  
  1296.                string _get_msg();
  1297.                void  _set_msg(in string msg);
  1298.  
  1299.       Thus, for convenience, an attribute can be used (rather than an instance 
  1300.       variable) in order to use the automatically defined "get" and "set" 
  1301.       methods without having to write their method procedures. The new 
  1302.       interface specification for "Hello" that results from adding attribute 
  1303.       "msg" to the "Hello" class is as follows (with some comment lines 
  1304.       omitted): 
  1305.  
  1306.                #include <somobj.idl>
  1307.  
  1308.                interface Hello : SOMObject
  1309.                {
  1310.                  void  sayHello();
  1311.  
  1312.                  attribute string msg;
  1313.                       //# This is equivalent to defining the methods:
  1314.                       //#     string _get_msg();
  1315.                       //#      void  _set_msg(string msg);
  1316.                };
  1317.  
  1318.    2. Re-run the SOM Compiler on the updated idl file, as in example 1.  This 
  1319.       produces new header files and updates the existing implementation file, 
  1320.       if needed, to reflect changes made to the .idl file.  In this example, 
  1321.       the implementation file is not modified by the SOM Compiler. 
  1322.  
  1323.    3. Customize the implementation. 
  1324.  
  1325.       Customize the implementation file by modifying the print statement in the 
  1326.       "sayHello" method procedure. This example prints the contents of the 
  1327.       "msg" attribute (which must be initialized in the client program) by 
  1328.       invoking the "_get_msg" method. Notice that, because the "_get_msg" 
  1329.       method name begins with an underscore, the method is invoked with two 
  1330.       leading underscores (for C only). 
  1331.  
  1332.                SOM_Scope void   SOMLINK sayHello(Hello somSelf, Environment  *ev)
  1333.                {
  1334.                    /* HelloData *somThis = HelloGetData(somSelf); */
  1335.                    HelloMethodDebug("Hello", "sayHello");
  1336.  
  1337.                    printf("%s\n", __get_msg(somSelf, ev));
  1338.  
  1339.                    /* for  C++, use   somSelf->_get_msg(ev);  */
  1340.                }
  1341.  
  1342.       This implementation assumes that "_set_msg" has been invoked to 
  1343.       initialize the "msg" attribute before the "_get_msg" method is invoked by 
  1344.       the "sayHello" method.  This initialization can be done within the client 
  1345.       program. 
  1346.  
  1347.    4. Update the client program. 
  1348.  
  1349.       Modify the client program so that the "_set_msg" method is invoked to 
  1350.       initialize the "msg" attribute before the "sayHello" method is invoked. 
  1351.       Notice that, because the "_set_msg" method name begins with an 
  1352.       underscore, the C client program invokes the method with two  leading 
  1353.       underscores. 
  1354.  
  1355.       For C programmers: 
  1356.  
  1357.                #include <hello.h>
  1358.  
  1359.                int main(int argc, char *argv[])
  1360.                {
  1361.                    Hello obj;
  1362.  
  1363.                    obj = HelloNew();
  1364.                    /* Set the msg text */
  1365.                    __set_msg(obj, somGetGlobalEnvironment(), "Hello World Again");
  1366.  
  1367.                    /* Execute the "sayHello" method */
  1368.                    _sayHello(obj, somGetGlobalEnvironment());
  1369.  
  1370.                    _somFree(obj);
  1371.                    return (0);
  1372.                }
  1373.  
  1374.       For C++ programmers: 
  1375.  
  1376.                #include <hello.xh>
  1377.  
  1378.                int main(int argc, char *argv[])
  1379.                {
  1380.                    Hello *obj;
  1381.                    obj = new Hello;
  1382.  
  1383.                    /* Set the msg text */
  1384.                    obj->_set_msg(somGetGlobalEnvironment(), "Hello World Again");
  1385.  
  1386.                    /* Execute the "sayHello" method */
  1387.                    obj->sayHello(somGetGlobalEnvironment());
  1388.  
  1389.                    obj->somFree();
  1390.                    return (0);
  1391.                }
  1392.  
  1393.    5. Compile and link the client program, as before. 
  1394.  
  1395.    6. Execute the client program: 
  1396.  
  1397.                > hello
  1398.                Hello World Again
  1399.  
  1400.       The next example extends the "Hello" class to override (redefine) one of 
  1401.       the methods it inherits from its parent class, SOMObject. 
  1402.  
  1403.  
  1404. ΓòÉΓòÉΓòÉ 3.2.3. Attributes vs instance variables ΓòÉΓòÉΓòÉ
  1405.  
  1406. As an alternative to defining "numberObjs" as an attribute, it could be defined 
  1407. as an instance variable, with a "get_numberObjs" method also defined for 
  1408. retrieving its value.  Instance variables are declared in an implementation 
  1409. statement, as shown below: 
  1410.  
  1411.    interface Hello
  1412.    {
  1413.    string get_msg() ;
  1414.    void set_msg(in string msg);
  1415.  
  1416.    #ifdef __SOMIDL__
  1417.    implementation
  1418.    {
  1419.        string message;
  1420.    };
  1421.    #endif
  1422.    };
  1423.  
  1424. As demonstrated in this example, one disadvantage to using an instance variable 
  1425. is that the "get_msg" and "set_msg" methods must be defined in the 
  1426. implementation file by the class implementor. For attributes, by contrast, 
  1427. default implementations of the "get" and "set" methods are generated 
  1428. automatically by the SOM Compiler in the .ih and .xih header files. 
  1429.  
  1430. Note: For some attributes (particularly those involving structures, strings, 
  1431. and pointers) the default implementation generated by the SOM Compiler for the 
  1432. "set" method may not be suitable. This happens because the SOM Compiler only 
  1433. performs a "shallow copy," which typically is not useful for distributed 
  1434. objects with these types of attributes.  In such cases, it is possible to write 
  1435. your own implementations, as you do for any other method, by specifying the 
  1436. "noset/noget" modifiers for the attribute. (See the subtopic "Modifier 
  1437. statements" in Chapter 4 "SOM IDL and the SOM Compiler.") 
  1438.  
  1439. Regardless of whether you let the SOM Compiler generate your implementations or 
  1440. not, if access to instance data is required, either from a subclass or a client 
  1441. program, then this access should be facilitated by using an attribute. 
  1442. Otherwise, instance data can be defined in the "implementation" statement as 
  1443. above (using the same syntax as used to declare variables in C or C++), with 
  1444. appropriate methods defined to access it. For more information about 
  1445. "implementation" statements, see the topic "Implementation statements" in 
  1446. Chapter 4. 
  1447.  
  1448. As an example where instance variables would be used (rather than attributes), 
  1449. consider a class "Date" that provides a method for returning the current date. 
  1450. Suppose the date is represented by three instance variables-"mm", "dd", and 
  1451. "yy". Rather than making "mm", "dd", and "yy" attributes (and allowing clients 
  1452. to access them directly), "Date" defines "mm", "dd", and "yy" as instance 
  1453. variables in the "implementation" statement, and defines a method "get_date" 
  1454. that converts "mm", "dd", and "yy" into a string of the form "mm/dd/yy": 
  1455.  
  1456.    interface Date
  1457.    {
  1458.            string get_date() ;
  1459.  
  1460.    #ifdef __SOMIDL__
  1461.    implementation
  1462.    {
  1463.        long mm,dd,yy;
  1464.    };
  1465.    #endif
  1466.    };
  1467.  
  1468. To access instance variables that a class introduces from within the class 
  1469. implementation file, two forms of notation are available: 
  1470.  
  1471. somThis->variableName 
  1472.  
  1473. or 
  1474.  
  1475. _variableName 
  1476.  
  1477. For example, the implementation for "get_date" would 
  1478.  
  1479.       access the "mm" instance variable as somThis->mm or _mm, 
  1480.       access "dd"  as somThis->dd or _dd, and 
  1481.       access "yy" as somThis->yy or _yy. 
  1482.  
  1483.  In C++ programs, the _variableName  form is available only if the programmer 
  1484.  first defines the macro VARIABLE_MACROS (that is, enter #define 
  1485.  VARIABLE_MACROS) in the implementation file prior to including the .xih file 
  1486.  for the class. 
  1487.  
  1488.  
  1489. ΓòÉΓòÉΓòÉ 3.2.4. Example 3-Overriding an Inherited Method ΓòÉΓòÉΓòÉ
  1490.  
  1491. An important aspect of OOP programming is the ability of a subclass to replace 
  1492. an inherited method implementation with a new implementation especially 
  1493. appropriate to its instances.  This is called overriding a method. Sometimes, a 
  1494. class may introduce methods that every descendant class is expected to 
  1495. override.  For example, SOMobjects introduces the somPrintSelf method, and a 
  1496. good SOM programmer will generally override this method when implementing a new 
  1497. class. 
  1498.  
  1499. The purpose of somPrintSelf is to print a brief description of an object.  The 
  1500. method can be useful when debugging an application that deals with a number of 
  1501. objects of the same class-assuming the class designer has overridden 
  1502. somPrintSelf with a message that is useful in distinguishing different objects 
  1503. of the class.  For example, the implementation of somPrintSelf provided by 
  1504. SOMobjects simply prints the class of the object and its address in memory. 
  1505. SOMclass overrides this method so that, when somPrintSelf is invoked on a class 
  1506. object, the name of the class will print. 
  1507.  
  1508. This example illustrates how somPrintSelf might be overridden for the "Hello" 
  1509. class.  An important identifying characteristic of "Hello" objects is the 
  1510. message they hold; thus, the following steps illustrate how somPrintSelf could 
  1511. be overridden in "Hello" to provide this information. 
  1512.  
  1513.    1. Modify the interface declaration in "hello.idl." 
  1514.  
  1515.       To override the somPrintSelf method in "Hello", additionalinformation 
  1516.       must be provided in "hello.idl" in the form of an implementation 
  1517.       statement, which gives extra information about the class, its methods and 
  1518.       attributes, and any instance variables.  (The previous examples omitted 
  1519.       the optional "implementation" statement, because it was not needed.) 
  1520.  
  1521.       In the current example, the "implementation" statement introduces the 
  1522.       modifiers  for the "Hello" class, as follows. 
  1523.  
  1524.                #include <somobj.idl>
  1525.  
  1526.                interface Hello : SOMObject
  1527.                {
  1528.                  void sayHello();
  1529.  
  1530.                  attribute string msg;
  1531.  
  1532.                  #ifdef __SOMIDL__
  1533.                  implementation
  1534.                  {
  1535.                          //# Method Modifiers:
  1536.                          somPrintSelf: override;
  1537.                          // Override the inherited implementation of somPrintSelf.
  1538.                  };
  1539.                  #endif
  1540.  
  1541.                  };
  1542.  
  1543.       Here, "somPrintSelf:" introduces a list of modifiers  for the (inherited) 
  1544.       somPrintSelf method in the class "Hello".  Modifiers are like C/C ++ 
  1545.       #pragma commands and give specific implementation details to the 
  1546.       compiler. This example uses only one modifier, "override." Because of the 
  1547.       "override" modifier, when somPrintSelf is invoked on an instance of class 
  1548.       "Hello", Hello's implementation of somPrintSelf (in the implementation 
  1549.       file) will be called, instead of the implementation inherited from the 
  1550.       parent class, SOMObject. 
  1551.  
  1552.       The "#ifdef__SOMIDL__" and "#endif" are standard C and C++ preprocessor 
  1553.       commands that cause the "implementation" statement to be read only when 
  1554.       using the SOM IDL compiler (and not some other IDL compiler). 
  1555.  
  1556.    2. Re-run the SOM Compiler on the updated .idl file, as before.  The SOM 
  1557.       Compiler extends the existing implementation file from Example 2 to 
  1558.       include new stub procedures as needed (in this case, for somPrintSelf). 
  1559.       Below is a shortened version of the C language implementation file as 
  1560.       updated by the SOM Compiler; C++ implementation files are similarly 
  1561.       revised.  Notice that the code previously added to the "sayHello" method 
  1562.       is not disturbed when the SOM Compiler updates the implementation file. 
  1563.  
  1564.                #include <hello.ih>
  1565.  
  1566.                SOM_Scope void   SOMLINK sayHello(Hello somSelf, Environment  *ev)
  1567.                {
  1568.                    /* HelloData *somThis = HelloGetData(somSelf); */
  1569.                    HelloMethodDebug("Hello","sayHello");
  1570.  
  1571.                    printf("%s\n", __get_msg(somSelf, ev));
  1572.                }
  1573.  
  1574.                SOM_Scope void   SOMLINK  somPrintSelf(Hello somSelf)
  1575.                {
  1576.                    HelloData *somThis = HelloGetData(somSelf);
  1577.                    HelloMethodDebug("hello","somPrintSelf");
  1578.  
  1579.                      Hello_parent_SOMObject_somPrintSelf(somSelf);
  1580.                }
  1581.  
  1582.       Note that the SOM Compiler added code allowing the "Hello" class to 
  1583.       redefine somPrintSelf.  The SOM Compiler provides a default 
  1584.       implementation for overriding the somPrintSelf method.  This default 
  1585.       implementation simply calls the "parent method" [the procedure that the 
  1586.       parent class of "Hello" (SOMObject) uses to implement the somPrintSelf 
  1587.       method]. This parent method call is accomplished by the macro 
  1588.       Hello_parent_SOMObject_somPrintSelf defined in "hello.ih." 
  1589.  
  1590.       Notice that the stub procedure for overriding the somPrintSelf method 
  1591.       does not include an Environment parameter. This is because somPrintSelf 
  1592.       is introduced by SOMObject, which does not include the Environment 
  1593.       parameter in any of its methods (to ensure backward compatibility). The 
  1594.       signature for a method cannot change after it has been introduced. 
  1595.  
  1596.    3. Customize the implementation. 
  1597.  
  1598.       Within the new somPrintSelf method procedure, display a brief description 
  1599.       of the object, appropriate to "Hello" objects.  Note that the parent 
  1600.       method call is not needed, so it has been deleted.  Also, direct access 
  1601.       to instance data introduced by the "Hello" class is not required, so the 
  1602.       assignment to "somThis" has been commented out (see the first line of the 
  1603.       procedure). 
  1604.  
  1605.                SOM_Scope void   SOMLINK somPrintSelf(Hello somSelf)
  1606.                {
  1607.                    HelloData *somThis = HelloGetData(somSelf);
  1608.                    HelloMethodDebug("Hello","somPrintSelf");
  1609.  
  1610.                  somPrintf("--a %s object at location %x with msg:s\n",
  1611.                                _somGetClassName(somSelf),
  1612.                                somSelf,
  1613.                                __get_msg(somSelf,0));
  1614.                }
  1615.  
  1616.    4. Update the client program to illustrate the change (also notice the new 
  1617.       message text): 
  1618.  
  1619.       For C programmers: 
  1620.  
  1621.                #include <hello.h>
  1622.  
  1623.                int main(int argc, char *argv╤ìΓêÖ)
  1624.                {
  1625.                    Hello obj;
  1626.                    Environment *ev = somGetGlobalEnvironment();
  1627.  
  1628.                    obj = HelloNew();
  1629.  
  1630.                    /* Set the msg text */
  1631.                    __set_msg(obj, ev, "Hi There");
  1632.  
  1633.                    /* Execute the "somPrintSelf" method */
  1634.                    _somPrintSelf(obj);
  1635.  
  1636.                         _somFree(obj);
  1637.                         return (0);
  1638.                }
  1639.  
  1640.       For C++ programmers: 
  1641.  
  1642.                #include <hello.xh>
  1643.  
  1644.                int main(int argc, char *argv[])
  1645.                {
  1646.                    Hello *obj;
  1647.                    Environment *ev = somGetGlobalEnvironment();
  1648.  
  1649.                    obj = new Hello;
  1650.  
  1651.                    /* Set the msg text */
  1652.                    __setmsg(obj, ev, "Hi There");
  1653.  
  1654.                   /* Execute the "somPrintSelf" method */
  1655.                      obj->somPrintSelf();
  1656.  
  1657.                    obj->somFree();
  1658.                    return (0);
  1659.                }
  1660.  
  1661.    5. Compile and link the client program, as before. 
  1662.  
  1663.    6. Execute the client program, which now outputs the message: 
  1664.  
  1665.                > hello
  1666.                 -- a Hello object at location 20062838 with msg: Hi There
  1667.  
  1668.  
  1669. ΓòÉΓòÉΓòÉ 3.2.5. Example 4 - Initializing a SOM Object ΓòÉΓòÉΓòÉ
  1670.  
  1671. The previous example showed how to override the method somPrintSelf, introduced 
  1672. by SOMObject. As mentioned in that example, somPrintSelf should generally be 
  1673. overridden when implementing a new class. Another method introduced by 
  1674. SOMObject  that should generally be overridden is somDefaultInit. The purpose 
  1675. of somDefaultInit is to provide a "default" initializer  for the instance 
  1676. variables introduced by a class. 
  1677.  
  1678. This example shows how to override somDefaultInit to give each "Hello" object's 
  1679. message an initial value when the object is first created. To learn more about 
  1680. initializers than shown in this example (including how to introduce new 
  1681. initializers that take arbitrary arguments, and how to explicitly invoke 
  1682. initializers) read "Initializing and Uninitializing Objects," in Chapter 5, 
  1683. "Implementing Classes in SOM." 
  1684.  
  1685. The overall process of overriding somDefaultInit is similar to that of the 
  1686. previous example. First, the IDL for "Hello" is modified. In addition to an 
  1687. override  modifier, an init modifier is used to indicate that a stub procedure 
  1688. for an initialization method is desired (the stub procedures for initializers 
  1689. are different from those of normal methods). 
  1690.  
  1691.    1. Modify the interface declaration in "hello.idl." 
  1692.  
  1693.  
  1694.             #include <somobj.idl>
  1695.  
  1696.             interface Hello : SOMObject
  1697.             {
  1698.               void sayHello();
  1699.  
  1700.               attribute string msg;
  1701.  
  1702.             #ifdef __SOMIDL__
  1703.             implementation
  1704.             {
  1705.                 //# Method Modifiers:
  1706.                 somPrintSelf: override;
  1707.                 somDefaultInit: override, init;
  1708.             };
  1709.             #endif
  1710.  
  1711.             };
  1712.  
  1713.    2. Re-run the SOM Compiler on the updated hello.idl file, as before. SOM 
  1714.       Compiler extends the existing implementation file. Below is the 
  1715.       initializer stub procedure that the SOM Compiler adds to the C language 
  1716.       implementation file; C++ implementation files would be similarly revised: 
  1717.  
  1718.  
  1719.             SOM_Scope void SOMLINK
  1720.                       somDefaultInit(Hello somSelf, somInitCtrl *ctrl)
  1721.             {
  1722.               HelloData *somThis; /* set by BeginInitializer */
  1723.               somInitCtrl globalCtrl;
  1724.               somBooleanVector myMask;
  1725.               HelloMethodDebug("Hello", "somDefaultInit");
  1726.               Hello_BeginInitializer_somDefaultInit;
  1727.  
  1728.               Hello_Init_SOMObject_somDefaultInit(somSelf, ctrl);
  1729.               /*
  1730.                * local Hello initialization code added by programmer
  1731.                */
  1732.             }
  1733.  
  1734.    3. Customize the implementation. 
  1735.  
  1736.       Here, the "msg" instance variable is set in the implementation template 
  1737.       (rather than in the client program, as before). Thus, the "msg" is 
  1738.       defined as part of the "Hello" object's initialization. 
  1739.  
  1740.             SOM_Scope void SOMLINK
  1741.                            somDefaultInit(Hello somSelf, somInitCtrl *ctrl)
  1742.             {
  1743.               HelloData *somThis; /* set by BeginInitializer */
  1744.               somInitCtrl globalCtrl;
  1745.               somBooleanVector myMask;
  1746.               HelloMethodDebug("Hello", "somDefaultInit");
  1747.               Hello_BeginInitializer_somDefaultInit;
  1748.  
  1749.               Hello_Init_SOMObject_somDefaultInit(somSelf, ctrl);
  1750.               /*
  1751.                * local Hello initialization code added by programmer
  1752.                */
  1753.               __set_msg(somSelf, "Initial Message");
  1754.             }
  1755.  
  1756.    4. Update the client program to illustrate default initialization. 
  1757.  
  1758.  
  1759.             #include <hello.h>
  1760.             main()
  1761.             {
  1762.                 Hello h = HelloNew();
  1763.  
  1764.                 /* Execute the "somPrintSelf" method */
  1765.                 _somPrintSelf(h);
  1766.             }
  1767.  
  1768.    5. Compile and link the client program, as before. 
  1769.  
  1770.    6. Execute the client program. 
  1771.  
  1772.   > hello
  1773.   -- a Hello object at 200633A8 with msg: Initial Message
  1774.  
  1775.  
  1776. ΓòÉΓòÉΓòÉ 3.2.6. Example 5-Using Multiple Inheritance ΓòÉΓòÉΓòÉ
  1777.  
  1778. The "Hello" class is useful for writing messages to the screen.  So that 
  1779. clients can also write messages to printers and disk files, this example 
  1780. references two additional classes: "Printer" and "Disk."  The "Printer" class 
  1781. will manage messages to a printer, and the "Disk" class will manage messages 
  1782. sent to files. These classes can be defined as follows: 
  1783.  
  1784.    #include <somobj.idl>
  1785.  
  1786.    interface Printer : SOMObject
  1787.    {
  1788.        void stringToPrinter(in string s) ;
  1789.         // This method writes a string to a printer.
  1790.    };
  1791.  
  1792.    #include <somobj.idl>
  1793.  
  1794.    interface Disk : SOMObject
  1795.    {
  1796.         void stringToDisk(in string s) ;
  1797.         // This method writes a string to disk.
  1798.    };
  1799.  
  1800. This example assumes the "Printer" and "Disk" classes are defined separately 
  1801. (in "print.idl" and "disk.idl," for example), are implemented in separate 
  1802. files, and are linked with the other example code.  Given the implementations 
  1803. of the "Printer" and "Disk" interfaces, the "Hello" class can use them by 
  1804. inheriting from them, as illustrated next. 
  1805.  
  1806.    1. Modify the interface declaration in "hello.idl". 
  1807.  
  1808.                #include <disk.idl>
  1809.                #include <printer.idl>
  1810.  
  1811.                interface Hello : Disk, Printer
  1812.                {
  1813.                    void sayHello();
  1814.  
  1815.                    attribute string msg;
  1816.  
  1817.                    enum outputTypes {screen, printer, disk};
  1818.                    // Declare an enumeration for the different forms of output
  1819.  
  1820.                    attribute outputTypes output;
  1821.                    // The current form of output
  1822.  
  1823.                #ifdef __SOMIDL__
  1824.  
  1825.                  implementation {
  1826.                  somDefaultInit: override, init;
  1827.                  };
  1828.                #endif //#  __SOMIDL__
  1829.                };
  1830.  
  1831.       Notice that SOMObject is not listed as a parent of "Hello" above, because 
  1832.       SOMObject is a parent of "Disk" (and of "Printer"). 
  1833.  
  1834.       The IDL specification above declares an enumeration "outputTypes" for the 
  1835.       different forms of output, and an attribute "output" whose value will 
  1836.       depend on where the client wants the output of the "sayHello" method to 
  1837.       go. 
  1838.  
  1839.       Note: SOM IDL allows the use of structures, unions (though with a syntax 
  1840.       different from C or C++), enumerations, constants, and typedefs, both 
  1841.       inside and outside the body of an interface statement. Declarations that 
  1842.       appear inside an interface body will be emitted in the header file (that 
  1843.       is, in "hello.h" or "hello.xh").  Declarations that appear outside of an 
  1844.       interface body do not appear in the header file (unless required by a 
  1845.       special #pragma directive; see the SOM Compiler options in Chapter 4). 
  1846.  
  1847.       SOM IDL also supports all of the C and C++ preprocessor directives, 
  1848.       including conditional compilation, macro processing, and file inclusion. 
  1849.  
  1850.    2. Re-run the SOM Compiler on the updated idl file.. 
  1851.  
  1852.       Unfortunately, when this is done, the implementation for somDefaultInit 
  1853.       is not correctly updated to reflect the addition of two new parents to 
  1854.       "Hello."  This is because the implementation file emitter never changes 
  1855.       the bodies of existing method procedures.  As a result, method procedures 
  1856.       for initializer methods are not given new parent calls when the parents 
  1857.       of a class are changed.  One way to deal with this (when the parents of a 
  1858.       class are changed) is to temporarily rename the method procedure for 
  1859.       initializer methods, and then run the implementation emitter. Once this 
  1860.       is done, the code in the renamed methods can be merged into the new 
  1861.       templates, which will include all the appropriate parent method calls. 
  1862.       When this is done here, the new implementation for somDefaultInit would 
  1863.       appear as: 
  1864.  
  1865.                   SOM_Scope void SOMLINK
  1866.                                  somDefaultInit(Hello somSelf, somInitCtrl *ctrl)
  1867.              {
  1868.                HelloData *somThis; /* set by BeginInitializer */
  1869.                somInitCtrl globalCtrl;
  1870.                somBooleanVector myMask;
  1871.                HelloMethodDebug("Hello", "somDefaultInit");
  1872.                Hello_BeginInitializer_somDefaultINit;
  1873.  
  1874.                 Hello_Init_Disk_somDefaultInit(somSelf, ctrl);
  1875.                 Hello_Init_Printer_somDefaultInit(somSelf, ctrl);
  1876.                /*
  1877.                 * local Hello initialization code added by programmer
  1878.                /*
  1879.                __set_msg(somSelf, "Initial Message");
  1880.             }
  1881.  
  1882.    3. Continue to customize the implementation file, hello.c, as follows. 
  1883.       Notice that the "sayHello" method (last discussed in Example 2) is now 
  1884.       modified to allow alternate ways of outputing a "msg". 
  1885.  
  1886.             SOM_Scope void  SOMLINK sayHello(Hello somSelf, Environment *ev)
  1887.             {
  1888.                 /* HelloData *somThis = HelloGetData(somSelf) ; */
  1889.                 HelloMethodDebug("Hello","sayHello") ;
  1890.                 switch (__get_output(somSelf, ev) ) {
  1891.                         /*  for C++, use:  somSelf->_get_output(ev) */
  1892.                 case Hello_screen:
  1893.                     printf("%s\n", __get_msg(somSelf, ev) );
  1894.                         /*  for C++, use:  somSelf->_get_msg(ev) */
  1895.                     break;
  1896.                 case Hello_printer:
  1897.                     _stringToPrinter(somSelf, ev, __get_msg(somSelf, ev) );
  1898.                         /* for C++, use:
  1899.                          * somSelf->stringToPrinter(ev, somSelf->_get_msg(ev) );
  1900.                          */
  1901.                     break;
  1902.                 case Hello_disk:
  1903.                     _stringToDisk(somSelf, ev, __get_msg(somSelf, ev) );
  1904.                         /*  for C++, use:
  1905.                          *   somSelf->stringToDisk(ev, somSelf->_get_msg(ev) );
  1906.                          */
  1907.                     break;
  1908.                 }
  1909.             }
  1910.  
  1911.       The "switch" statement invokes the appropriate method depending on the 
  1912.       value of the "output" attribute.  Notice how the "case" statements 
  1913.       utilize the enumeration values of "outputTypes" declared in "hello.idl" 
  1914.       by prefacing the enumeration names with the class name (Hello_screen, 
  1915.       Hello_printer, and Hello_disk). 
  1916.  
  1917.    4. Update the client program, as illustrated next: 
  1918.  
  1919.                #include <hello.h>
  1920.                        /* for C++, use "hello.xh" and <stdio.h> */
  1921.  
  1922.                int main(int argc, char *argv[])
  1923.                {
  1924.                    Hello a = HelloNew();
  1925.                    Environment *ev = somGetGlobalEnvironment();
  1926.  
  1927.                    /*Invoke "sayHello" on an object and use each output */
  1928.                    _sayHello(a, ev) ; /* for c++, use:a->sayHello(ev);*/
  1929.                     __set_output(a, ev, Hello_printer);
  1930.                                              /* C++: a->_set_output(ev,Hello_printer);*/
  1931.                    _sayHello(a, ev);
  1932.                    __set_output(a, ev, Hello_disk);
  1933.                               /* C++:a->_set_output(ev,Hello-disk);       */
  1934.                    _sayHello(a, ev) ;
  1935.  
  1936.                    _somFree(a0 ;  /* for C++, use: a->somFree(); */
  1937.                     return (0);
  1938.                }
  1939.  
  1940.    5. Compile and link the client program as before, except also include the 
  1941.       implementation files for the "Printer" and "Disk" classes in the 
  1942.       compilation. 
  1943.  
  1944.    6. Execute the client program.  Observe that the message that prints is the 
  1945.       "msg" defined in Example 4 as part of the somDefaultInit initialization 
  1946.       of the "Hello" object. 
  1947.  
  1948.        Initial Message
  1949.  
  1950.        Initial Message               - goes to a Printer
  1951.  
  1952.        Initial Message               - goes to Disk
  1953.  
  1954.  This tutorial has described features of SOM IDL that will be useful to C and 
  1955.  C++ programmers.  SOM IDL also provides features such as full type checking, 
  1956.  constructs for declaring private methods, and constructs for defining methods 
  1957.  that receive and return pointers to structures.  Chapter 4, "SOM IDL and the 
  1958.  SOM Compiler" gives complete description of the SOM IDL syntax and also 
  1959.  describes how to use the SOM Compiler.  In addition, Chapter 5, "Implementing 
  1960.  Classes in SOM," provides helpful information for completing the 
  1961.  implementation template, for using initializer (somDefaultInit or user-defined 
  1962.  initialization methods), for defining SOM class libraries, and for customizing 
  1963.  various aspects of SOMobjects execution. 
  1964.  
  1965.  
  1966. ΓòÉΓòÉΓòÉ 4. Using SOM Classes in Client Programs ΓòÉΓòÉΓòÉ
  1967.  
  1968. This chapter discusses how to use SOM classes that have already been fully 
  1969. implemented. That is, these topics describe the steps that a programmer uses to 
  1970. instantiate an object and invoke some method(s) on it from within an 
  1971. application program. 
  1972.  
  1973. Who should read this chapter? 
  1974.  
  1975.      Programmers who wish to use SOM classes that were originally developed by 
  1976.       someone else will need to know the information in this chapter. These 
  1977.       programmers often may not need the information from any subsequent 
  1978.       chapters. 
  1979.  
  1980.      By contrast, class implementers who are creating their own SOM classes 
  1981.       should continue with Chapter 4, "SOM IDL and the SOM Compiler," and 
  1982.       Chapter 5, "Implementing Classes in SOM "for complete information on the 
  1983.       SOM Interface Definition Language (SOM IDL) syntax and other details of 
  1984.       class implementation. 
  1985.  
  1986.  Programs that use a class are referred to as client programs. A client program 
  1987.  can be written in  C, in C++, or in another language. As noted, this chapter 
  1988.  describes how client programs can use SOM classes (classes defined using SOM, 
  1989.  as described in Chapter 2, "Tutorial for Implementing SOM Classes" and in 
  1990.  Chapter 4, "SOM IDL and the SOM Compiler"and Chapter 5 "Implementing Classes 
  1991.  in SOM"). Using a SOM class involves creating instances of a class, invoking 
  1992.  methods on objects, and so forth. All of the methods, functions, and macros 
  1993.  described here can also be used by class implementers within the 
  1994.  implementation file for a class. 
  1995.  
  1996.  Note: "Using a SOM class," as described in this chapter, does not include 
  1997.  subclassing the class in a client program. In particular, the C++ compatible 
  1998.  SOM classes made available in the .xh binding file can not be subclassed in 
  1999.  C++ to create new C++ or SOM classes. 
  2000.  
  2001.  Some of the macros and functions described here are supplied as part of SOM's 
  2002.  C and C++ usage bindings. These bindings are functions and macros defined in 
  2003.  header files to be included in client programs. The usage bindings make it 
  2004.  more convenient for C and C++ programmers to create and use instances of SOM 
  2005.  classes. SOM classes can be also used without the C or C++ bindings, however. 
  2006.  For example, users of other programming languages can use SOM classes, and C 
  2007.  and C++ programmers can use a SOM class without using its language bindings. 
  2008.  The language bindings simply offer a more convenient programmer's interface to 
  2009.  SOM. Vendors of other languages may also offer SOM bindings; check with your 
  2010.  language vendor for possible SOM support. 
  2011.  
  2012.  To use the C or C++ bindings for a class, a client program must include a 
  2013.  header file for the class (using the #include preprocessor directive). For a C 
  2014.  language client program, the file <classFileStem>.h must be included. For a 
  2015.  C++ language client program, the file <classFileStem>.xh must be included. The 
  2016.  SOM Compiler generates these header files from an IDL interface definition. 
  2017.  The header files contain definitions of the macros and functions that make up 
  2018.  the C or C++ bindings for the class. Whether the header files include bindings 
  2019.  for the class's private methods and attributes (in addition to the public 
  2020.  methods and attributes) depends on the IDL interface definition available to 
  2021.  the user, and on how the SOM Compiler was invoked when generating bindings. 
  2022.  
  2023.  Usage binding headers automatically include any other bindings upon which they 
  2024.  may rely. Client programs not using the C or C++ bindings for any particular 
  2025.  class of SOM object (for example, a client program that does not know at 
  2026.  compile time what classes it will be using) should simply include the 
  2027.  SOM-supplied bindings for  SOMObject, provided in the header file "somobj.h" 
  2028.  (for C programs) or"somobj.xh" (for C++ programs). 
  2029.  
  2030.  For each task that a user of a SOM class might want to perform, this chapter 
  2031.  shows how the task would be accomplished by: 
  2032.  
  2033.      a C programmer using the C bindings, 
  2034.      a C++ programmer using the C++ bindings, or 
  2035.      a programmer not using SOM's C or C++ language bindings. 
  2036.  
  2037.  If neither of the first two approaches is applicable, the third approach can 
  2038.  always be used. 
  2039.  
  2040.  
  2041. ΓòÉΓòÉΓòÉ 4.1. An Example Client Program ΓòÉΓòÉΓòÉ
  2042.  
  2043. Following is a C program that uses the class "Hello" (as defined in the 
  2044. Tutorial in Chapter 2). The "Hello" class provides one attribute, "msg", of 
  2045. type string, and one method, "sayHello". The "sayHello" method simply displays 
  2046. the value of the "msg" attribute of the object on which the method is invoked. 
  2047.  
  2048.    #include <hello.h>  /* include the header file for Hello */
  2049.  
  2050.    int main(int argc, char *argv[])
  2051.    {
  2052.        /* declare a variable (obj) that is a
  2053.         * pointer to an instance of the Hello class: */
  2054.        Hello obj;
  2055.  
  2056.        /* create an instance of the Hello class
  2057.         * and store a pointer to it in obj: */
  2058.        obj = HelloNew();
  2059.  
  2060.        /* invoke method _set_msg on obj with the argument
  2061.         * "Hello World Again". This method sets the value of
  2062.         * obj's 'msg' attribute to the specified string.
  2063.         */
  2064.         __set_msg(obj, somGetGlobalEnvironment(), "Hello World Again");
  2065.  
  2066.         /* invoke method sayHello on obj. This method prints
  2067.          * the value of obj's 'msg' attribute.  */
  2068.         _sayHello(obj, somGetGlobalEnvironment());
  2069.  
  2070.         _somFree(obj);
  2071.         return(0);
  2072.    }
  2073.  
  2074. The C++ version of the foregoing client program is shown below: 
  2075.  
  2076.    #include <hello.xh>  /* include the header file for Hello */
  2077.  
  2078.    int main(int argc, char *argv[])
  2079.    {
  2080.        /* declare a variable (obj) that is a
  2081.         * pointer to an instance of the Hello class: */
  2082.        Hello *obj;
  2083.  
  2084.        /* create an instance of the Hello class
  2085.         * and store a pointer to it in obj: */
  2086.        obj = new Hello;
  2087.  
  2088.       /* invoke method _set_msg on obj with the argument
  2089.        * "Hello World Again". This method sets the value of
  2090.        * obj's 'msg' attribute to the specified string.  */
  2091.       obj->_set_msg(somGetGlobalEnvironment(), "Hello World Again");
  2092.  
  2093.       /* invoke method sayHello on obj. This method prints
  2094.        * the value of obj's 'msg' attribute.  */
  2095.       obj->sayHello(somGetGlobalEnvironment());
  2096.  
  2097.       obj->somFree();
  2098.       return(0);
  2099.    }
  2100.  
  2101. These client programs both produce the output: 
  2102.  
  2103. Hello World Again
  2104.  
  2105.  
  2106. ΓòÉΓòÉΓòÉ 4.2. Using SOM Classes: the Basics ΓòÉΓòÉΓòÉ
  2107.  
  2108. This section covers the following subjects: 
  2109.  
  2110.      Declaring object variables 
  2111.      Creating instances of a class 
  2112.      Invoking methods on objects 
  2113.      Using class objects 
  2114.      Compiling and linking 
  2115.  
  2116.  
  2117. ΓòÉΓòÉΓòÉ 4.2.1. Declaring object variables ΓòÉΓòÉΓòÉ
  2118.  
  2119. When declaring an object variable, an object interface name defined in IDL is 
  2120. used as the type of the variable. The exact syntax is slightly different for C 
  2121. vs. C++ programmers. Specifically, 
  2122.  
  2123.  <interfaceName>  obj ;   in C programs or 
  2124.  <interfaceName> *obj ;   in C++ programs 
  2125.  
  2126.  declares "obj" to be a pointer to an object that has type <interfaceName>. In 
  2127.  SOM, objects of this type are instances of the SOM class named 
  2128.  <interfaceName>, or of any SOM class derived from this class. Thus, for 
  2129.  example, 
  2130.  
  2131.  Animal obj;              in C programs or 
  2132.  Animal *obj;             in C++ programs 
  2133.  
  2134.  declares "obj" as pointer to an object of type "Animal" that can be used to 
  2135.  reference an instance of the SOM class "Animal" or any SOM class derived from 
  2136.  "Animal". Note that the type of an object need not be the same as its class; 
  2137.  an object of type "Animal" might not be an instance of the "Animal" class 
  2138.  (rather, it might be an instance of some subclass of "Animal" - the "Cat" 
  2139.  class, perhaps). 
  2140.  
  2141.  All SOM objects are of type SOMObject, even though they may not be instances 
  2142.  of the SOMObject class. Thus, if it is not known at compile time what type of 
  2143.  object the variable will point to, the following declaration can be used: 
  2144.  
  2145.  SOMObject obj;           in C programs or 
  2146.  SOMObject *obj;          in C++ programs. 
  2147.  
  2148.  Because the sizes of SOM objects are not known at compile time, instances of 
  2149.  SOM classes must always be dynamically allocated. Thus, a variable declaration 
  2150.  must always define a pointer to an object. 
  2151.  
  2152.  Note: In the C usage bindings, as within an IDL specification, an interface 
  2153.  name used as a type implicitly indicates a pointer to an object that has that 
  2154.  interface (this is required by the CORBA specification). The C usage bindings 
  2155.  for SOM classes therefore hide the pointer with a C typedef for 
  2156.  <interfaceName>. But this is not appropriate in the C++  usage bindings, which 
  2157.  define a C++ class for <interfaceName>. Thus, it is not correct in C++ to use 
  2158.  a declaration of the form: 
  2159.  
  2160.  <interfaceName>  obj ;   not valid in C++ programs 
  2161.  
  2162.  Note: If a C programmer also prefers to use explicit pointers to 
  2163.  <interfaceName> types, then the SOM Compiler option -maddstar can be used when 
  2164.  the C binding files are generated, and the explicit " *" will then be required 
  2165.  in declarations of object variables. (This option is required for 
  2166.  compatibility with existing SOM OIDL code. For information on using the 
  2167.  -maddstar option, see "Running the SOM Compiler" in Chapter 4, "SOM IDL and 
  2168.  the SOM Compiler.") 
  2169.  
  2170.  Users of other programming languages must also define object variables to be 
  2171.  pointers to the data structure used to represent SOM objects. The way this is 
  2172.  done is programming-language dependent. The header file "somtypes.h" defines 
  2173.  the structure of SOM objects for the C language. 
  2174.  
  2175.  
  2176. ΓòÉΓòÉΓòÉ 4.2.2. Creating instances of a class ΓòÉΓòÉΓòÉ
  2177.  
  2178. For C programmers with usage bindings, SOM provides the <className>New and the 
  2179. <className>Renew macros for creating instances of a class. 
  2180.  
  2181. These macros are illustrated with the following two examples, each of which 
  2182. creates a single instance of class "Hello": 
  2183.  
  2184.    obj = HelloNew();
  2185.    obj = HelloRenew(buffer);
  2186.  
  2187.  
  2188. ΓòÉΓòÉΓòÉ 4.2.2.1. Using <className>New ΓòÉΓòÉΓòÉ
  2189.  
  2190. After verifying that the <className> class object exists, the <className>New 
  2191. macro invokes the somNew method on the class object.  This allocates enough 
  2192. space for a new instance of <className>, creates a new instance of the class, 
  2193. initializes this new object by invoking somDefaultInit on it, and then returns 
  2194. a pointer to it.  The <className>New macro automatically creates the the class 
  2195. object for <className>, as well as its ancestor classes and metaclass, if these 
  2196. objects have not already been created. 
  2197.  
  2198. After a client program has finished using an object created using the 
  2199. <className >New macro, the object should be freed by invoking the method 
  2200. somFree on it: 
  2201.  
  2202.    _somFree(obj);
  2203.  
  2204. After uninitializing the object by invoking somDestruct on it, somFree calls 
  2205. the class object for storage deallocation. This is important because storage 
  2206. for an object created using the <className>New macro is allocated by the class 
  2207. of the object. Thus, only the class of the object can know how to reclaim the 
  2208. object's storage. object for storage deallocation. 
  2209.  
  2210.  
  2211. ΓòÉΓòÉΓòÉ 4.2.2.2. Using <className>Renew ΓòÉΓòÉΓòÉ
  2212.  
  2213. After verifying that the <className> class object exists, the <className>Renew 
  2214. macro invokes the somRenew method on the class object.  <className>Renew is 
  2215. only used when the space for the object has been allocated previously. (Perhaps 
  2216. the space holds an old uninitialized object that is not needed anymore.) This 
  2217. macro converts the given space into a new, initialized instance of <className> 
  2218. and returns a pointer to it.  The programmer is responsible for ensuring that 
  2219. the argument of <className>Renew  points to a block of storage large enough to 
  2220. hold an instance of class <className>. The SOM method somGetInstanceSize can be 
  2221. invoked on the class to determine the amount of memory required. Like 
  2222. <className>New, the <className>Renew macro automatically creates any required 
  2223. class objects that have not already been created. 
  2224.  
  2225. Hint: When creating a large number of class instances, it may be more efficient 
  2226. to allocate at once enough memory to hold all the instances, and then invoke 
  2227. <className>Renew once for each object to be created, rather than performing 
  2228. separate memory allocations. 
  2229.  
  2230.  
  2231. ΓòÉΓòÉΓòÉ 4.2.2.3. Using <className>NewClass ΓòÉΓòÉΓòÉ
  2232.  
  2233. The C and C++ usage bindings for a SOM class also provide static linkage to a 
  2234. <className>NewClass function that can be used to create the class object.  This 
  2235. can be useful if the class object is needed before its instances are created. 
  2236.  
  2237. For example, the following C code uses the function HelloNewClass to create the 
  2238. "Hello" class object. The arguments to this function are defined by the usage 
  2239. bindings, and indicate the version of the class implementation that is assumed 
  2240. by the bindings. (For more detail on creation of classes, see the later 
  2241. section, "Creating a class object.") Once the class object has been created, 
  2242. the example invokes the method somGetInstanceSize  on this class to determine 
  2243. the size of a "Hello" object, uses SOMMalloc to allocate storage, and then uses 
  2244. the HelloRenew macro to create ten instances of the "Hello" class: 
  2245.  
  2246.    #include <hello.h>
  2247.    main()
  2248.    {
  2249.    SOMClass helloCls; /*  A pointer for the Hello class object */
  2250.    Hello objA[10];    /*  an array of Hello instances */
  2251.    unsigned char *buffer;
  2252.    int i;
  2253.    int size;
  2254.  
  2255.    /* create the Hello class object:  */
  2256.    helloCls =  HelloNewClass(Hello_MajorVersion, Hello_MinorVersion);
  2257.  
  2258.    /* get the amount of space needed for a Hello instance:
  2259.     * (somGetInstanceSize is a method provided by SOM.) */
  2260.    size =  _somGetInstanceSize(helloCls);
  2261.    size = ((size+3)/4)*4;  /* round up to doubleword multiple */
  2262.  
  2263.    /* allocate the total space needed for ten instances: */
  2264.    buffer =  SOMMalloc(10*size);
  2265.  
  2266.    /* convert the space into ten separate Hello instances: */
  2267.    for (i=0; i<10; i++)
  2268.        objA[i] = HelloRenew(buffer+i*size);
  2269.    ...
  2270.    ...
  2271.    /* Uninitialize the objects and free them */
  2272.    for (i=0; i<10; i++)
  2273.      _somDestruct(objA[i],0,0);
  2274.    SOMFree(buffer);
  2275.    }
  2276.  
  2277. When an object created with the <className>Renew macro is no longer needed, its 
  2278. storage must be freed using the dual to whatever method was originally used to 
  2279. allocate the storage. Two method pairs are typical: 
  2280.  
  2281.      For example, if an object was originally initialized using the 
  2282.       <className>New macro, then, as discussed previously, the client should 
  2283.       use the somFree  method on it. 
  2284.  
  2285.      On the other hand, if the program uses the SOMMalloc function to allocate 
  2286.       memory, as illustrated in the example above, then the SOMFree function 
  2287.       must be called to free the objects' storage (because SOMFree is the dual 
  2288.       to SOMMalloc). Before this is done, the objects in the region to be freed 
  2289.       should be deinitialized by invoking the somDestruct method on them. This 
  2290.       allows each object to free any memory that may have been allocated 
  2291.       without the programmer's knowledge. (The somFree method also calls the 
  2292.       somDestruct method.) 
  2293.  
  2294.  Note:  In the somDestruct method call above, the first zero indicates that 
  2295.         memory should not be freed by the class of the object (that is, the 
  2296.         programmer will do it explicitly).  The second zero indicates that the 
  2297.         class of the object is responsible for overall control of object 
  2298.         uninitialization.  For further discussion, see "Initializing and 
  2299.         Uninitializing Objects," in Chapter 5, "Implementing Classes in SOM." 
  2300.  
  2301.  For C++ programmers with usage bindings, instances of a class <className> can 
  2302.  be created with a new operator provided by the usage bindings of each SOM 
  2303.  class.  The new operator automatically creates the class object for 
  2304.  <className>, as well as its ancestor classes and metaclass,  if they do not 
  2305.  yet exist.  After verifying the existence of the desired class object, the new 
  2306.  operator then invokes the somNewNoInit  method on the class.  This allocates 
  2307.  memory and creates a new instance of the class,  but it does not initialize 
  2308.  the new object. Initialization of the new object is then performed using one 
  2309.  of the C++ constructors defined by the usage bindings. (For further 
  2310.  discussion, see "Initializing and Uninitializing Objects," in Chapter 5, 
  2311.  "Implementing Classes in SOM.") Two variations of the new operator require no 
  2312.  arguments. When either is used, the C++ usage bindings provide a default 
  2313.  constructor that invokes the somDefaultInit method on the new object.  Thus, a 
  2314.  new object initialized by somDefaultInit would be created using either of the 
  2315.  forms: 
  2316.  
  2317.  new <className> 
  2318.  
  2319.  
  2320.  new <classname>() 
  2321.  
  2322.  For example: 
  2323.  
  2324.      obj = new Hello;
  2325.      obj1 = new Hello();
  2326.  
  2327.  For convenience, pointers to SOM objects created using the new operator can be 
  2328.  freed using the delete operator, just as for normal C++ objects (or, the 
  2329.  somFree method could be used): 
  2330.  
  2331.     delete obj;
  2332.     obj1->somFree;
  2333.  
  2334.  When previously allocated space will be used to hold a new object, C++ 
  2335.  programmers should use the somRenew method, described below. C++ bindings do 
  2336.  not provide a macro for this purpose. 
  2337.  
  2338.  somNew and somRenew: C and C++ programmers, as well programmers using other 
  2339.  languages, can create instances of a class using the SOM methods somNew and 
  2340.  somRenew, invoked on the class object. As discussed and illustrated above for 
  2341.  the C bindings, the class object must first be created using the 
  2342.  <className>NewClass procedure (or, perhaps, using the somFindClass method-see 
  2343.  the section "Using class objects," to follow later in this chapter). 
  2344.  
  2345.  The somNew method invoked on the class object creates a new instance of the 
  2346.  class, initializes the object using somDefaultInit, and then returns a pointer 
  2347.  to the new object. For instance, the following C example creates a new object 
  2348.  of the "Hello" class. 
  2349.  
  2350.      #include <hello.h>
  2351.      main()
  2352.      {
  2353.        SOMClass helloCls;   /* a pointer to the Hello class */
  2354.        Hello obj;           /* a pointer to an Hello instance */
  2355.        /* create the Hello class  */
  2356.        helloCls = HelloNewClass(Hello_MajorVersion, Hello_MinorVersion);
  2357.        obj = _somNew(helloCls); /* create the Hello instance */
  2358.      }
  2359.  
  2360.  An object created using the somNew method should be freed by invoking the 
  2361.  somFree method on it after the client program is finished using the object. 
  2362.  
  2363.  The somRenew method invoked on the class object creates a new instance of a 
  2364.  class using the given space, rather than allocating new space for the object. 
  2365.  The method converts the given space into an instance of the class, initializes 
  2366.  the new object using somDefaultInit, and then returns a pointer to it. The 
  2367.  argument to somRenew must point to a block of storage large enough to hold the 
  2368.  new instance. The method somGetInstanceSize can be used to determine the 
  2369.  amount of memory required. For example, the following C++ code creates ten 
  2370.  instances of the "Hello" class: 
  2371.  
  2372.      #include <hello.xh>
  2373.      #include <somcls.xh>
  2374.      main()
  2375.      {
  2376.        SOMClass *helloCls; // a pointer to the Hello class
  2377.        Hello *objA[10]  //  an array of Hello instance pointers
  2378.        unsigned char *buffer;
  2379.        int i;
  2380.        int size;
  2381.  
  2382.       // create the Hello class object
  2383.       helloCls =  HelloNewClass(Hello_MajorVersion, Hello_MinorVersion);
  2384.  
  2385.       // get the amount of space needed for a Hello instance:
  2386.       size = helloCls-> somGetInstanceSize();
  2387.       size = ((size+3)/4)*4;  // round up to doubleword multiple
  2388.  
  2389.       // allocate the total space needed for ten instances
  2390.       buffer =  SOMMalloc(10*size);
  2391.  
  2392.       // convert the space into ten separate Hello objects
  2393.       for (i=0; i<10; i++)
  2394.          objA[i] = helloCls-> somRenew(buffer+i*size);
  2395.  
  2396.       // Uninitialize the objects and free them
  2397.       for (i=0; i<10; i++)
  2398.          objA[i]-> somDestruct(0,0);
  2399.       SOMFree(buffer);
  2400.      }
  2401.  
  2402.  The somNew  and somRenew methods are useful for creating instances of a class 
  2403.  when the header file for the class is not included in the client program at 
  2404.  compile time. (The name of the class might be specified by user input, for 
  2405.  example.) However, the <className>New macro (for C) and the new operator (for 
  2406.  C++) can only be used for classes whose header file is included in the client 
  2407.  program at compile time. 
  2408.  
  2409.  Objects created using the somRenew method should be freed by the client 
  2410.  program that allocated it, using the dual to whatever allocation approach was 
  2411.  initially used. If the somFree method is not appropriate (because the method 
  2412.  somNew was not initially used), then, before memory is freed, the object 
  2413.  should be explicitly deinitialized by invoking the somDestruct method on it. 
  2414.  (The somFree method calls the somDestruct method.  Refer to the previous C 
  2415.  example for Renew for an explanation of the arguments to somDestruct.) 
  2416.  
  2417.  
  2418. ΓòÉΓòÉΓòÉ 4.2.3. Invoking methods on objects ΓòÉΓòÉΓòÉ
  2419.  
  2420. This topic describes the general way to invoke methods in C/C+ + and in other 
  2421. languages, and then presents subtopics for more specialized situations. 
  2422.  
  2423.  
  2424. ΓòÉΓòÉΓòÉ 4.2.3.1. Making typical method calls ΓòÉΓòÉΓòÉ
  2425.  
  2426. For C programmers with usage bindings: To invoke a method in C, use the macro: 
  2427.  
  2428.  _<methodName> (receiver, args)
  2429.  
  2430. (that is, an underscore followed by the method name). Arguments to the macro 
  2431. are the receiver of the method followed by all of the arguments to the method. 
  2432. For example: 
  2433.  
  2434.    _foo(obj, somGetGlobalEnvironment(), x, y);
  2435.  
  2436. This invokes method "foo" on "obj" (the remaining arguments are arguments to 
  2437. the method "foo"). This expression can be used anywhere that a standard 
  2438. function call can be used in C. 
  2439.  
  2440. Required arguments 
  2441.  
  2442. In C, calls to methods defined using IDL require at least two arguments- a 
  2443. pointer to the receiving object (the object responding to the method) and a 
  2444. value of type (Environment *). The Environment data structure is specified by 
  2445. CORBA, and is used to pass environmental information between a caller and a 
  2446. called method. For example, it is used to return exceptions. (For more 
  2447. information on how to supply and use the Environment structure, see the later 
  2448. section entitled "Exceptions and error handling.") 
  2449.  
  2450. In the IDL definition of a method, by contrast, the receiver and the 
  2451. Environment pointer are not listed as parameters to the method. (Unlike the 
  2452. receiver, the Environment pointer is considered a method parameter, even though 
  2453. it is never explicitly specified in IDL. For this reason, it is called an 
  2454. implicit method parameter.) For example, if a method is defined in a .idl file 
  2455. with two parameters, as in: 
  2456.  
  2457.    int foo (in char c, in float f);
  2458.  
  2459. then, with the C usage bindings, the method would be invoked with four 
  2460. arguments, as in: 
  2461.  
  2462.    intvar = _foo(obj, somGetGlobalEnvironment(), x, y);
  2463.  
  2464. where "obj" is the object responding to the method and "x" and "y" are the 
  2465. arguments corresponding to "c" and "f", above. 
  2466.  
  2467. If the IDL specification of the method includes a context specification, then 
  2468. the method has an additional (implicit) context parameter. Thus, when invoking 
  2469. the method, this argument must follow immediately after the Environment pointer 
  2470. argument.  (None of the SOM-supplied methods require context arguments.)  The 
  2471. Environment  and context method parameters are prescribed by the CORBA 
  2472. standard. 
  2473.  
  2474. If the IDL specification of the class that introduces the method includes the 
  2475. callstyle=oidl modifier, then the (Environment*) and context arguments should 
  2476. not be supplied when invoking the method. That is, the receiver of the method 
  2477. call is followed immediately by the arguments to the method (if any). Some of 
  2478. the classes supplied in the SOMobjects Toolkit (including SOMObject, SOMClass, 
  2479. and SOMClassMgr) are defined in this way, to ensure compatibility with the 
  2480. previous release of SOM. The SOM Programming Reference specifies for each 
  2481. method whether these arguments are used. 
  2482.  
  2483. If you use a C expression to compute the first argument to a method call (the 
  2484. receiver), you must use an expression without side effects, because the first 
  2485. argument is evaluated twice by the _<methodName> macro expansion. In 
  2486. particular, a somNew method call or a macro call of <className>New can not be 
  2487. used as the first argument to a C method call, because doing so would create 
  2488. two new class instances rather than one. 
  2489.  
  2490. Following the initial, required arguments to a method (the receiving object, 
  2491. the Environment, if any, and the context, if any), you enter any additional 
  2492. arguments required by that method, as specified in IDL.  For a discussion of 
  2493. how IDL in/out/inout argument types may to C/C++ data types, see the topic 
  2494. "Parameter list" in Chapter 4, "SOM IDL and the SOM Compiler." 
  2495.  
  2496. Short form vs long form 
  2497.  
  2498. If a client program uses the bindings for two different classes that introduce 
  2499. or inherit two different methods of the same name, then the _<methodName> macro 
  2500. described above (called the short form) will not be provided by the bindings, 
  2501. because the macro would be ambiguous in that circumstance. The following long 
  2502. form macro, however, is always provided by the usage bindings for each class 
  2503. that supports the method: 
  2504.  
  2505.   <className>_<methodName>(receiver, args)
  2506.  
  2507. For example, method "foo" supported by class "Bar" can be invoked as: 
  2508.  
  2509.   Bar_foo(obj, somGetGlobalEnvironment(), x, y)   (in C)
  2510.  
  2511. where "obj"  has type "Bar" and "x" and "y" are the arguments to method "foo". 
  2512.  
  2513. In most cases (where there is no ambiguity, and where the method is not a 
  2514. va_list method, as described in the subsequent subtopic "Using 'va_list' 
  2515. methods"), a C programmer may use either the short or the long form of a method 
  2516. invocation macro interchangeably. However, only the long form complies with the 
  2517. CORBA standard for C usage bindings.  If you wish to write code that can be 
  2518. easily ported to other vendor platforms that support the CORBA standard, use 
  2519. the long form exclusively. The long form is always available for every method 
  2520. that a class supports. The short form is provided both as a programming 
  2521. convenience and for source code compatibility with release 1 of SOM. 
  2522.  
  2523. In order to use the long form, a programmer will usually know what type an 
  2524. object is expected to have.  If this is not known, but the different methods 
  2525. have the same signature, the method can be invoked using name-lookup 
  2526. resolution, as described in a following subtopic of this section. 
  2527.  
  2528. For C++  programmers with usage bindings:  To invoke a method, use the standard 
  2529. C++ form shown below: 
  2530.  
  2531.   obj-><methodName> (args)
  2532.  
  2533. where args are the arguments to the method. For instance, the following example 
  2534. invokes method "foo" on "obj": 
  2535.  
  2536.    obj->foo(somGetGlobalEnvironment(), x, y)
  2537. Required arguments 
  2538.  
  2539. All methods introduced by classes declared using IDL (except those having the 
  2540. SOM IDL callstyle=oidl modifier) have at least one parameter-a value of type 
  2541. (Environment *). The Environment data structure is used to pass environmental 
  2542. information between a caller and a called method. For example, it is used to 
  2543. return exceptions. For more information on how to supply and use the 
  2544. Environment structure, see the later section entitled "Exceptions and error 
  2545. handling." 
  2546.  
  2547. The Environment pointer is an implicit parameter; in the IDL definition of a 
  2548. method, the Environment pointer is not explicitly listed as a parameter to the 
  2549. method. For example, if a method is defined in IDL with two explicit 
  2550. parameters, as in: 
  2551.  
  2552.    int foo (in char c, in float f);
  2553.  
  2554. then the method would be invoked from C++ bindings with three arguments, as in: 
  2555.  
  2556.    intvar = obj->foo(somGetGlobalEnvironment(), x, y);
  2557.  
  2558. where "obj" is the object responding to the method and "x" and "y" are the 
  2559. arguments corresponding to "c" and "f", above. 
  2560.  
  2561. If the IDL specification of the method includes a context specification, then 
  2562. the method has a second implicit parameter, of type context, and the method 
  2563. must be invoked with an additional context argument.  This argument must follow 
  2564. immediately after the Environment pointer argument.  (No SOM-supplied methods 
  2565. require context arguments.)  The Environment and context method parameters are 
  2566. prescribed by the CORBA standard. 
  2567.  
  2568. If the IDL specification of the class that introduces the method includes the 
  2569. callstyle=oidl modifier, then the (Environment  *) and context arguments should 
  2570. not be supplied when the method is invoked. Some of the classes supplied in the 
  2571. SOMobjects Toolkit (including SOMObject, SOMClass, and SOMClassMgr) are defined 
  2572. in this way, to ensure compatibility with the previous release of SOM. The SOM 
  2573. Programming Reference specifies for each method whether these arguments are 
  2574. used. 
  2575.  
  2576. Following the initial, required arguments to a method (the receiving object, 
  2577. the Environment, if any, and the context, if any), you enter any additional 
  2578. arguments required by that method, as specified in IDL.  For a discussion of 
  2579. how IDL in/out/inout argument types map to C/C++ data types, see the topic 
  2580. "Parameter list" in Chapter 4, "SOM IDL and the SOM Compiler." 
  2581.  
  2582. For non-C/C++ programmers:  To invoke a static method  (that is, a method 
  2583. declared when defining an OIDL or IDL object interface) without using the C or 
  2584. C++ usage bindings, a programmer can use the somResolve procedure. The 
  2585. somResolve  procedure takes as arguments a pointer to the object on which the 
  2586. method is to be invoked and a method token for the desired method. It returns a 
  2587. pointer to the method's procedure (or raises a fatal error if the object does 
  2588. not support the method). Depending on the language and system, it may be 
  2589. necessary to cast this procedure pointer to the appropriate type; the way this 
  2590. is done is language-specific. 
  2591.  
  2592. The method is then invoked by calling the procedure returned by somResolve (the 
  2593. means for calling a procedure, given a pointer to it, is language-specific), 
  2594. passing the method's receiver, the Environment pointer (if necessary), the 
  2595. context argument (if necessary) and the remainder of the method's arguments, if 
  2596. any. (See the section above for C programmers; the arguments to a method 
  2597. procedure are the same as the arguments passed using the long form of the 
  2598. C-language method-invocation macro for that method.) 
  2599.  
  2600. Using somResolve requires the programmer to know where to find the method token 
  2601. for the desired method. Method tokens are available from class objects that 
  2602. support the method (via the method somGetMethodToken), or from a global data 
  2603. structure, called the ClassData structure,  corresponding to the class that 
  2604. introduces the method. In C and C++ programs with access to the definitions for 
  2605. ClassData structures provided by usage bindings, the method token for method 
  2606. methodName introduced by class className may be accessed by the following 
  2607. expression: 
  2608.  
  2609.   <className>ClassData.<methodName>
  2610.  
  2611. For example, the method token for method "sayHello"introduced by class "Hello" 
  2612. is stored at location HelloClassData.sayHello, for C and C++ programmers.  The 
  2613. way method tokens are accessed in other languages is language-specific. 
  2614.  
  2615. As an  example of using offset resolution to invoke methods from a programming 
  2616. language other than C/C++, one would do the following to create an instance of 
  2617. a SOM Class X in Smalltalk: 
  2618.  
  2619.    1. Initialize the SOM run-time environment, if it has not previously been 
  2620.       initialized, using the somEnvironmentNew function. 
  2621.  
  2622.    2. If the class object for class X has not yet been created, use somResolve 
  2623.       with arguments SOMClassMgrObject (returned by somEnvironmentNew in step 
  2624.       1) and the method token for the somFindClass method,  to obtain a method 
  2625.       procedure pointer for the somFindClass method. Use the method procedure 
  2626.       for somFindClass to create the class object for class X:  Call the 
  2627.       procedure with arguments SOMClassMgrObject, the result of calling the 
  2628.       somIdFromString function with argument "X", and the major and minor 
  2629.       version numbers for class X (or zero). The procedure returns the class 
  2630.       object for class X. 
  2631.  
  2632.    3. Use somResolve with arguments representing the class object for X 
  2633.       (returned by somFindClass in step 2) and the method token for the somNew 
  2634.       method, to obtain a method procedure pointer for method somNew. (The 
  2635.       somNew method is used to create instances of class X.) 
  2636.  
  2637.    4. Call the method procedure for somNew (using the method procedure pointer 
  2638.       obtained in step 3) with the class object for X (returned by somFindClass 
  2639.       in step 3) as the argument. The procedure returns a new instance of class 
  2640.       X. 
  2641.  
  2642.  In addition to somResolve, SOM also supplies the somClassResolve procedure. 
  2643.  Instead of an object, the somClassResolve procedure takes a class as its first 
  2644.  argument, and then selects a method procedure from the instance method table 
  2645.  of the passed class. (The somResolve procedure, by contrast, selects a method 
  2646.  procedure from the instance method table of the class of which the passed 
  2647.  object is an instance.) The somClassResolve procedure therefore supports 
  2648.  casted  method resolution. See the SOM Programming Reference for more 
  2649.  information on somResolve  and somClassResolve. 
  2650.  
  2651.  If the programmer does not know at compile time which class introduces the 
  2652.  method to be invoked, or if the programmer cannot directly access method 
  2653.  tokens, then the procedure somResolveByName can be used to obtain a method 
  2654.  procedure using name-lookup resolution, as described in the next section. 
  2655.  
  2656.  If the signature of the method to be invoked is not known at compile time, but 
  2657.  can be discovered at run time, use somResolve or somResolveByName  to get a 
  2658.  pointer to the somDispatch method procedure, then use it to invoke the 
  2659.  specific method, as described below under "Method name or signature not known 
  2660.  at compile time." 
  2661.  
  2662.  
  2663. ΓòÉΓòÉΓòÉ 4.2.3.2. Accessing Attributes ΓòÉΓòÉΓòÉ
  2664.  
  2665. In addition to methods, SOM objects can also have attributes. An attribute is 
  2666. an IDL shorthand for declaring methods, and does not necessarily indicate the 
  2667. presence of any particular instance data in an object of that type. Attribute 
  2668. methods are called "get" and "set" methods. For example, if a class "Hello" 
  2669. declares an attribute called "msg", then object variables of type "Hello" will 
  2670. support the methods _get_msg and _set_msg to access or set the value of the 
  2671. "msg" attribute. (Attributes that are declared as "readonly" have no "set" 
  2672. method, however.) 
  2673.  
  2674. The "get" and "set" methods are invoked in the same way as other methods. For 
  2675. example, given class "Hello" with attribute "msg" of type string, the following 
  2676. code segments set and get the value of the "msg" attribute: 
  2677.  
  2678. For C: 
  2679.  
  2680.    #include <hello.h>
  2681.    Hello obj;
  2682.    Environment *ev = somGetGlobalEnvironment();
  2683.  
  2684.    obj = HelloNew();
  2685.    __set_msg(obj, ev, "Good Morning");/*note: two leading underscores */
  2686.    printf("%s\n", __get_msg(obj, ev));
  2687.  
  2688. For C++: 
  2689.  
  2690.    #include <hello.xh>
  2691.    #include <stdio.h>
  2692.    Hello *obj;
  2693.    Environment *ev = somGetGlobalEnvironment();
  2694.  
  2695.    obj = new Hello;
  2696.    obj->_set_msg(ev, "Good Morning");
  2697.    printf("%s\n", obj->_get_msg(ev));
  2698.  
  2699. Attributes available with each class, if any, are described in the 
  2700. documentation of the class itself in the SOM Programming Reference. 
  2701.  
  2702.  
  2703. ΓòÉΓòÉΓòÉ 4.2.3.3. Using name-lookup method resolution ΓòÉΓòÉΓòÉ
  2704.  
  2705. For C/C++  programmers:  Offset resolution is the most efficient way to select 
  2706. the method procedure appropriate to a given method call. Client programs can, 
  2707. however, invoke a method using "name-lookup" resolution instead of offset 
  2708. resolution. The C and C++ bindings for method invocation use offset resolution 
  2709. by default, but methods defined with the namelookup SOM IDL modifier result in 
  2710. C bindings in which the short form invocation macro uses name-lookup resolution 
  2711. instead.  Also, for both C and C++ bindings, a special lookup_<methodName> 
  2712. macro is defined. 
  2713.  
  2714. Name-lookup resolution is appropriate in the case where a programmer knows at 
  2715. compile time which arguments will be expected by a method (that is, its 
  2716. signature), but does not know the type of the object on which the method will 
  2717. be invoked. For example, name-lookup resolution can be used when two different 
  2718. classes introduce different methods of the same name and signature, and it is 
  2719. not known which method should be invoked (because the type of the object is not 
  2720. known at compile time). 
  2721.  
  2722. Name-lookup resolution is also used to invoke dynamic methods (that is, methods 
  2723. that have been added to a class's interface at run time rather than being 
  2724. specified in the class's IDL specification). For more information on 
  2725. name-lookup method resolution, see the topic "Method Resolution" in Chapter 4, 
  2726. "SOM IDL and the SOM Compiler." 
  2727.  
  2728. For C: To invoke a method using name-lookup resolution, when using the C 
  2729. bindings for a method that has been implemented with the namelookup modifier, 
  2730. use either of the following macros: 
  2731.  
  2732.       _<methodName> (receiver, args) 
  2733.  
  2734.       lookup_<methodName> (receiver, args) 
  2735.  
  2736.  Thus, the short-form method invocation macro results in name-lookup resolution 
  2737.  (rather than offset resolution), when the method has been defined as a 
  2738.  namelookup method. (The long form of the macro for offset resolution is still 
  2739.  available in the C usage bindings.) If the method takes a variable number of 
  2740.  arguments, then the first form shown above is used when supplying a variable 
  2741.  number of arguments, and the second form is used when supplying a va_list 
  2742.  argument in place of the variable number of arguments. 
  2743.  
  2744.  For C++: To invoke a method using name-lookup resolution, when using the C++ 
  2745.  bindings for a method that has been defined with the namelookup modifier, use 
  2746.  either of the following macros: 
  2747.  
  2748.       lookup_<methodName> (receiver, args) 
  2749.  
  2750.       <className>_lookup_<methodName> (receiver, args) 
  2751.  
  2752.  If the method takes a variable number of arguments, then the first form shown 
  2753.  above is used when supplying a variable number of arguments, and the second 
  2754.  form is used when supplying a va_list argument in place of the variable number 
  2755.  of arguments. Note that the offset-resolution forms for invoking methods using 
  2756.  the C++ bindings are also still available, even if the method has been defined 
  2757.  as a namelookup method. 
  2758.  
  2759.  For C/C++  To invoke a method using name-lookup resolution, when the method 
  2760.  has not been defined as a namelookup method: 
  2761.  
  2762.      Use the somResolveByName procedure (described in the following section), 
  2763.       or any of the methods somLookupMethod, somFindMethod or somFindMethodOk 
  2764.       to obtain a pointer to the procedure that implements the desired method. 
  2765.  
  2766.      Then, invoke the desired method by calling that procedure, passing the 
  2767.       method's intended receiver, the Environment pointer (if needed), the 
  2768.       context argument (if needed), and the remainder of the method's 
  2769.       arguments, if any. 
  2770.  
  2771.  The somLookupMethod, somFindMethod and somFindMethodOK methods are invoked on 
  2772.  a class object  (the class of the method receiver should be used), and take as 
  2773.  an argument the somId for the desired method (which can be obtained from the 
  2774.  method's name using the somIdFromString function). For more information on 
  2775.  these methods, see the SOM Programming Reference. 
  2776.  
  2777.  Important Note: SOM provides many ways for a SOM user to acquire a pointer to 
  2778.  a method procedure. Once this is done, it becomes the user's responsibility to 
  2779.  make appropriate use of this procedure. 
  2780.  
  2781.      First, the procedure should only be used on objects for which this is 
  2782.       appropriate-otherwise, run-time errors are likely to result. 
  2783.  
  2784.      Second, when the procedure is used, it is essential that the compiler be 
  2785.       given correct information concerning the signature of the method and the 
  2786.       linkage required by the method.  (On many systems, there are different 
  2787.       ways to pass method arguments, and linkage information tells a compiler 
  2788.       how to pass the arguments indicated by a method's signature). 
  2789.  
  2790.  SOM method procedures on Windows NT and Windows 95 must be called with "_ _ 
  2791.  stdcall" linkage. In Contrast, SOM method procedures on OS/2 must be called 
  2792.  with "system" linkage.  On AIX, there is only one linkage convention for 
  2793.  procedure calls. While C and C++ provide standard ways to indicate a method 
  2794.  signature, the way to indicate linkage information depends on the specific 
  2795.  compiler and system.  For each method declared using OIDL or IDL,  the C and 
  2796.  C++ usage bindings therefore use conditional macros and a typedef to name a 
  2797.  type that has the correct linkage convention. This type name can then be used 
  2798.  by programmers with access to the usage bindings for the class that introduces 
  2799.  the method whose procedure pointer is used. The type is named 
  2800.  somTD_<className>_<methodName>. This is illustrated in the following example, 
  2801.  and further details are provided in the section below, titled "Obtaining a 
  2802.  method's procedure pointer." 
  2803.  
  2804.  
  2805. ΓòÉΓòÉΓòÉ 4.2.3.4. A name-lookup example ΓòÉΓòÉΓòÉ
  2806.  
  2807. The following example shows the use of name-lookup by a SOM client programmer. 
  2808. Name-lookup resolution is appropriate when a programmer knows that an object 
  2809. will respond to a method of some given name, but does not know enough about the 
  2810. type of the object to use offset method resolution. How can this happen? It 
  2811. normally happens when a programmer wants to write generic code, using methods 
  2812. of the same name and signature that are applicable to different classes of 
  2813. objects, and yet these classes have no common ancestor that introduces the 
  2814. method. This can easily occur in single-inheritance systems (such as Smalltalk 
  2815. and SOM release 1) and can also happen in multiple-inheritance systems such as 
  2816. SOM release 2-when class hierarchies designed by different people are brought 
  2817. together for clients' use. 
  2818.  
  2819. If multiple inheritance is available, it is always possible to create a common 
  2820. class ancestor into which methods of this kind can be migrated. A refactoring 
  2821. of this kind often implements a semantically pleasing generalization that 
  2822. unifies common features of two previously unrelated class hierarchies. This 
  2823. step is most practical, however, when it does not require the redefinition or 
  2824. recompilation of current applications that use offset resolution. SOM is unique 
  2825. in that it allows this. 
  2826.  
  2827. However, such refactoring must redefine the classes that originally introduced 
  2828. the common methods (so the methods can be inherited from the new "unifying" 
  2829. class instead). A client programmer who simply wants to create an application 
  2830. may not control the implementations of the classes. Thus, the use of 
  2831. name-lookup method resolution seems the best alternative for programmers who do 
  2832. not want to define new classes, but simply to make use of available ones. 
  2833.  
  2834. For example, assume the existence of two different SOM classes, "classX" and 
  2835. "classY", whose only common ancestor is SOMObject, and who both introduce a 
  2836. method named "reduce" that accepts a string as an argument and returns a long. 
  2837. We assume that the classes were not designed in conjunction with each other. As 
  2838. a result, it is unlikely that the "reduce" method was defined with a namelookup 
  2839. modifier. 
  2840.  
  2841. Following is a C++ generic procedure that uses name-lookup method resolution to 
  2842. invoke the "reduce" method on its argument, which may be either of type 
  2843. "classX" or "classY". Note that there is no reason to include classY's usage 
  2844. bindings, since the typedef provided for the "reduce" method procedure in 
  2845. "classX" is sufficient for invoking the method procedure, independently of 
  2846. whether the target object is of type "classX" or "classY". 
  2847.  
  2848.    #include <classX.xh> // use classX's method proc typedef
  2849.  
  2850.    // this procedure can be invoked on a target of type
  2851.    // classX or classY.
  2852.  
  2853.    long generic_reduce1(SOMObject *target, string arg)
  2854.    {
  2855.       somTD_classX_reduce reduceProc = (somTD_classX_reduce)
  2856.       somResolveByName(target, "reduce");
  2857.       return reduceProc(target, arg);
  2858.    }
  2859.  
  2860. On the other hand, If the classes were designed in conjunction with each other, 
  2861. and the class designer felt that programmers might want to write generic code 
  2862. appropriate to either class of object, the namelookup modifier might have been 
  2863. used. This is a possibility in SOM release 2, even with multiple inheritance, 
  2864. but it is much more likely that the class designer would use multiple 
  2865. inheritance to introduce the reduce method in a separate class, and then use 
  2866. this other class as a parent for both classX and classY (thereby allowing the 
  2867. use of offset resolution). 
  2868.  
  2869. In any case, if the "reduce" method in "classX" were defined as a namelookup 
  2870. method, the following code would be appropriate.  Note that the name-lookup 
  2871. support provided by "classX" usage bindings is still appropriate for use on 
  2872. targets that do not have type "classX".  As a result, the "reduce" method 
  2873. introduced by "classY" need not have been defined as a namelookup method. 
  2874.  
  2875.    #include <classX.xh> // use classX's name-lookup support
  2876.  
  2877.    // this procedure can be invoked on a target of type
  2878.    // classX or classY.
  2879.  
  2880.    long generic_reduce2(SOMObject *target, string arg)
  2881.    {
  2882.        return lookup_reduce(target, arg);
  2883.    }
  2884.  
  2885. For non-C/C++  programmers:  Name-lookup  resolution is useful for non-C/C++ 
  2886. programmers when the type of an object on which a method must be invoked is not 
  2887. known at compile time or when method tokens cannot be directly accessed by the 
  2888. programmer. To invoke a method using name-lookup resolution when not using the 
  2889. C or C++ usage bindings, use the somResolveByName procedure to acquire a 
  2890. procedure pointer. How the programmer indicates the method arguments and the 
  2891. linkage convention in this case is compiler specific. 
  2892.  
  2893. The somResolveByName  procedure takes as arguments a pointer to the object on 
  2894. which the method is to be invoked and the name of the method, as a string. It 
  2895. returns a pointer to the method's procedure (or NULL if the method is not 
  2896. supported by the object). The method can then be invoked by calling the method 
  2897. procedure, passing the method's receiver, the Environment pointer (if 
  2898. necessary), the context argument (if necessary), and the rest of the method's 
  2899. arguments, if any. (See the section above for C programmers; the arguments to a 
  2900. method procedure are the same as the arguments passed to the long-form 
  2901. C-language method-invocation macro for that method.) 
  2902.  
  2903. As an example of invoking methods using name-lookup resolution using the 
  2904. procedure somResolveByName, the following steps are used to create an instance 
  2905. of a SOM Class X in Smalltalk: 
  2906.  
  2907.    1. Initialize the SOM run-time environment (if it is not already 
  2908.       initialized) using the somEnvironmentNew function. 
  2909.  
  2910.    2. If the class object for class X has not yet been created, use 
  2911.       somResolveByName with the arguments SOMClassMgrObject (returned by 
  2912.       somEnvironmentNew in step 1) and the string "somFindClass", to obtain a 
  2913.       method procedure pointer for the somFindClass method. Use the method 
  2914.       procedure for somFindClass to create the class object for class X: Call 
  2915.       the method procedure with these four arguments: SOMClassMgrObject; the 
  2916.       variable holding class X 's somId (the result of calling the 
  2917.       somIdFromString function with argument "X"); and the major and minor 
  2918.       version numbers for class X (or zero). The result is the class object for 
  2919.       class X. 
  2920.  
  2921.    3. Use somResolveByName with arguments the class object for X (returned by 
  2922.       somFindClass in step 2) and the string "somNew", to obtain a method 
  2923.       procedure pointer for method somNew. (This somNew method is used to 
  2924.       create instances of a class.) 
  2925.  
  2926.    4. Call the method procedure for somNew (using the method procedure pointer 
  2927.       obtained in step 3) with the class object for X (returned by somFindClass 
  2928.       in step 3) as the argument. The result is a new instance of class X. How 
  2929.       the programmer indicates the method arguments and the linkage convention 
  2930.       is compiler-specific. 
  2931.  
  2932.  
  2933. ΓòÉΓòÉΓòÉ 4.2.3.5. Obtaining a method's procedure pointer ΓòÉΓòÉΓòÉ
  2934.  
  2935. Method resolution is the process of obtaining a pointer to the procedure that 
  2936. implements a particular method for a particular object at run time.  The method 
  2937. is then invoked subsequently by calling that procedure, passing the method's 
  2938. intended receiver, the Environment pointer (if needed), the context argument 
  2939. (if needed), and the method's other arguments, if any. C and C++ programmers 
  2940. may wish to obtain a pointer to a method's procedure for efficient repeated 
  2941. invocations. 
  2942.  
  2943. Obtaining a pointer to a method's procedure is achieved in one of two ways, 
  2944. depending on whether the method is to be resolved using offset resolution or 
  2945. name-lookup resolution. Obtaining a method's procedure pointer via offset 
  2946. resolution is faster, but it requires that the name of the class that 
  2947. introduces the method and the name of the method be known at compile time.  It 
  2948. also requires that the method be defined as part of that class's interface in 
  2949. the IDL specification of the class. (See the topic "Method Resolution" in 
  2950. Chapter 4, "SOM IDL and the SOM Compiler" for more information on offset and 
  2951. name-lookup method resolution.) 
  2952.  
  2953.  
  2954. ΓòÉΓòÉΓòÉ 4.2.3.5.1. Offset resolution ΓòÉΓòÉΓòÉ
  2955.  
  2956. To obtain a pointer to a procedure using offset resolution, the C/C++ usage 
  2957. bindings provide the SOM_Resolve and SOM_ResolveNoCheck macros. The usage 
  2958. bindings themselves use the first of these, SOM_Resolve, for offset-resolution 
  2959. method calls. The difference in the two macros is that the SOM_Resolve macro 
  2960. performs consistency checking on its arguments, but the macro 
  2961. SOM_ResolveNoCheck, which is faster, does not. Both macros require the same 
  2962. arguments: 
  2963.  
  2964.       SOM_Resolve(<receiver>, <className>, <methodName>) 
  2965.  
  2966.       SOM_ResolveNoCheck(<receiver>, <className>, <methodName>) 
  2967.  
  2968.  where the arguments are as follows: 
  2969.  
  2970.  receiver          The object to which the method will apply. It should be 
  2971.                    specified as an expression without side effects. 
  2972.  
  2973.  className         The name of the class that introduces the method. 
  2974.  
  2975.  methodName        The name of the desired method. 
  2976.  
  2977.  These two names (className and methodName) must be given as tokens, rather 
  2978.  than strings or expressions. (For example, as Animal rather than "Animal".) If 
  2979.  the symbol SOM_TestOn is defined and the symbol SOM_NoTest is not defined in 
  2980.  the current compilation unit, then SOM_Resolve verifies that receiver is an 
  2981.  instance of className or some class derived from className. If this test 
  2982.  fails, an error message is output and execution is terminated. 
  2983.  
  2984.  The SOM_Resolve and SOM_ResolveNoCheck  macros use the procedure somResolve to 
  2985.  obtain the entry-point address of the desired method procedure (or raise a 
  2986.  fatal error if methodName is not introduced by className). This result can be 
  2987.  directly applied to the method arguments, or stored in a variable of generic 
  2988.  procedure type (for example, somMethodPtr) and retained for later method use. 
  2989.  This second possibility would result in a loss of information, however, for 
  2990.  the reasons now given. 
  2991.  
  2992.  The SOM_Resolve or SOM_ResolveNoCheck macros are especially useful because 
  2993.  they cast the method procedure they obtain to the right type to allow the C or 
  2994.  C++ compiler to call  this procedure with system linkage and with the 
  2995.  appropriate arguments. This is why the result of SOM_Resolve is immediately 
  2996.  useful for calling the method procedure, and why storing the result of 
  2997.  SOM_Resolve in a variable of some "generic" procedure type results in a loss 
  2998.  of information. The correct type information can be regained, however, because 
  2999.  the type used by SOM_Resolve for casting the result of somResolve  is 
  3000.  available from C/C++ usage bindings using the typedef name 
  3001.  somTD_<className>_<methodName>. This type name describes a pointer to a method 
  3002.  procedure for methodName introduced by class className. If the final argument 
  3003.  of the method is a va_list, then the method procedure returned by SOM_Resolve 
  3004.  or SOM_ResolveNoCheck must be called with a va_list  argument, and not a 
  3005.  variable number of arguments. 
  3006.  
  3007.  Below is a C example of using SOM_Resolve to obtain a method procedure pointer 
  3008.  for method "sayHello", introduced by class "Hello", and using it to invoke the 
  3009.  method on "obj." (Assume that the only argument required by the "sayHello" 
  3010.  method is the Environment pointer.) 
  3011.  
  3012.      somMethodProc *p;
  3013.      SOMObject obj = HelloNew();
  3014.      p = SOM_Resolve(obj, Hello, sayHello);
  3015.      ((somTD_Hello_sayHello)p) (obj, somGetGlobalEnvironment());
  3016.  
  3017.  SOM_Resolve and SOM_ResolveNoCheck can only be used to obtain method 
  3018.  procedures for static methods  (methods that have been declared in an IDL 
  3019.  specification for a class) and not methods that are added to a class at run 
  3020.  time. See the SOM Programming Reference for more information and examples on 
  3021.  SOM_Resolve and SOM_ResolveNoCheck. 
  3022.  
  3023.  
  3024. ΓòÉΓòÉΓòÉ 4.2.3.5.2. Name-lookup method resolution ΓòÉΓòÉΓòÉ
  3025.  
  3026. To obtain a pointer to a method's procedure using name-lookup  resolution, use 
  3027. the somResolveByName procedure (described in the following section), or any of 
  3028. the somLookupMethod, somFindMethod and somFindMethodOK methods. These methods 
  3029. are invoked on a class object that supports the desired method, and they take 
  3030. an argument specifying the a somId for the desired method (which can be 
  3031. obtained from the method's name using the somIdFromString function). For more 
  3032. information on these methods and for examples of their use, see the SOM 
  3033. Programming Reference. 
  3034.  
  3035.  
  3036. ΓòÉΓòÉΓòÉ 4.2.3.6. Method name or signature not known at compile time ΓòÉΓòÉΓòÉ
  3037.  
  3038. If the programmer does not know a method's name at compile time (for example, 
  3039. it might be specified by user input), then the method can be invoked in one of 
  3040. two ways, depending upon whether its signature is known: 
  3041.  
  3042.      Suppose the signature of the method is known at compile time (even though 
  3043.       the method name is not). In that case, when the name of the method 
  3044.       becomes available at run time, the somLookupMethod, somFindMethod or 
  3045.       somFindMethodOk methods or the somResolveByName procedure can be used to 
  3046.       obtain a pointer to the method's procedure using name-lookup method 
  3047.       resolution, as described in the preceding topics. That method procedure 
  3048.       can then be invoked, passing the method's intended receiver, the 
  3049.       Environment pointer (if needed), the context argument (if needed), and 
  3050.       the remainder of the method's arguments. 
  3051.  
  3052.      If the method's signature is unknown until run time, then 
  3053.       dispatch-function resolution is indicated, as described in the next 
  3054.       topic. 
  3055.  
  3056.  
  3057. ΓòÉΓòÉΓòÉ 4.2.3.6.1. Dispatch-function method resolution ΓòÉΓòÉΓòÉ
  3058.  
  3059. If the signature of the method is not known at compile time (and hence the 
  3060. method's argument list cannot be constructed until run time), then the method 
  3061. can be invoked at run time by (a) placing the arguments in a variable of type 
  3062. va_list at run time and (b) either using the somGetMethodData method followed 
  3063. by use of the somApply function, or by invoking the somDispatch or 
  3064. somClassDispatch method. Using somApply is more efficient, since this is what 
  3065. the somDispatch method does, but it requires two steps instead of one. In 
  3066. either case, the result invokes a "stub" procedure called an apply stub, whose 
  3067. purpose is to remove the method arguments from the va_list, and then pass them 
  3068. to the appropriate method procedure in the way expected by that procedure. For 
  3069. more information on these methods and for examples of their use, see the 
  3070. somApply function, and the somGetMethodData, somDispatch, and somClassDispatch 
  3071. methods in the SOM Programming Reference. 
  3072.  
  3073.  
  3074. ΓòÉΓòÉΓòÉ 4.2.4. Using class objects ΓòÉΓòÉΓòÉ
  3075.  
  3076. Using a class object encompasses three aspects: getting the class of an object, 
  3077. creating a new class object, or simply referring to a class object through the 
  3078. use of a pointer. 
  3079.  
  3080.  
  3081. ΓòÉΓòÉΓòÉ 4.2.4.1. Getting the class of an object ΓòÉΓòÉΓòÉ
  3082.  
  3083. To get the class that an object is an instance of, SOM provides a method called 
  3084. somGetClass. The somGetClass method takes an object as its only argument and 
  3085. returns a pointer to the class object of which it is an instance. For example, 
  3086. the following statements store in "myClass" the class object of which "obj" is 
  3087. an instance. 
  3088.  
  3089. myClass = _somGetClass(obj);  (for C)
  3090. myClass = obj->somGetClass();  (for C++)
  3091.  
  3092. Getting the class of an object is useful for obtaining information about the 
  3093. object; in some cases, such information cannot be obtained directly from the 
  3094. object, but only from its class. The section below entitled "Getting 
  3095. information about a class" describes the methods that can be invoked on a class 
  3096. object after it is obtained using somGetClass. 
  3097.  
  3098. The somGetClass method can be overridden by a class to provide enhanced or 
  3099. alternative semantics for its objects. Because it is usually important to 
  3100. respect the intended semantics of a class of objects, the somGetClass method 
  3101. should normally be used to access the class of an object. 
  3102.  
  3103. In a few special cases, it is not possible to make a method call on an object 
  3104. in order to determine its class. For such situations, SOM provides the 
  3105. SOM_GetClass  macro. In general, the somGetClass method and the SOM_GetClass 
  3106. macro may have different behavior (if somGetClass has been overridden). This 
  3107. difference may be limited to side effects, but it is possible for their results 
  3108. to differ as well. The SOM_GetClass macro should only be used when absolutely 
  3109. necessary. 
  3110.  
  3111.  
  3112. ΓòÉΓòÉΓòÉ 4.2.4.2. Creating a class object ΓòÉΓòÉΓòÉ
  3113.  
  3114. A class object is created automatically the first time the <className>New 
  3115. macro (for C) or the new operator (C++) is invoked to create an instance of 
  3116. that class. In other situations, however, it may be necessary to create a class 
  3117. object explicitly, as this section describes. 
  3118.  
  3119.  
  3120. ΓòÉΓòÉΓòÉ 4.2.4.2.1. Using <className>Renew or somRenew ΓòÉΓòÉΓòÉ
  3121.  
  3122. It is sometimes necessary to create a class object before creating any 
  3123. instances of the class. For example, creating instances using the <className> 
  3124. Renew macro or the somRenew method requires knowing how large the created 
  3125. instance will be, so that memory can be allocated for it. Getting this 
  3126. information requires creating the class object (see the example under "Creating 
  3127. instances of a class" early in this chapter). As another example, a class 
  3128. object must be explicitly created when a program does not use the SOM bindings 
  3129. for a class. Without SOM bindings for a class, its instances must be created 
  3130. using somNew or somRenew, and these methods require that the class object be 
  3131. created in advance. 
  3132.  
  3133. Use the <className>NewClass procedure to create a class object: 
  3134.  
  3135.      When using the C/C++ language bindings for the class, and 
  3136.  
  3137.      When the name of the class is known at compile time. 
  3138.  
  3139.  
  3140. ΓòÉΓòÉΓòÉ 4.2.4.2.2. Using <className>NewClass ΓòÉΓòÉΓòÉ
  3141.  
  3142. The <className>NewClass procedure initializes the SOM run-time environment, if 
  3143. necessary, creates the class object (unless it already exists), creates class 
  3144. objects for the ancestor classes and metaclass of the class, if necessary, and 
  3145. returns a pointer to the newly created class object. After its creation, the 
  3146. class object can be referenced in client code using the macro 
  3147.  
  3148.  _<className>                            (for C and C++ programs) 
  3149.  
  3150.  or the expression 
  3151.  
  3152.  <className>ClassData.classObject        (for C and C++ programs). 
  3153.  
  3154.  The <className>NewClass procedure takes two arguments, the major version 
  3155.  number and minor version number of the class. These numbers are checked 
  3156.  against the version numbers built into the class library to determine if the 
  3157.  class is compatible with the client's expectations. The class is compatible if 
  3158.  it has the same major version number and the same or a higher minor version 
  3159.  number. If the class is not compatible, an error is raised. Major version 
  3160.  numbers usually only change when a significant enhancement or incompatible 
  3161.  change is made to a class. Minor version numbers change when minor 
  3162.  enhancements or fixes are made. Downward compatibility is usually maintained 
  3163.  across changes in the minor version number. Zero can be used in place of 
  3164.  version numbers to bypass version number checking. 
  3165.  
  3166.  When using SOM bindings for a class, these bindings define constants 
  3167.  representing the major and minor version numbers of the class at the time the 
  3168.  bindings were generated. These constants are named <className>_MajorVersion 
  3169.  and <className>_MinorVersion. For example, the following procedure call: 
  3170.  
  3171.      AnimalNewClass(Animal_MajorVersion, Animal_MinorVersion);
  3172.  
  3173.  creates the class object for class "Animal". Thereafter, _Animal can be used 
  3174.  to reference the "Animal" class object. 
  3175.  
  3176.  The preceding technique for checking version numbers is not failsafe. For 
  3177.  performance reasons, the version numbers for a class are only checked when the 
  3178.  class object is created, and not when the class object or its instances are 
  3179.  used. Thus, run-time errors may result when usage bindings for a particular 
  3180.  version of a class are used to invoke methods on objects created by an earlier 
  3181.  version of the class. 
  3182.  
  3183.  
  3184. ΓòÉΓòÉΓòÉ 4.2.4.2.3. Using somFindClass or somFindClsInFile ΓòÉΓòÉΓòÉ
  3185.  
  3186. To create a class object when  not using the C/C++  language bindings for the 
  3187. class, or when the class name is not known at compile time: 
  3188.  
  3189.      First, initialize the SOM run-time environment by calling the 
  3190.       somEnvironmentNew function (unless it is known that the SOM run-time 
  3191.       environment has already been initialized). 
  3192.  
  3193.      Then, use the somFindClass or somFindClsInFile method to create the class 
  3194.       object. (The class must already be defined in a dynamically linked 
  3195.       library, or DLL.) 
  3196.  
  3197.  The somEnvironmentNew function initializes the SOM run-time environment. That 
  3198.  is, it creates the four primitive SOM objects (SOMClass, SOMObject, 
  3199.  SOMClassMgr, and the SOMClassMgrObject), and it initializes SOM global 
  3200.  variables. The function takes no arguments and returns a pointer to the 
  3201.  SOMClassMgrObject. 
  3202.  
  3203.  Note:  Although somEnvironmentNew must be called before using other SOM 
  3204.         functions and methods, explicitly calling somEnvironmentNew is usually 
  3205.         not necessary when using the C/C++ bindings,  because the macros for 
  3206.         <className>NewClass,  <className>New , and <className>Renew call it 
  3207.         automatically, as does the new operator for C++. Calling 
  3208.         somEnvironmentNew repeatedly does no harm. 
  3209.  
  3210.  After the SOM run-time environment has been initialized, the methods 
  3211.  somFindClass and somFindClsInFile can be used to create a class object. These 
  3212.  methods must be invoked on the class manager, which is pointed to by the 
  3213.  global variable SOMClassMgrObject.  (It is also returned as the result of 
  3214.  somEnvironmentNew.) 
  3215.  
  3216.  The somFindClass method takes the following arguments: 
  3217.  
  3218.  classId                  A somId identifying the name of the class to be 
  3219.                           created. The somIdFromString function returns a 
  3220.                           classId  given the name of the class. 
  3221.  
  3222.  major version number     The expected major version number of the class. 
  3223.  
  3224.  minor version number     The expected minor version number of the class. 
  3225.  
  3226.  The version numbers are checked against the version numbers built into the 
  3227.  class library to determine if the class is compatible with the client's 
  3228.  expectations. 
  3229.  
  3230.  The somFindClass  method dynamically loads the DLL containing the class's 
  3231.  implementation, if needed, creates the class object (unless it already exists) 
  3232.  by invoking its <className>NewClass procedure, and returns a pointer to it. If 
  3233.  the class could not be created, somFindClass returns NULL. For example, the 
  3234.  following C code fragment creates the class "Hello" and stores a pointer to it 
  3235.  in "myClass": 
  3236.  
  3237.      SOMClassMgr cm = somEnvironmentNew();
  3238.      somId classId = somIdFromString("Hello");
  3239.      SOMClass myClass = _somFindClass(SOMClassMgrObject, classId
  3240.                             Hello_MajorVersion, Hello_MinorVersion);
  3241.      ...
  3242.      SOMFree(classId);
  3243.  
  3244.  The somFindClass method uses somLocateClassFile to get the name of the library 
  3245.  file containing the class. If the class was defined with a "dllname" class 
  3246.  modifier, then somLocateClassFile returns that file name; otherwise, it 
  3247.  assumes that the class name is the name of the library file. The 
  3248.  somFindClsInFile method is similar to somFindClass, except that it takes an 
  3249.  additional (final) argument-the name of the library file containing the class. 
  3250.  The somFindClsInFile method is useful when a class is packaged in a DLL along 
  3251.  with other classes and the "dllname" class modifier has not been given in the 
  3252.  class's IDL specification. Invoking methods without corresponding class usage 
  3253.  bindings 
  3254.  
  3255.  This topic builds on the preceding discussion, and illustrates how a client 
  3256.  program can apply dynamic SOM mechanisms to utilize classes and objects for 
  3257.  which specific usage bindings are not available. This process can be applied 
  3258.  when a class implementor did not ship the C/C++ language bindings. 
  3259.  Furthermore, the process allows more programming flexibility, because it is 
  3260.  not necessary to know the class and method names at compile time in order to 
  3261.  access them at run time. (At run time, however, you must be able to provide 
  3262.  the method arguments, either explicitly or via a va_list, and provide a 
  3263.  generalized way to handle return values.) As an example application, a 
  3264.  programmer might create an online class viewer that can access many classes 
  3265.  without requiring usage bindings for all those classes, and the person using 
  3266.  the viewer can select class names at run time. 
  3267.  
  3268.  As another aspect of flexibility, a code sequence similar to the following C++ 
  3269.  example could be re-used to access any class or method. After getting the 
  3270.  somId for a class name, the example uses the somFindClass method to create the 
  3271.  class object. The somNew method is then invoked to create an instance of the 
  3272.  specified class, and the somDispatch method is used to invoke a method on the 
  3273.  object. 
  3274.  
  3275.   #include <stdio.h>
  3276.   #include <somcls.xh>
  3277.  
  3278.   int main()
  3279.   {
  3280.           SOMClass *classobj;
  3281.           somId tempId;
  3282.           somId methId;
  3283.           SOMObject *s2;
  3284.           Environment * main_ev = somGetGlobalEnvironment();
  3285.  
  3286.           tempId = SOM_IdFromString("myClassName");
  3287.           classobj = SOMClassMgrObject->somFindClass(tempId,0,0);
  3288.           SOMFree(tempId);
  3289.  
  3290.           if (NULL==classobj)
  3291.           {
  3292.                   printf("somFindClass could not find the selected class\n");
  3293.           }
  3294.           else
  3295.           {
  3296.                   s2 = (SOMObject *) (classobj->somNew());
  3297.                   methId = somIdFromString("sayHello");
  3298.                   if (s2->somDispatch((somToken *) 0, methId, s2, ev))
  3299.                           printf("Method successfully called.\n");
  3300.           }
  3301.  
  3302.           return 0;
  3303.   }
  3304.  
  3305.  
  3306. ΓòÉΓòÉΓòÉ 4.2.4.3. Referring to class objects ΓòÉΓòÉΓòÉ
  3307.  
  3308. Saving a pointer as the class object is created: The <className>NewClass macro 
  3309. and the somFindClass method, used to create class objects, both return a 
  3310. pointer to the newly created class object. Hence, one way to obtain a pointer 
  3311. to a class object is to save the value returned by <className>NewClass or 
  3312. somFindClass  when the class object is created. 
  3313.  
  3314. Getting a pointer after the class object is created: After a class object has 
  3315. been created, client programs can also get a pointer to the class object from 
  3316. the class name. When the class name is known at compile time and the client 
  3317. program is using the C or C++ language bindings, the macro 
  3318.  
  3319.       _<className> 
  3320.  
  3321.  can be used to refer to the class object for <className>. Also, when the class 
  3322.  name is known at compile time and the client program is using the C or C++ 
  3323.  language bindings, the expression 
  3324.  
  3325.       <className>ClassData.classObject 
  3326.  
  3327.  refers to the class object for <className>. For example, _Hello refers to the 
  3328.  class object for class "Hello" in C or C++ programs, and 
  3329.  HelloClassData.classObject refers to the class object for class "Hello." in C 
  3330.  or C++ programs. 
  3331.  
  3332.  Getting a pointer to the class object from an instance:  If any instances of 
  3333.  the class are known to exist, a pointer to the class object can also be 
  3334.  obtained by invoking the somGetClass method on such an instance. (See "Getting 
  3335.  the class of an object," above.) 
  3336.  
  3337.  Getting a pointer in other situations: If the class name is not known until 
  3338.  run time, or if the client program is not using the C or C++ language 
  3339.  bindings, and no instances of the class are known to exist, then the 
  3340.  somClassFromId method can be used to obtain a pointer to a class object after 
  3341.  the class object has been created. The somClassFromId method should be invoked 
  3342.  on the class manager, which is pointed to by the global variable 
  3343.  SOMClassMgrObject. The only argument to the method is a somId for the class 
  3344.  name, which can be obtained using the somIdFromString function. The method 
  3345.  somClassFromId returns a pointer to the class object of the specified class. 
  3346.  For example, the following C code stores in "myClass" a pointer to the class 
  3347.  object for class "Hello" (or NULL, if the class cannot be located): 
  3348.  
  3349.      SOMClassMgr cm = somEnvironmentNew();
  3350.      somId classId = somIdFromString("Hello");
  3351.      SOMClass myClass =_somClassFromId(SOMClassMgrObject,classId
  3352.                             Hello_MajorVersion, Hello_MinorVersion);
  3353.      SOMFree(classId);
  3354.  
  3355.  
  3356. ΓòÉΓòÉΓòÉ 4.2.5. Compiling and linking ΓòÉΓòÉΓòÉ
  3357.  
  3358. This section describes how to compile and link C and C++ client programs. 
  3359. Compiling and linking a client program with a SOM class is done in one of two 
  3360. ways, depending on how the class is packaged. 
  3361.  
  3362. Note: If you are building an application that uses a combination of C and C++ 
  3363. compiled object modules, then the C++ linker must be used to link them. 
  3364.  
  3365. If the class is not packaged as a library (that is, the client program has the 
  3366. implementation source code for the class, as in the examples given in the SOM 
  3367. IDL tutorial), then the client program can be compiled together with the class 
  3368. implementation file as follows. (This assumes that the client program and the 
  3369. class are both implemented in the same language, C or C++. If this is not the 
  3370. case, then each module must be compiled separately to produce an object file 
  3371. and the resulting object files linked together to form an executable.) 
  3372.  
  3373. In the following examples, the environment variable SOMBASE refers to the 
  3374. directory in which SOM has been installed. The examples also assume that the 
  3375. header files and the import library for the "Hello" class reside in the 
  3376. "include" and "lib" directories where SOM has been installed.  If this is not 
  3377. the case, additional path information should be supplied for these files. For 
  3378. client program "main" and class "Hello": For C programmers: 
  3379.  
  3380.    > set LIB=%SOMBASE%\lib;%LIB%
  3381.    > icc -I. -I%SOMBASE%\include main.c hello.c somtk.lib
  3382.  
  3383. For C++ programmers: 
  3384.  
  3385.    > set LIB=%SOMBASE%\lib;%LIB%
  3386.    > icc -I. -I%SOMBASE%\include main.cpp hello.cpp somtk.lib
  3387.  
  3388. If the class is packaged as a class library, then the client program, "main", 
  3389. is compiled as above, except that the class implementation file is not part of 
  3390. the compilation. Instead, the "import library" provided with the class library 
  3391. is used to resolve the symbolic references that appear in "main". For example, 
  3392. to compile the C client program "main.c" that uses class "Hello": 
  3393.  
  3394. Under *OS/2: 
  3395.  
  3396.    > set LIB=%SOMBASE%\lib;%LIB%
  3397.    > icc -I. -I%SOMBASE%\include main.c somtk.lib hello.lib
  3398.  
  3399.  
  3400. ΓòÉΓòÉΓòÉ 4.3. Language-neutral Methods and Functions ΓòÉΓòÉΓòÉ
  3401.  
  3402. This section describes methods, functions, and macros that client programs can 
  3403. use regardless of the programming language in which they are written. In other 
  3404. words, these functions and methods are not part of the C or C++ bindings. 
  3405.  
  3406.  
  3407. ΓòÉΓòÉΓòÉ 4.3.1. Generating output ΓòÉΓòÉΓòÉ
  3408.  
  3409. The following functions and methods are used to generate output, including 
  3410. descriptions of SOM objects. They all produce their output using the 
  3411. character-output procedure held by the global variable SOMOutCharRoutine. The 
  3412. default procedure for character output simply writes the character to stdout, 
  3413. but it can be replaced to change the output destination of the methods and 
  3414. functions below. (See Chapter 5 for more information on customizing SOM.) 
  3415.  
  3416.  somDumpSelf              (method) writes a detailed description of an object, 
  3417.                           including its class, its location, and its instance 
  3418.                           data. The receiver of the method is the object to be 
  3419.                           dumped. An additional argument is the "nesting level" 
  3420.                           for the description. [All lines in the description 
  3421.                           will be indented by (2 * level) spaces.] 
  3422.  
  3423.  somPrintSelf             (method) Writes a brief description of an object, 
  3424.                           including its class and location in memory. The 
  3425.                           receiver of the method is the object to be printed. 
  3426.  
  3427.  somPrintf                (function) SOM's version of the C "printf" function. 
  3428.                           It generates character stream output via 
  3429.                           SOMOutCharRoutine. It has the same interface as the C 
  3430.                           "printf" function. 
  3431.  
  3432.  somVprintf               (function) Represents the "vprint" form of somPrintf. 
  3433.                           Its arguments are a formatting string and a va_list 
  3434.                           holding the remaining arguments. 
  3435.  
  3436.  somPrefixLevel           (function) Generates (via somPrintf) spaces to prefix 
  3437.                           a line at the indicated level. The return type is 
  3438.                           void. The argument is an integer specifying the 
  3439.                           level. The number of spaces generated is (2 * level). 
  3440.  
  3441.  somLPrintf               (function) Combines somPrefixLevel and somPrintf. The 
  3442.                           first argument is the level of the description (as 
  3443.                           for somPrefixLevel) and the remaining arguments are 
  3444.                           as for somPrintf (or for the C "printf" function). 
  3445.  
  3446.  See the SOM Programming Reference for more information on a specific function 
  3447.  or method. 
  3448.  
  3449.  
  3450. ΓòÉΓòÉΓòÉ 4.3.2. Getting information about a class ΓòÉΓòÉΓòÉ
  3451.  
  3452. The following methods are used to obtain information about a class or to locate 
  3453. a particular class object: 
  3454.  
  3455.  somCheckVersion          Checks a class for compatibility with the specified 
  3456.                           major and minor version numbers. The receiver of the 
  3457.                           method is the SOM class about which information is 
  3458.                           needed. Additional arguments are values of the major 
  3459.                           and minor version numbers. The method returns TRUE if 
  3460.                           the class is compatible, or FALSE otherwise. 
  3461.  
  3462.  somClassFromId           Finds the class object of an existing class when 
  3463.                           given its somId, but without loading the class. The 
  3464.                           receiver of the method is the class manager (pointed 
  3465.                           to by the global variable SOMClassMgrObject). The 
  3466.                           additional argument is the class's somId. The method 
  3467.                           returns a pointer to the class (or NULL if the class 
  3468.                           does not exist). 
  3469.  
  3470.  somDescendedFrom         Tests whether one class is derived from another. The 
  3471.                           receiver of the method is the class to be tested, and 
  3472.                           the potential ancestor class is the argument. The 
  3473.                           method returns TRUE if the relationships exists, or 
  3474.                           FALSE otherwise. 
  3475.  
  3476.  somFindClass             Finds or creates the class object for a class, given 
  3477.                           the class's somId and its major and minor version 
  3478.                           numbers. The receiver of the method is the class 
  3479.                           manager (pointed to by the global variable 
  3480.                           SOMClassMgrObject). Additional arguments are the 
  3481.                           class's somId and the major and minor version 
  3482.                           numbers. The method returns a pointer to the class 
  3483.                           object, or NULL if the class could not be created. 
  3484.  
  3485.  somFindClsInFile         Finds or creates the class object for a class. This 
  3486.                           method is similar to somFindClass, except the user 
  3487.                           also provides the name of a file to be used for 
  3488.                           dynamic loading, if needed. The receiver of the 
  3489.                           method is the class manager (pointed to by the global 
  3490.                           variable SOMClassMgrObject). Additional arguments are 
  3491.                           the class's somId, the major and minor version 
  3492.                           numbers, and the file name. The method returns a 
  3493.                           pointer to the class object, or NULL if the class 
  3494.                           could not be created. 
  3495.  
  3496.  somGetInstancePartSize   Obtains the size of the instance variables introduced 
  3497.                           by a class. The receiver of the method is the class 
  3498.                           object. The method returns the amount of space, in 
  3499.                           bytes, needed for the instance variables. 
  3500.  
  3501.  somGetInstanceSize       Obtains the total size requirements for an instance 
  3502.                           of a class. The receiver of the method is the class 
  3503.                           object. The method returns the amount of space, in 
  3504.                           bytes, required for the instance variables introduced 
  3505.                           by the class itself and by all of its ancestor 
  3506.                           classes. 
  3507.  
  3508.  somGetName               Obtains the name of a class. The receiver of the 
  3509.                           method is the class object. The method returns the 
  3510.                           class name. 
  3511.  
  3512.  somGetNumMethods         Obtains the number of methods available for a class. 
  3513.                           The receiver of the method is the class object. The 
  3514.                           method returns the total number of currently 
  3515.                           available methods (static or otherwise, including 
  3516.                           inherited methods). 
  3517.  
  3518.  somGetNumStaticMethods   Obtains the number of static methods available for a 
  3519.                           class. (A static method is one declared in the 
  3520.                           class's interface specification [.idl] file.) The 
  3521.                           receiver of the method is the class object. The 
  3522.                           method returns the total number of available static 
  3523.                           methods, including inherited ones. 
  3524.  
  3525.  somGetParents            Obtains a sequence of the parent (base) classes of a 
  3526.                           specified class. The receiver of the method is the 
  3527.                           class object. The method returns a pointer to a 
  3528.                           linked list of the parent (base) classes (unless the 
  3529.                           receiver is SOMObject, for which it returns NULL). 
  3530.  
  3531.  somGetVersionNumbers     Obtains the major and minor version numbers of a 
  3532.                           class. The return type is void, and the two arguments 
  3533.                           are pointers to locations in memory where the method 
  3534.                           can store the major and minor version numbers (of 
  3535.                           type long). 
  3536.  
  3537.  somSupportsMethod        Indicates whether instances of a given class support 
  3538.                           a given method. The receiver of the somSupportsMethod 
  3539.                           method is the class object. The argument is the somId 
  3540.                           for the method in question. The somSupportsMethod 
  3541.                           method returns TRUE if the method is supported, or 
  3542.                           FALSE otherwise. 
  3543.  
  3544.  See the SOM Programming Reference for more information on a specific method. 
  3545.  
  3546.  
  3547. ΓòÉΓòÉΓòÉ 4.3.3. Getting information about an object ΓòÉΓòÉΓòÉ
  3548.  
  3549. The following methods and functions are used to obtain information about an 
  3550. object (instance) or to determine whether a variable holds a valid SOM object. 
  3551.  
  3552.  
  3553. ΓòÉΓòÉΓòÉ 4.3.3.1. Methods ΓòÉΓòÉΓòÉ
  3554.  
  3555.  somGetClass              Gets the class object of a specified object. The 
  3556.                           receiver of the method is the object whose class is 
  3557.                           desired. The method returns a pointer to the object's 
  3558.                           corresponding class object. 
  3559.  
  3560.  somGetClassName          Obtains the class name of an object. The receiver of 
  3561.                           the method is the object whose class name is desired. 
  3562.                           The method returns a pointer to the name of the class 
  3563.                           of which the specified object is an instance. 
  3564.  
  3565.  somGetSize               Obtains the size of an object. The receiver of the 
  3566.                           method is the object. The method returns the amount 
  3567.                           of contiguous space, in bytes, that is needed to hold 
  3568.                           the object itself (not including any additional space 
  3569.                           that the object may be using or managing outside of 
  3570.                           this area). 
  3571.  
  3572.  somIsA                   Determines whether an object is an instance of a 
  3573.                           given class or of one of its descendant classes. The 
  3574.                           receiver of the method is the object to be tested. An 
  3575.                           additional argument is the name of the class to which 
  3576.                           the object will be compared. This method returns TRUE 
  3577.                           if the object is an instance of the specified class 
  3578.                           or if (unlike somIsInstanceOf) it is an instance of 
  3579.                           any descendant class of the given class; otherwise, 
  3580.                           the method returns FALSE. 
  3581.  
  3582.  somIsInstanceOf          Determines whether an object is an instance of a 
  3583.                           specific class (but not of any descendant class).The 
  3584.                           receiver of the method is the object. The argument is 
  3585.                           the name of the class to which the object will be 
  3586.                           compared. The method returns TRUE if the object is an 
  3587.                           instance of the specified class, or FALSE otherwise. 
  3588.  
  3589.  somRespondsTo            Determines whether an object supports a given method. 
  3590.                           The receiver of the method is the object. The 
  3591.                           argument is the somId for the method in question. (A 
  3592.                           somId can be obtained from a string by using the 
  3593.                           somIdFromString function.) The somRespondsTo method 
  3594.                           returns TRUE if the object supports the method, or 
  3595.                           FALSE otherwise. 
  3596.  
  3597.  
  3598. ΓòÉΓòÉΓòÉ 4.3.3.2. Functions ΓòÉΓòÉΓòÉ
  3599.  
  3600.  somIsObj                 Takes as its only argument an address (which may not 
  3601.                           be valid). The function returns TRUE (1) if the 
  3602.                           address contains a valid SOM object, or FALSE (0) 
  3603.                           otherwise. This function is designed to be failsafe. 
  3604.  
  3605.  See the SOM Programming Reference for more information on a specific method or 
  3606.  function. 
  3607.  
  3608.  
  3609. ΓòÉΓòÉΓòÉ 4.3.4. Debugging ΓòÉΓòÉΓòÉ
  3610.  
  3611. The following macros are used to conditionally generate output for debugging. 
  3612. All output generated by these macros is written using the replaceable 
  3613. character-output procedure pointed to by the global variable SOMOutCharRoutine. 
  3614. The default procedure simply writes the character to stdout, but it can be 
  3615. replaced to change the output destination of the methods and functions below. 
  3616. (See Chapter 5 for more information on customizing SOM.) 
  3617.  
  3618. Debugging output is produced or suppressed based on the settings of three 
  3619. global variables, SOM_TraceLevel, SOM_WarnLevel, and SOM_AssertLevel: 
  3620.  
  3621.      SOM_TraceLevel controls the behavior of the <className>MethodDebug macro; 
  3622.  
  3623.      SOM_WarnLevel controls the behavior of the macros SOM_WarnMsg, SOM_TestC, 
  3624.       and SOM_Expect; and 
  3625.  
  3626.      SOM_AssertLevel controls the behavior of the SOM_Assert macro. 
  3627.  
  3628.  Available macros for generating debugging output are as follows: 
  3629.  
  3630.  <className>MethodDebug   (macro for C and C++ programmers using the SOM 
  3631.                           language bindings for <className>) 
  3632.                           The arguments to this macro are a class name and a 
  3633.                           method name. If the SOM_TraceLevel global variable 
  3634.                           has a nonzero value, the <className>MethodDebug macro 
  3635.                           produces a message each time the specified method (as 
  3636.                           defined by the specified class) is executed. This 
  3637.                           macro is typically used within the procedure that 
  3638.                           implements the specified method. (The SOM Compiler 
  3639.                           automatically generates calls to the 
  3640.                           <className>MethodDebug macro within the 
  3641.                           implementation template files it produces.) u To 
  3642.                           suppress method tracing for all methods of a class, 
  3643.                           put the following statement in the implementation 
  3644.                           file after including the header file for the class: 
  3645.  
  3646.                                                     #define <className>MethodDebug(c,m) \
  3647.                                                                        SOM_NoTrace(c,m)
  3648.  
  3649.                           This can yield a slight performance improvement. The 
  3650.                           SOMMTraced metaclass, discussed below, provides a 
  3651.                           more extensive tracing facility that includes method 
  3652.                           parameters and returned values. 
  3653.  
  3654.  SOM_TestC                The SOM_TestC macro takes as an argument a boolean 
  3655.                           expression. If the boolean expression is TRUE 
  3656.                           (nonzero) and SOM_AssertLevel is greater than zero, 
  3657.                           then an informational message is output. If the 
  3658.                           expression is FALSE (zero) and SOM_WarnLevel is 
  3659.                           greater than zero, a warning message is produced. 
  3660.  
  3661.  SOM_WarnMsg              The SOM_WarnMsg macro takes as an argument a 
  3662.                           character string. If the value of SOM_WarnLevel is 
  3663.                           greater than zero, the specified message is output. 
  3664.  
  3665.  SOM_Assert               The SOM_Assert macro takes as arguments a boolean 
  3666.                           expression and an error code (an integer). If the 
  3667.                           boolean expression is TRUE (nonzero) and 
  3668.                           SOM_AssertLevel  is greater than zero, then an 
  3669.                           informational message is output. If the expression is 
  3670.                           FALSE (zero), and the error code indicates a 
  3671.                           warning-level error and SOM_WarnLevel is greater than 
  3672.                           zero, then a warning message is output. If the 
  3673.                           expression is FALSE and the error code indicates a 
  3674.                           fatal error, then an error message is produced and 
  3675.                           the process is terminated. 
  3676.  
  3677.  SOM_Expect               The SOM_Expect macro takes as an argument a boolean 
  3678.                           expression. If the boolean expression is FALSE (zero) 
  3679.                           and SOM_WarnLevel is set to be greater than zero, 
  3680.                           then a warning message is output. If condition is 
  3681.                           TRUE and SOM_AssertLevel is set to be greater than 
  3682.                           zero, then an informational message is output. 
  3683.  
  3684.  See the SOM Programming Reference for more information on a specific macro. 
  3685.  
  3686.  The somDumpSelf and somPrintSelf methods can be useful in testing and 
  3687.  debugging. The somPrintSelf method produces a brief description of an object, 
  3688.  and the somDumpSelf method produces a more detailed description. See the SOM 
  3689.  Programming Reference for more information. 
  3690.  
  3691.  
  3692. ΓòÉΓòÉΓòÉ 4.3.5. Checking the validity of method calls ΓòÉΓòÉΓòÉ
  3693.  
  3694. The C and C++ language bindings include code to check the validity of method 
  3695. calls at run time. If a validity check fails, the SOM_Error macro ends the 
  3696. process. (SOM_Error is described below.) To enable method-call validity 
  3697. checking, place the following directive in the client program prior to any 
  3698. #include directives for SOM header files: 
  3699.  
  3700. #define SOM_TestOn
  3701.  
  3702. Alternatively, the -DSOM_TestOn option can be used when compiling the client 
  3703. program to enable method-call validity checking. 
  3704.  
  3705.  
  3706. ΓòÉΓòÉΓòÉ 4.3.6. Exceptions and error handling ΓòÉΓòÉΓòÉ
  3707.  
  3708. In the classes provided in the SOM run-time library (that is, SOMClass, 
  3709. SOMObject, and SOMClassMgr), error handling is performed by a user-replaceable 
  3710. procedure, pointed to by the global variable SOMError, that produces an error 
  3711. message and an error code and, if appropriate ate, ends the process where the 
  3712. error occurred. (Chapter 5 describes how to customize the error handling 
  3713. procedure.) 
  3714.  
  3715. Each error is assigned a unique integer error code. Errors are grouped into 
  3716. three categories, based on the last digit of the error code: 
  3717.  
  3718.  SOM_Ignore               This category of error represents an informational 
  3719.                           event. The event is considered normal and can be 
  3720.                           ignored or logged at the user's discretion. Error 
  3721.                           codes having a last digit of 2 belong to this 
  3722.                           category. 
  3723.  
  3724.  SOM_Warn                 This category of error represents an unusual 
  3725.                           condition that is not a normal event, but is not 
  3726.                           severe enough to require program termination. Error 
  3727.                           codes having a last digit of 1 belong to this 
  3728.                           category. 
  3729.  
  3730.  SOM_Fatal                This category of error represents a condition that 
  3731.                           should not occur or that would result in loss of 
  3732.                           system integrity if processing were allowed to 
  3733.                           continue. In the default error handling procedure, 
  3734.                           these errors cause the termination of the process in 
  3735.                           which they occur. Error codes having a last digit of 
  3736.                           9 belong to this category. 
  3737.  
  3738.  The various codes for all errors detected by SOM are listed in Appendix A, 
  3739.  "Customer Support and Error Codes." 
  3740.  
  3741.  When errors are encountered in client programs or user defined-classes, the 
  3742.  following two macros can be used to invoke the error-handling procedure: 
  3743.  
  3744.  SOM_Error                The SOM_Error macro takes an error code as its only 
  3745.                           argument and invokes the SOM error handling procedure 
  3746.                           (pointed to by the global variable SOMError) to 
  3747.                           handle the error. The default error handling 
  3748.                           procedure prints a message that includes the error 
  3749.                           code, the name of the source file, and the line 
  3750.                           number where the macro was invoked. If the last digit 
  3751.                           of the error code indicates a serious error (of 
  3752.                           category SOM_Fatal), the process causing the error is 
  3753.                           terminated. (Chapter 5 describes how to customize the 
  3754.                           error handling procedure.) 
  3755.  
  3756.  SOM_Test                 The SOM_Test macro takes a boolean expression as an 
  3757.                           argument. If the expression is TRUE (nonzero) and the 
  3758.                           SOM_AssertLevel is greater than zero, then an 
  3759.                           informational message is output. If the expression is 
  3760.                           FALSE (zero), an error message is produced and the 
  3761.                           program is terminated. 
  3762.  
  3763.  See the SOM Programming Reference for more information on a specific macro. 
  3764.  
  3765.  Other classes provided by the SOMobjects Toolkit (including those in the DSOM, 
  3766.  and Interface Repository frameworks, and the utility classes and metaclasses) 
  3767.  handle errors differently. Rather than invoking SOMError with an error code, 
  3768.  their methods return exceptions via the (Environment *) inout parameter 
  3769.  required by these methods. The following sections describe the exception 
  3770.  declarations, the standard exceptions, and how to set and get exception 
  3771.  information in an Environment structure. 
  3772.  
  3773.  
  3774. ΓòÉΓòÉΓòÉ 4.3.6.1. Exception declarations ΓòÉΓòÉΓòÉ
  3775.  
  3776. As discussed in Chapter 4 in the section entitled "SOM Interface Definition 
  3777. Language," a method may be declared to return zero or more exceptions. IDL 
  3778. exceptions are implemented by simply passing back error information after a 
  3779. method call, as opposed to the "catch/throw" model where an exception is 
  3780. implemented by a long jump or signal. Associated with each type of exception is 
  3781. a name, and optionally, a struct-like data structure for holding error 
  3782. information. A method declares the types of exceptions it may return in a 
  3783. raises expression. 
  3784.  
  3785. Below is an example IDL declaration of a "BAD_FLAG" exception, which may be 
  3786. "raised" by a"checkFlag" method, as part of a "MyObject" interface: 
  3787.  
  3788.    interface MyObject {
  3789.       exception BAD_FLAG { long ErrCode; char Reason[80];}
  3790.  
  3791.       void checkFlag(in unsigned long flag) raises(BAD_FLAG);
  3792.    };
  3793.  
  3794. An exception structure contains whatever information is necessary to help the 
  3795. caller understand the nature of the error. The exception declaration can be 
  3796. treated like a struct definition:  i.e., whatever you can access in an IDL 
  3797. struct, you can access in an exception declaration. Alternatively, the 
  3798. structure can be empty, whereby the exception is just identified by its name. 
  3799.  
  3800. The SOM Compiler will map the exception declaration in the above example to the 
  3801. following C language constructs: 
  3802.  
  3803.    typedef struct BAD_FLAG {
  3804.       long ErrCode;
  3805.       char Reason[80];
  3806.    } BAD_FLAG;
  3807.  
  3808.    #define ex_BAD_FLAG "MyObject::BAD_FLAG"
  3809.  
  3810. When an exception is detected, the "checkFlag" method must call SOMMalloc to 
  3811. allocate a "BAD_FLAG" structure, initialize it with the appropriate error 
  3812. information, and make a call to somSetException (see "Setting an exception 
  3813. value," below) to record the exception value in the Environment structure 
  3814. passed in the method call. The caller, after invoking "checkFlag", can check 
  3815. the Environment structure that was passed to the method to see if there was an 
  3816. exception, and if so, extract the exception value from the Environment (see 
  3817. "Getting an exception value," below.) 
  3818.  
  3819.  
  3820. ΓòÉΓòÉΓòÉ 4.3.6.2. Standard exceptions ΓòÉΓòÉΓòÉ
  3821.  
  3822. In addition to user-defined exceptions (those defined explicitly in an IDL 
  3823. file), there are several predefined exceptions for system run-time errors. A 
  3824. system exception  can be returned on any method call. (That is, they are 
  3825. implicitly declared for every method whose class uses IDL call style, and they 
  3826. do not appear in any raises expressions.) The standard exceptions are listed in 
  3827. Table 2 of Section 4.2, "SOM Interface Definition Language". Most of the 
  3828. predefined system exceptions pertain to Object Request Broker errors. 
  3829. Consequently, these types of exceptions are most likely to occur in DSOM 
  3830. applications (Chapter 6). 
  3831.  
  3832. Each of the standard exceptions has the same structure: an error code (to 
  3833. designate the subcategory of the exception) and a completion status code. For 
  3834. example, the NO_MEMORY standard exception has the following definition: 
  3835.  
  3836.    enum completion_status {YES, NO, MAYBE};
  3837.    exception NO_MEMORY { unsigned long minor;
  3838.                          completion_status completed; };
  3839.  
  3840. The completion status value indicates whether the method was never initiated 
  3841. (NO), completed execution prior to the exception (YES), or the completion 
  3842. status is indeterminate (MAYBE). 
  3843.  
  3844. Since all the standard exceptions have the same structure, file "somcorba.h" 
  3845. (included by "som.h") defines a generic StExcep typedef which can be used 
  3846. instead of the specific typedefs: 
  3847.  
  3848.    typedef struct StExcep {
  3849.         unsigned long minor;
  3850.         completion_status completed;
  3851.    } StExcep;
  3852.  
  3853. The standard exceptions are defined in an IDL module called StExcep, in the 
  3854. file named "stexcep.idl", and the C definitions can be found in "stexcep.h". 
  3855.  
  3856.  
  3857. ΓòÉΓòÉΓòÉ 4.3.6.3. The Environment ΓòÉΓòÉΓòÉ
  3858.  
  3859. The Environment is a data structure that contains environmental information 
  3860. that can be passed between a caller and a called object when a method is 
  3861. executed. For example, it is used to pass information about the user id of a 
  3862. client, to return exception data to the client following a method call, and so 
  3863. on. 
  3864.  
  3865. A pointer to an Environment variable is passed as an argument to method calls 
  3866. (unless the method's class has the callstyle=oidl SOM IDL modifier). The 
  3867. Environment typedef is defined in "som.h", and an instance of the structure is 
  3868. allocated by the caller in any reasonable way: on  the stack (by declaring a 
  3869. local variable and initializing it using the macro SOM_InitEnvironment), 
  3870. dynamically (using the SOM_CreateLocalEnvironment macro), or by calling the 
  3871. somGetGlobalEnvironment function to allocate an Environment structure to be 
  3872. shared by objects running in the same thread. 
  3873.  
  3874. For class libraries that use callstyle=oidl, there is no explicit Environment 
  3875. parameter. For these libraries, exception information may be passed using the 
  3876. per-thread Environment structure returned by the somGetGlobalEnvironment 
  3877. procedure. 
  3878.  
  3879.  
  3880. ΓòÉΓòÉΓòÉ 4.3.6.4. Setting an exception value ΓòÉΓòÉΓòÉ
  3881.  
  3882. To set an exception value in the caller's Environment structure, a method 
  3883. implementation makes a call to the somSetException procedure: 
  3884.  
  3885.    void  somSetException ( Environment *ev,
  3886.                                exception_type major,
  3887.                                string exception_name,
  3888.                                void *params);
  3889.  
  3890. where "ev" is a pointer to the Environment structure passed to the method, 
  3891. "major" is an exception_type, "exception_name" is the string name of the 
  3892. exception (usually the constant defined by the IDL compiler, for example, 
  3893. ex_BAD_FLAG), and "params"  is a pointer to an (initialized) exception 
  3894. structure which must be allocated by SOMMalloc: 
  3895.  
  3896.    typedef enum exception_type {
  3897.       NO_EXCEPTION, USER_EXCEPTION, SYSTEM_EXCEPTION
  3898.    } exception_type;
  3899.  
  3900. It is important to reiterate that somSetException expects the params argument 
  3901. to be a pointer to a structure that was allocated using SOMMalloc. When 
  3902. somSetException is called, the client passes ownership of the exception 
  3903. structure to the SOM run-time environment. The SOM run-time  environment will 
  3904. free the structure when the exception is reset (that is, upon the next call to 
  3905. somSetException), or when the somExceptionFree procedure is called. 
  3906.  
  3907. Note that somSetException simply sets the exception value; it performs no exit 
  3908. processing. If there are multiple calls to somSetException before the method 
  3909. returns, the caller will only see the last exception value. 
  3910.  
  3911.  
  3912. ΓòÉΓòÉΓòÉ 4.3.6.5. Getting an exception value ΓòÉΓòÉΓòÉ
  3913.  
  3914. After a method returns, the calling client program can look at the Environment 
  3915. structure to see if there was an exception. The Environment struct is mostly 
  3916. opaque, except for an exception type field named _major: 
  3917.  
  3918.    typedef struct Environment {
  3919.       exception_type   _major;
  3920.       ...
  3921.    } Environment;
  3922.  
  3923. If ev._major != NO_EXCEPTION, there was an exception returned by the call. The 
  3924. caller can retrieve the exception name and value (passed as parameters in the 
  3925. somSetException call) from an Environment struct via the following functions: 
  3926.  
  3927.       string somExceptionId (Environment *ev); 
  3928.  
  3929.       somToken somExceptionValue (Environment *ev); 
  3930.  
  3931.  The somExceptionId function returns the exception name, if any, as a string. 
  3932.  The function somExceptionValue returns a pointer to the value of the 
  3933.  exception, if any, contained in the exception structure. If NULL is passed as 
  3934.  the Environment pointer in either of the above calls, an implicit call is made 
  3935.  to somGetGlobalEnvironment. 
  3936.  
  3937.  The somExceptionFree procedure will free any memory in the Environment 
  3938.  associated with the last exception: 
  3939.  
  3940.       void  somExceptionFree (Environment *ev); 
  3941.  
  3942.  If preferred, developers can alternatively use the CORBA "exception_free" API 
  3943.  to free the memory in an Environment structure. 
  3944.  
  3945.  Note: File "somcorba.h" (included by "som.h") provides the following aliases 
  3946.  for strict compliance with CORBA programming interfaces: 
  3947.  
  3948.      #ifdef CORBA_FUNCTION_NAMES
  3949.      #define exception_id    somExceptionId
  3950.      #define exception_value somExceptionValue
  3951.      #define exception_free  somExceptionFree
  3952.      #endif /* CORBA_FUNCTION_NAMES */
  3953.  
  3954.  
  3955. ΓòÉΓòÉΓòÉ 4.3.6.6. Example ΓòÉΓòÉΓòÉ
  3956.  
  3957. Let us define an IDL interface for a "MyObject" object, which declares a 
  3958. "BAD_FLAG" exception, which can be raised by the "checkFlag"method, in a file 
  3959. called "myobject.idl": 
  3960.  
  3961.    interface MyObject {
  3962.      exception BAD_FLAG { long ErrCode;   char Reason[80]; }
  3963.  
  3964.      void checkFlag(in unsigned long flag) raises(BAD_FLAG);
  3965.    };
  3966.  
  3967. The SOM IDL compiler will map the exception to the following C language 
  3968. constructs, in myobject.h: 
  3969.  
  3970.    typedef struct BAD_FLAG {
  3971.       long ErrCode;
  3972.       char Reason[80];
  3973.    } BAD_FLAG;
  3974.  
  3975.    #define ex_BAD_FLAG "MyObject::BAD_FLAG"
  3976.  
  3977. A client program that invokes the "checkFlag" method might contain the 
  3978. following error handling code.  (Note: The error checking code below lies in 
  3979. the user-written procedure, "ErrorCheck," so the code need not be replicated 
  3980. through the program.) 
  3981.  
  3982. size='auto'.
  3983.    #include "som.h"
  3984.    #include "myobject.h"
  3985.    boolean ErrorCheck(Environment *ev);   /* prototype */
  3986.  
  3987.    main()
  3988.    {
  3989.        unsigned long flag;
  3990.        Environment ev;
  3991.        MyObject myobj;
  3992.        char     *exId;
  3993.        BAD_FLAG *badFlag;
  3994.        StExcep  *stExValue;
  3995.  
  3996.        myobj = MyObjectNew();
  3997.        flag  = 0x01L;
  3998.        SOM_InitEnvironment(&ev);
  3999.  
  4000.         /* invoke the checkFlag method, passing the Environment param */
  4001.        _checkFlag(myobj, &ev, flag);
  4002.  
  4003.        /* check for exception */
  4004.        if (ErrorCheck(&ev))
  4005.        {
  4006.           /* ... */
  4007.           somExceptionFree(&ev);   /* free the exception memory */
  4008.        }
  4009.  
  4010.        /* ... */
  4011.    }
  4012.  
  4013.    /* error checking procedure */
  4014.    boolean ErrorCheck(Environment *ev)
  4015.    {
  4016.      switch (ev._major)
  4017.      {
  4018.      case SYSTEM_EXCEPTION:
  4019.        /* get system exception id and value */
  4020.        exId      =  somExceptionId(ev);
  4021.        stExValue =  somExceptionValue(ev);
  4022.        /* ... */
  4023.        return( TRUE);
  4024.  
  4025.      case USER_EXCEPTION:
  4026.        /* get user-defined exception id and value */
  4027.        exId =  somExceptionId(ev);
  4028.        if (strcmp(exId, ex_BAD_FLAG) == 0)
  4029.        {
  4030.           badFlag = (BAD_FLAG *)  somExceptionValue(ev);
  4031.           /* ... */
  4032.        }
  4033.        /* ... */
  4034.        return( TRUE);
  4035.  
  4036.      case NO_EXCEPTION:
  4037.        return( FALSE);
  4038.      }
  4039.    }
  4040.  
  4041. The implementation of the "checkFlag" method might contain the following 
  4042. error-handling code: 
  4043.  
  4044.    #include "som.h"
  4045.    #include "myobject.h"
  4046.  
  4047.    void  checkFlag(MyObject somSelf, Environment *ev,
  4048.                    unsigned long flag)
  4049.    {
  4050.       BAD_FLAG *badFlag;
  4051.       /* ... */
  4052.  
  4053.       if ( /* flag is invalid */ )
  4054.       {
  4055.          badFlag = (BAD_FLAG *) SOMMalloc(sizeof(BAD_FLAG));
  4056.          badFlag->ErrCode = /* bad flag code */;
  4057.          strcpy(badFlag->Reason, "bad flag was passed");
  4058.          somSetException(ev, USER_EXCEPTION,
  4059.                          ex_BAD_FLAG, (void *)badFlag);
  4060.          return;
  4061.       }
  4062.       /* ... */
  4063.    }
  4064.  
  4065.  
  4066. ΓòÉΓòÉΓòÉ 4.3.7. Memory management ΓòÉΓòÉΓòÉ
  4067.  
  4068. The memory management functions used by SOM are a subset of those supplied in 
  4069. the ANSI C standard library. They have the same calling interface and the same 
  4070. return types as their ANSI C equivalents, but include supplemental error 
  4071. checking. Errors detected by these functions are passed to SOMError (described 
  4072. in the previous section). The correspondence between SOM memory management 
  4073. functions and their ANSI C standard library equivalents is shown below: 
  4074.  
  4075. ΓöîΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÉ
  4076. Γöé SOM FUNCTION             Γöé EQUIVALENT ANSI C LIBRARY ROUTINE  Γöé
  4077. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  4078. Γöé SOMMALLOC              Γöé MALLOC                Γöé
  4079. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  4080. Γöé SOMCALLOC              Γöé CALLOC                Γöé
  4081. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  4082. Γöé SOMREALLOC              Γöé REALLOC               Γöé
  4083. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  4084. Γöé SOMFREE               Γöé FREE                 Γöé
  4085. ΓööΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÿ
  4086.  
  4087. SOMMalloc, SOMCalloc, SOMRealloc, and SOMFree are actually global variables 
  4088. that point to the SOM memory management functions (rather than being the names 
  4089. of the functions themselves), so that users can replace them with their own 
  4090. memory management functions if desired. (See chapter 5 for a discussion of 
  4091. replacing the SOM memory management functions.) 
  4092.  
  4093. Clearing memory for objects 
  4094.  
  4095. The memory associated with objects initialized by a client program must also be 
  4096. freed by the client.  The SOM-provided method somFree  is used to release the 
  4097. storage containing the receiver object: 
  4098.  
  4099.  #include "origcls.h"
  4100.  
  4101. main ()
  4102. {
  4103.    OrigCls myObject;
  4104.    myObject = OrigClsNew ();
  4105.  
  4106.     /*  Code to use myObject  */
  4107.     _somFree (myObject);
  4108. {
  4109.  
  4110. Clearing memory for the Environment 
  4111.  
  4112. Any memory associated with an exception in an Environment structure is 
  4113. typically freed using the somExceptionFree function. (Or, the CORBA 
  4114. "exception_free" API can be used.) The somExceptionFree function takes the 
  4115. following form (also see "Example" in the previous topic for an application 
  4116. example): 
  4117.  
  4118.   void somExceptionFree(Environment *ev);
  4119.  
  4120. Note: For information on managing the memory, objects, and exceptions used by 
  4121. DSOM applications, see "Memory management" in Chapter 6, "Distributed SOM 
  4122. (DSOM)." 
  4123.  
  4124.  
  4125. ΓòÉΓòÉΓòÉ 4.3.8. SOM manipulations using somId's ΓòÉΓòÉΓòÉ
  4126.  
  4127. A somId is similar to a number that represents a zero-terminated string. A 
  4128. somId is used in SOM to identify method names, class names, and so forth. For 
  4129. example, many of the SOM methods that take a method or class name as a 
  4130. parameter require a value of type somId rather than string. All SOM 
  4131. manipulations using somIds are case insensitive, although the original case of 
  4132. the string is preserved. 
  4133.  
  4134. During its first use with any of the following functions, a somId is 
  4135. automatically converted to an internal representation (registered). Because the 
  4136. representation of a somId changes, a special SOM type (somId) is provided for 
  4137. this purpose. Names and the corresponding somId can be declared at compile 
  4138. time, as follows: 
  4139.  
  4140.    string example = "exampleMethodName";
  4141.    somId exampleId = &example;
  4142.  
  4143. or a somId can be generated at run time, as follows: 
  4144.  
  4145.    somId myMethodId;
  4146.    myMethodId = somIdFromString("exampleMethodName");
  4147.  
  4148. SOM provides the following functions that generate or use a somId: 
  4149.  
  4150.  somIdFromString          Finds the somId that corresponds to a string. The 
  4151.                           method takes a string as its argument, and returns a 
  4152.                           value of type somId that represents the string. The 
  4153.                           returned somId must later be freed using SOMFree. 
  4154.  
  4155.  somStringFromId          Obtains the string that corresponds to a somId. The 
  4156.                           function takes a somId as its argument and returns 
  4157.                           the string that the somId represents. 
  4158.  
  4159.  somCompareIds            Determines whether two somId values are the same 
  4160.                           (that is, represent the same string). This function 
  4161.                           takes two somId values as arguments. It returns TRUE 
  4162.                           (1) if the somIds represent the same string, or FALSE 
  4163.                           (0) otherwise. 
  4164.  
  4165.  somCheckId               Determines whether SOM already knows a somId. The 
  4166.                           function takes a somId as its argument. It verifies 
  4167.                           whether the somId is registered and in normal form, 
  4168.                           registers it if necessary, and returns the input 
  4169.                           somId. 
  4170.  
  4171.  somRegisterId            The same as somCheckId, except it returns TRUE (1) if 
  4172.                           this is the first time the somId has been registered, 
  4173.                           or FALSE (0) otherwise. 
  4174.  
  4175.  somUniqueKey             Finds the unique key for a somId. The function takes 
  4176.                           a somId identifier as its argument, and returns the 
  4177.                           unique key for the somId-a number that uniquely 
  4178.                           represents the string that the somId represents. This 
  4179.                           key is the same as the key for another somId if and 
  4180.                           only if the other somId refers to the same string as 
  4181.                           the input somId. 
  4182.  
  4183.  somTotalRegIds           Finds the total number of somIds that have been 
  4184.                           registered, as an unsigned long. This function is 
  4185.                           used to determine an appropriate argument to 
  4186.                           somSetExpectedIds, below, in later executions of the 
  4187.                           program. The function takes no input arguments. 
  4188.  
  4189.  somSetExpectedIds        Indicates how many unique somIds SOM can expect to 
  4190.                           use during program execution, which, if accurate, can 
  4191.                           improve the space and time utilization of the program 
  4192.                           slightly. This routine must be called before the SOM 
  4193.                           run-time environment is initialized (that is, before 
  4194.                           the function somEnvironmentNew is invoked and before 
  4195.                           any objects are created). This is the only SOM 
  4196.                           function that can be invoked before the SOM run-time 
  4197.                           environment is initialized. The input argument is an 
  4198.                           unsigned long. The function has no return value. 
  4199.  
  4200.  See the SOM Programming Reference for more information on a specific function. 
  4201.  
  4202.  
  4203. ΓòÉΓòÉΓòÉ 5. SOM IDL and the SOM Compiler ΓòÉΓòÉΓòÉ
  4204.  
  4205. This chapter first discusses how to define SOM classes and then describes the 
  4206. SOM Compiler. To allow a class of objects to be implemented in one programming 
  4207. language and used in another (that is, to allow a SOM class to be language 
  4208. neutral), the interface to objects of this class must be specified separately 
  4209. from the objects' implementation. 
  4210.  
  4211. To summarize:  As a first step, a file known as the .idl file is used to 
  4212. declare classes and their methods, using SOM's language#neutral Interface 
  4213. Definition Language (IDL). Next, the SOM Compiler is run on the .idl file to 
  4214. produce a template implementation file that contains stub method procedures for 
  4215. the new and overridden methods; this preliminary code corresponds to the 
  4216. computer language that will implement the class. Then, the class implementer 
  4217. fills in the stub procedures with code that implements the methods (or 
  4218. redefines overridden methods) and sets instance data. (This implementation 
  4219. process is the subject of Chapter 5, "Implementing Classes in SOM.") At this 
  4220. point, the implementation file can be compiled and linked with a client program 
  4221. that uses it (as described in Chapter 3, "Using SOM Classes in Client 
  4222. Programs"). 
  4223.  
  4224. Syntax for SOM IDL and the SOM Compiler are presented in this chapter, along 
  4225. with helpful information for using them correctly. 
  4226.  
  4227.  
  4228. ΓòÉΓòÉΓòÉ 5.1. Interface vs Implementation ΓòÉΓòÉΓòÉ
  4229.  
  4230. The interface to a class of objects contains the information that a client must 
  4231. know to use an object-namely, the names of its attributes and the signatures of 
  4232. its methods.  The interface is described in a formal language independent of 
  4233. the programming language used to implement the object's methods. In SOM, the 
  4234. formal language used to define object interfaces is the Interface Definition 
  4235. Language (IDL), standardized by CORBA. 
  4236.  
  4237. The implementation of a class of objects (that is, the procedures that 
  4238. implement methods) is written in the implementer's preferred programming 
  4239. language. This language can be object-oriented (for instance, C++) or 
  4240. procedural (for instance, C). 
  4241.  
  4242. A completely implemented class definition, then, consists of two main files: 
  4243.  
  4244.      An IDL specification of the interface to instances of the class (the 
  4245.       interface definition file (or .idl file) and 
  4246.  
  4247.      Method procedures written in the implementer's language of choice (the 
  4248.       implementation file). 
  4249.  
  4250.  The interface definition file has an .idl extension, as noted. The 
  4251.  implementation file, however, has an extension specific to the language in 
  4252.  which it is written. For example, implementations written in C have a .c 
  4253.  extension, and implementations written in C++ have a .cpp extension. 
  4254.  
  4255.  To assist users in implementing SOM classes, the SOMobjects Toolkit provides a 
  4256.  SOM Compiler. The SOM Compiler takes as input an object interface definition 
  4257.  file  (the .idl file) and produces a set of binding files that make it 
  4258.  convenient to implement and use a SOM class whose instances are objects that 
  4259.  support the defined interface. The binding files and their purposes are as 
  4260.  follows: 
  4261.  
  4262.      An implementation template that serves as a guide for how the 
  4263.       implementation file for the class should look. The class implementer 
  4264.       fills in this template file with language-specific code to implement the 
  4265.       methods that are available on the class' instances. 
  4266.  
  4267.      Header files to be included (a) in the class's implementation file and 
  4268.       (b) in client programs that use the class. 
  4269.  
  4270.  These binding files produced by the SOM Compiler bridge the gap between  SOM 
  4271.  and the object model used in object-oriented languages (such as C++), and they 
  4272.  allow SOM to be used with non-object-oriented languages (such as C). The SOM 
  4273.  Compiler currently produces binding files for the C and C++ programming 
  4274.  languages. SOM can also be used with other programming languages; the bindings 
  4275.  simply offer a more convenient programmer's interface to SOM. Vendors of other 
  4276.  languages may also offer SOM bindings; check with your language vendor for 
  4277.  possible SOM support. 
  4278.  
  4279.  The subsequent sections of this chapter provide full syntax for SOM IDL and 
  4280.  the SOM Compiler. 
  4281.  
  4282.  
  4283. ΓòÉΓòÉΓòÉ 5.2. SOM Interface Definition Language ΓòÉΓòÉΓòÉ
  4284.  
  4285. This section describes the syntax of SOM's Interface Definition Language (SOM 
  4286. IDL). SOM IDL complies with CORBA's standard for IDL; it also adds constructs 
  4287. specific to SOM. (For more information on the CORBA standard for IDL, see The 
  4288. Common Object Request Broker: Architecture and Specification, published by 
  4289. Object Management Group and x/Open.) The full grammar for SOM IDL is given in 
  4290. Appendix C. Instructions for converting existing OIDL-syntax files to IDL are 
  4291. given in Appendix B. The current section describes the syntax and semantics of 
  4292. SOM IDL using the following conventions: 
  4293.  
  4294.       Constants (words to be used literally, such as keywords) appear in bold. 
  4295.       User-supplied elements appear in italics. 
  4296.       { }       Groups related items together as a single item. 
  4297.  
  4298.       [ ]       Encloses an optional item. 
  4299.  
  4300.       *         Indicates zero or more repetitions of the preceding item. 
  4301.  
  4302.       +         Indicates one or more repetitions of the preceding item. 
  4303.  
  4304.       |         Separates alternatives. 
  4305.  
  4306.       _         Within a set of alternatives, an underscore indicates the 
  4307.                 default, if defined. 
  4308.  
  4309.  IDL is a formal language used to describe object interfaces. Because, in SOM, 
  4310.  objects are implemented as instances of classes, an IDL object interface 
  4311.  definition specifies for a class of objects what methods (operations) are 
  4312.  available, their return types, and their parameter types. For this reason, we 
  4313.  often speak of an IDL specification for a class (as opposed to simply an 
  4314.  object interface). Constructs specific to SOM discussed below further 
  4315.  strengthen this connection between SOM classes and the IDL language. 
  4316.  
  4317.  IDL generally follows the same lexical rules as C and C++, with some 
  4318.  exceptions. In particular: 
  4319.  
  4320.      IDL uses the ISO Latin-1 (8859.1) character set (as per the CORBA 
  4321.       standard). 
  4322.  
  4323.      White space is ignored except as token delimiters. 
  4324.  
  4325.      C and C++ comment styles are supported. 
  4326.  
  4327.      IDL supports standard C/C++ preprocessing, including macro substitution, 
  4328.       conditional compilation, and source file inclusion. 
  4329.  
  4330.      Identifiers (user-defined names for methods, attributes, instance 
  4331.       variables, and so on) are composed of alphanumeric and underscore 
  4332.       characters, (with the first character alphabetic) and can be of arbitrary 
  4333.       length, up to an operating-system limit of about 250 characters. 
  4334.  
  4335.      Identifiers must be spelled consistently with respect to case throughout 
  4336.       a specification. 
  4337.  
  4338.      Identifiers that differ only in case yield a compilation error. 
  4339.  
  4340.      There is a single name space for identifiers (thus, using the same 
  4341.       identifier for a constant and a class name within the same naming scope, 
  4342.       for example, yields a compilation error). 
  4343.  
  4344.      Integer, floating point, character, and string literals are defined just 
  4345.       as in C and C++. 
  4346.  
  4347.  The terms listed in the Keywords table are reserved keywords and may not be 
  4348.  used otherwise. Keywords must be spelled using upper- and lower-case 
  4349.  characters exactly as shown in the table. For example, "void" is correct, but 
  4350.  "Void" yields a compilation error. 
  4351.  
  4352.  A typical IDL specification for a single class, residing in a single .idl 
  4353.  file, has the following form. (Also see the later section, "Module 
  4354.  declarations to define multiple interfaces in an .idl file.") The order is 
  4355.  unimportant, except that names must be declared (or forward referenced) before 
  4356.  they are referenced. The subsequent topics of this section describe the 
  4357.  requirements for these specifications: 
  4358.  
  4359.  Include directives       (optional) 
  4360.  
  4361.  Type declarations        (optional) 
  4362.  
  4363.  Constant declarations    (optional) 
  4364.  
  4365.  Exception declarations   (optional) 
  4366.  
  4367.  Interface declaration    (optional) 
  4368.  
  4369.  Module declaration       (optional) 
  4370.  
  4371.                           Keywords for SOM IDL 
  4372.  
  4373.                                                     ΓöîΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÉ
  4374.                                                     Γöé any           Γöé FALSE           Γöé readonly         Γöé
  4375.                                                     Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  4376.                                                     Γöé attribute        Γöé float           Γöé sequence         Γöé
  4377.                                                     Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  4378.                                                     Γöé boolean         Γöé implementation      Γöé short          Γöé
  4379.                                                     Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  4380.                                                     Γöé case           Γöé in            Γöé string          Γöé
  4381.                                                     Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  4382.                                                     Γöé char           Γöé inout           Γöé struct          Γöé
  4383.                                                     Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  4384.                                                     Γöé class          Γöé interface         Γöé switch          Γöé
  4385.                                                     Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  4386.                                                     Γöé const          Γöé long           Γöé TRUE           Γöé
  4387.                                                     Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  4388.                                                     Γöé context         Γöé module          Γöé TypeCode         Γöé
  4389.                                                     Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  4390.                                                     Γöé default         Γöé octet           Γöé typedef         Γöé
  4391.                                                     Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  4392.                                                     Γöé double          Γöé oneway          Γöé unsigned         Γöé
  4393.                                                     Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  4394.                                                     Γöé enum           Γöé out            Γöé union          Γöé
  4395.                                                     Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  4396.                                                     Γöé exception        Γöé raises          Γöé void           Γöé
  4397.                                                     ΓööΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÿ
  4398.  
  4399.  
  4400. ΓòÉΓòÉΓòÉ 5.2.1. Include directives ΓòÉΓòÉΓòÉ
  4401.  
  4402. The IDL specification for a class normally contains #include statements that 
  4403. tell the SOM Compiler where to find the interface definitions (the .idl files) 
  4404. for: 
  4405.  
  4406.      Each of the class's parent (direct base) classes, and 
  4407.      The class's metaclass (if specified). 
  4408.  
  4409.  The #include statements must appear in the above order. For example, if class 
  4410.  "C" has parents "foo" and "bar" and metaclass "meta", then file "C.idl" must 
  4411.  begin with the following #include statements: 
  4412.  
  4413.      #include <foo.idl>
  4414.      #include <bar.idl>
  4415.      #include <meta.idl>
  4416.  
  4417.  As in C and C++, if a filename is enclosed in angle brackets (< >), the search 
  4418.  for the file will begin in system-specific locations. If the filename appears 
  4419.  in double quotation marks (" "), the search for the file will begin in the 
  4420.  current working directory, then move to the system-specific locations. 
  4421.  
  4422.  
  4423. ΓòÉΓòÉΓòÉ 5.2.2. Type and constant declarations ΓòÉΓòÉΓòÉ
  4424.  
  4425. IDL specifications may include type declarations and constant declarations as 
  4426. in C and C++, with the restrictions/extensions described below.  [Note: For any 
  4427. reader not familiar with C, a recommended reference is The C Programming 
  4428. Language (2nd edition, 1988, Prentice Hall) by Brian W. Kernighan and Dennis M. 
  4429. Ritchie. See pages 36-40 for a discussion of type and constant declarations.] 
  4430.  
  4431. IDL supports the following basic types (these basic types are also defined for 
  4432. C and C++ client and implementation programs, using the SOM bindings): 
  4433.  
  4434.  
  4435. ΓòÉΓòÉΓòÉ 5.2.2.1. Integral types ΓòÉΓòÉΓòÉ
  4436.  
  4437. IDL supports only the integral types short,  long, unsigned short, and unsigned 
  4438. long, which represent the following value ranges: 
  4439.  
  4440.  short                    -2[15] .. 2[15]-1 
  4441.  long                     -2[31] .. 2[31]-1 
  4442.  unsigned short           0 .. 2[16]-1 
  4443.  unsigned long            0 .. 2[32]-1 
  4444.  
  4445.  
  4446. ΓòÉΓòÉΓòÉ 5.2.2.2. Floating point types ΓòÉΓòÉΓòÉ
  4447.  
  4448. IDL supports the float and double floating-point types. The float type 
  4449. represents the IEEE single-precision floating-point numbers; double represents 
  4450. the IEEE double-precision floating-point numbers. 
  4451.  
  4452.  
  4453. ΓòÉΓòÉΓòÉ 5.2.2.3. Character type ΓòÉΓòÉΓòÉ
  4454.  
  4455. IDL supports a char type, which represents an 8-bit quantity. The ISO Latin-1 
  4456. (8859.1) character set defines the meaning and representation of graphic 
  4457. characters. The meaning and representation of null and formatting characters is 
  4458. the numerical value of the character as defined in the ASCII (ISO 646) 
  4459. standard. Unlike C/C++, type char cannot be qualified as signed or unsigned. 
  4460. (The octet type, below, can be used in place of unsigned char.) 
  4461.  
  4462.  
  4463. ΓòÉΓòÉΓòÉ 5.2.2.4. Boolean type ΓòÉΓòÉΓòÉ
  4464.  
  4465. IDL supports a boolean type for data items that can take only the values TRUE 
  4466. and FALSE. 
  4467.  
  4468.  
  4469. ΓòÉΓòÉΓòÉ 5.2.2.5. Octet type ΓòÉΓòÉΓòÉ
  4470.  
  4471. IDL supports an octet type, an 8-bit quantity guaranteed not to undergo 
  4472. conversion when transmitted by the communication system. The octet type can be 
  4473. used in place of the unsigned char type. 
  4474.  
  4475.  
  4476. ΓòÉΓòÉΓòÉ 5.2.2.6. Any type ΓòÉΓòÉΓòÉ
  4477.  
  4478. IDL supports an any type, which permits the specification of values of any IDL 
  4479. type. In the SOM C and C++ bindings, the any type is mapped onto the following 
  4480. struct: 
  4481.  
  4482.    typedef struct any {
  4483.        TypeCode _type;
  4484.        void *_value;
  4485.    } any;
  4486.  
  4487. The "_value" member for an any type is a pointer to the actual value. The 
  4488. "_type" member is a pointer to an instance of a TypeCode that represents the 
  4489. type of the value. The TypeCode provides functions for obtaining information 
  4490. about an IDL type. Chapter 7, "The Interface Repository Framework," describes 
  4491. TypeCodes and their associated functions. 
  4492.  
  4493.  
  4494. ΓòÉΓòÉΓòÉ 5.2.2.7. Constructed types ΓòÉΓòÉΓòÉ
  4495.  
  4496. In addition to the above basic types, IDL also supports three constructed 
  4497. types: struct, union, and enum. The structure and enumeration types are 
  4498. specified in IDL the same as they are in C and C++ [Kernighan-Ritchie 
  4499. references: struct, p. 128; union, p. 147; enum, p. 39], with the following 
  4500. restrictions: 
  4501.  
  4502.       Unlike C/C++, recursive type specifications are allowed only through the 
  4503.       use of the sequence template type (see below). 
  4504.  
  4505.       Unlike C/C++, structures, discriminated unions, and enumerations in IDL 
  4506.       must be tagged. For example, "struct { int a; ... }" is an invalid type 
  4507.       specification. The tag introduces a new type name. 
  4508.  
  4509.       In IDL, constructed type definitions need not be part of a typedef 
  4510.       statement; furthermore, if they are part of a typedef statement, the tag 
  4511.       of the struct must differ from the type name being defined by the 
  4512.       typedef. For example, the following are valid IDL struct and enum 
  4513.       definitions: 
  4514.  
  4515.                struct myStruct {
  4516.                   long x;
  4517.                   double y;
  4518.                };                               /* defines type name myStruct*/
  4519.  
  4520.                enum colors { red, white, blue };  /* defines type name colors */
  4521.  
  4522.       By contrast, the following definitions are not valid: 
  4523.  
  4524.                typedef struct myStruct {        /*  NOT VALID  */
  4525.                   long x;
  4526.                   double y;
  4527.                } myStruct;                      /* myStruct has been redefined */
  4528.  
  4529.                typedef enum colors { red, white, blue } colors;  /* NOT VALID */
  4530.  
  4531.  The valid IDL struct and enum definitions shown above are translated by the 
  4532.  SOM Compiler into the following definitions in the C and C++ bindings, 
  4533.  assuming they were declared within the scope of interface "Hello": 
  4534.  
  4535.      typedef struct Hello_myStruct {  /* C/C++ bindings for IDL struct */
  4536.         long x;
  4537.         double y;
  4538.      } Hello_myStruct;
  4539.  
  4540.      typedef unsigned long Hello_colors; /* C/C++ bindings for IDL enum */
  4541.      #define Hello_red 1UL
  4542.      #define Hello_white 2UL
  4543.      #define Hello_blue 3UL
  4544.  
  4545.  When an enumeration is defined within an interface statement for a class, then 
  4546.  within C/C++ programs, the enumeration names must be referenced by prefixing 
  4547.  the class name. For example, if the colors enum, above, were defined within 
  4548.  the interface statement for class Hello, then the enumeration names would be 
  4549.  referenced as Hello_red, Hello_white, and Hello_blue. Notice the first 
  4550.  identifier in an enumeration is assigned the value 1. 
  4551.  
  4552.  All types and constants generated by the SOM Compiler are fully qualified. 
  4553.  That is, prepended to them is the fully qualified name of the interface or 
  4554.  module in which they appear.  For example, consider the following fragment of 
  4555.  IDL: 
  4556.  
  4557.      module M {
  4558.          typedef long long_t;
  4559.          module  N {
  4560.              typedef long long_t;
  4561.              interface I {
  4562.                  typedef long long_t;
  4563.              };
  4564.          };
  4565.      };
  4566.  
  4567.  That specification would generate the following three types: 
  4568.  
  4569.      typedef long  M_long_t;
  4570.      typedef long  M_N_long_t;
  4571.      typedef long  M_N_I_long_t;
  4572.  
  4573.  For programmer convenience, the SOM Compiler also generates shorter bindings, 
  4574.  without the interface qualification. Consider the next IDL fragment: 
  4575.  
  4576.      module M {
  4577.          typedef long long_t;
  4578.          module  N {
  4579.              typedef short short_t;
  4580.              interface I {
  4581.                  typedef char char_t;
  4582.              };
  4583.          };
  4584.      };
  4585.  
  4586.  In the C/C++ bindings of the preceding fragment, you can refer to "M_long_t" 
  4587.  as "long_t", to "M_N_short_t" as "short_t", and to "M_N_I_char_t" as "char_t". 
  4588.  
  4589.  However, these shorter forms are available only when their interpretation is 
  4590.  not ambiguous. Thus, in the first example the shorthand for "M_N_I_long_t" 
  4591.  would not be allowed, since it clashes with "M_long_t" and "M_N_long_t". If 
  4592.  these shorter forms are not required, they can be ignored by setting #define 
  4593.  SOM_DONT_USE_SHORT_NAMES before including the public header files, or by using 
  4594.  the SOM Compiler option -mnouseshort so that they are not generated in the 
  4595.  header files. 
  4596.  
  4597.  In the SOM documentation and samples, both long and short forms are 
  4598.  illustrated, for both type names and method calls. It is the responsibility of 
  4599.  each user to adopt a style according to personal preference. It should be 
  4600.  noted, however, that CORBA specifies that only the long forms must be present. 
  4601.  
  4602.  
  4603. ΓòÉΓòÉΓòÉ 5.2.2.7.1. Union type ΓòÉΓòÉΓòÉ
  4604.  
  4605. IDL also supports a union type, which is a cross between the C union and switch 
  4606. statements. The syntax of a union type declaration is as follows: 
  4607.  
  4608. union identifier switch ( switch-type )
  4609.   { case+ }
  4610.  
  4611. The "identifier" following the union keyword defines a new legal type. (Union 
  4612. types may also be named using a typedef declaration.) The "switch-type" 
  4613. specifies an integral, character, boolean, or enumeration type, or the name of 
  4614. a previously defined integral, boolean, character, or enumeration type. Each 
  4615. "case" of the union is specified with the following syntax: 
  4616.  
  4617. case-label+  type-spec  declarator ; 
  4618.  
  4619. where "type-spec" is any valid type specification; "declarator" is an 
  4620. identifier, an array declarator (such as, foo[3][5]), or a pointer declarator 
  4621. (such as, *foo); and each "case-label" has one of the following forms: 
  4622.  
  4623. case const-expr: 
  4624. default: 
  4625.  
  4626. The "const-expr" is a constant expression that must match or be automatically 
  4627. castable to the "switch-type". A default case can appear no more than once. 
  4628.  
  4629. Unions are mapped onto C/C++ structs. For example, the following IDL 
  4630. declaration: 
  4631.  
  4632.    union Foo switch (long) {
  4633.      case 1: long x;
  4634.      case 2: float y;
  4635.      default: char z;
  4636.    };
  4637.  
  4638. is mapped onto the following C struct: 
  4639.  
  4640.    typedef Hello_struct {
  4641.      long _d;
  4642.      union {
  4643.        long x;
  4644.        float y;
  4645.        char z;
  4646.      } _u;
  4647.    } Hello_foo;
  4648.  
  4649. The discriminator is referred to as "_d", and the union in the struct is 
  4650. referred to as "_u". Hence, elements of the union are referenced just as in C: 
  4651.  
  4652.    Foo v;
  4653.  
  4654.    /* get a pointer to Foo in v: */
  4655.    switch(v->_d) {
  4656.      case 1: printf("x = %ld\n", v->_u.x); break;
  4657.      case 2: printf("y = %f\n", v->_u.y); break;
  4658.      default: printf("z = %c\n", v->_u.z); break;
  4659.    }
  4660.  
  4661. Note: This example is from The Common Object Request Broker: Architecture and 
  4662. Specification, revision 1.1, page 90. 
  4663.  
  4664.  
  4665. ΓòÉΓòÉΓòÉ 5.2.2.8. Template types (sequences and strings) ΓòÉΓòÉΓòÉ
  4666.  
  4667. IDL defines two template types not found in C and C++: sequences and strings. A 
  4668. sequence is a one-dimensional array with two characteristics:  a maximum size 
  4669. (specified at compile time) and a length (determined at run time). Sequences 
  4670. permit passing unbounded arrays between objects. Sequences are specified as 
  4671. follows: 
  4672.  
  4673. sequence < simple-type [, positive-integer-const] > 
  4674.  
  4675. where "simple-type" specifies any valid IDL type, and the optional 
  4676. "positive-integer-const" is a constant expression that specifies the maximum 
  4677. size of the sequence (as a positive integer). 
  4678.  
  4679. Note: The "simple-type" cannot have a `*' directly in the sequence statement. 
  4680. Instead, a typedef for the pointer type must be used. For example, instead of: 
  4681.  
  4682.    typedef sequence<long *> seq_longptr; // Error: '*' not allowed.
  4683.  
  4684. use: 
  4685.  
  4686.    typedef long * longptr;
  4687.    typedef sequence<longptr> seq_longptr;  // Ok.
  4688.  
  4689. In SOM's C and C++ bindings, sequences  are mapped onto structs with the 
  4690. following members: 
  4691.  
  4692.       unsigned long _maximum; 
  4693.       unsigned long _length; 
  4694.       simple-type *_buffer; 
  4695.  
  4696.  where "simple-type" is the specified type of the sequence.  For example, the 
  4697.  IDL declaration 
  4698.  
  4699.      typedef sequence<long, 10> vec10;
  4700.  
  4701.  results in the following C struct: 
  4702.  
  4703.      #ifndef _IDL_SEQUENCE_long_defined
  4704.      #define _IDL_SEQUENCE_long_defined
  4705.      typedef struct {
  4706.          unsigned long _maximum;
  4707.          unsigned long _length;
  4708.          long *_buffer;
  4709.      } _IDL_SEQUENCE_long;
  4710.      #endif /* _IDL_SEQUENCE_long_defined */
  4711.      typedef _IDL_SEQUENCE_long vec10;
  4712.  
  4713.  and an instance of this type is declared as follows: 
  4714.  
  4715.      vec10 v = {10L, 0L, (long *)NULL};
  4716.  
  4717.  The "_maximum" member designates the actual size of storage allocated for the 
  4718.  sequence, and the "_length" member designates the number of values contained 
  4719.  in the "_buffer" member. For bounded sequences, it is an error to set the 
  4720.  "_length" or "_maximum" member to a value larger than the specified bound of 
  4721.  the sequence. 
  4722.  
  4723.  Before a sequence is passed as the value of an "in" or "inout" method 
  4724.  parameter, the "_buffer" member must point to an array of elements of the 
  4725.  appropriate type, and the "_length" member must contain the number of elements 
  4726.  to be passed. (If the parameter is "inout" and the sequence is unbounded, the 
  4727.  "_maximum" member must also be set to the actual size of the array. Upon 
  4728.  return, "_length" will contain the number of values copied into "_buffer", 
  4729.  which must be less than "_maximum".) When a sequence is passed as an "out" 
  4730.  method parameter or received as the return value, the method procedure 
  4731.  allocates storage for "_buffer" as needed, the "_length" member contains the 
  4732.  number of elements returned, and the "_maximum" member contains the number of 
  4733.  elements allocated. (The client is responsible for subsequently freeing the 
  4734.  memory pointed to by  "_buffer".) 
  4735.  
  4736.  C and C++ programs using SOM's language bindings can refer to sequence types 
  4737.  as: 
  4738.  
  4739.  _IDL_SEQUENCE_type 
  4740.  
  4741.  where "type" is the effective type of the sequence members. For example, the 
  4742.  IDL type sequence<long,10> is referred to in a C/C++ program by the type name 
  4743.  _IDL_SEQUENCE_long. If longint is defined via a typedef to be type long, then 
  4744.  the IDL type sequence<longint,10> is also referred to by the type name 
  4745.  _IDL_SEQUENCE_long. 
  4746.  
  4747.  If the typedef is for a pointer type, then the effective type is the name of 
  4748.  the pointer type. For example, the following statements define a C/C++ type 
  4749.  _IDL_SEQUENCE_longptr and not _IDL_SEQUENCE_long: 
  4750.  
  4751.      typedef long * longptr;
  4752.      typedef sequence<longptr> seq_longptr;
  4753.  
  4754.  A string is similar to a sequence of type char. It can contain all possible 
  4755.  8-bit quantities except NULL. Strings are specified as follows: 
  4756.  
  4757.       string  [ < positive-integer-const > ] 
  4758.  
  4759.  where the optional "positive-integer-const" is a constant expression that 
  4760.  specifies the maximum size of the string (as a positive integer, which does 
  4761.  not include the extra byte to hold a NULL as required in C/C++). In SOM's C 
  4762.  and C++ bindings, strings are mapped onto zero-byte terminated character 
  4763.  arrays. The length of the string is encoded by the position of the zero-byte. 
  4764.  For example, the following IDL declaration: 
  4765.  
  4766.      typedef string<10> foo;
  4767.  
  4768.  is converted to the following C/C++ typedef: 
  4769.  
  4770.      typedef char *foo;
  4771.  
  4772.  A variable of this type is then declared as follows: 
  4773.  
  4774.      foo s = (char *) NULL;
  4775.  
  4776.  C and C++ programs using SOM's language bindings can refer to string types by 
  4777.  the type name string. 
  4778.  
  4779.  When an unbounded string is passed as the value of an "inout" method 
  4780.  parameter, the returned value is constrained to be no longer than the input 
  4781.  value. Hence, using unbounded strings as "inout" parameters is not advised. 
  4782.  
  4783.  
  4784. ΓòÉΓòÉΓòÉ 5.2.2.9. Arrays ΓòÉΓòÉΓòÉ
  4785.  
  4786. Multidimensional, fixed-size arrays can be declared in IDL as follows: 
  4787.  
  4788. identifier {[ positive-integer-const ] }+ 
  4789.  
  4790. where the "positive-integer-const" is a constant expression that specifies the 
  4791. array size, in each dimension, as a positive integer. The array size is fixed 
  4792. at compile time. 
  4793.  
  4794.  
  4795. ΓòÉΓòÉΓòÉ 5.2.2.10. Pointers ΓòÉΓòÉΓòÉ
  4796.  
  4797. Although the CORBA standard for IDL does not include them, SOM IDL offers 
  4798. pointer types. Declarators of a pointer type are specified as in C and C++: 
  4799.  
  4800. type *declarator 
  4801.  
  4802. where "type" is a valid IDL type specification and "declarator" is an 
  4803. identifier or an array declarator. 
  4804.  
  4805.  
  4806. ΓòÉΓòÉΓòÉ 5.2.2.11. Object types ΓòÉΓòÉΓòÉ
  4807.  
  4808. The name of the interface to a class of objects can be used as a type. For 
  4809. example, if an IDL specification includes an interface declaration (described 
  4810. below) for a class (of objects)  "C1", then "C1" can be used as a type name 
  4811. within that IDL specification. When used as a type, an interface name indicates 
  4812. a pointer to an object that supports that interface. An interface name can be 
  4813. used as the type of a method argument, as a method return type, or as the type 
  4814. of a member of a constructed type (a struct, union, or enum). In all cases, the 
  4815. use of an interface name implicitly indicates a pointer to an object that 
  4816. supports that interface. 
  4817.  
  4818. As explained in Using SOM Classes in Client Programs, SOM's C usage bindings 
  4819. for SOM classes also follow this convention.  However, within SOM's C++ 
  4820. bindings, the pointer is made explicit, and the use of an interface name as a 
  4821. type refers to a class instance itself, rather than a pointer to a class 
  4822. instance. For example, to declare a variable "myobj" that is a pointer to an 
  4823. instance of class "Foo" in an IDL specification and in a C program, the 
  4824. following declaration is required: 
  4825.  
  4826.    Foo myobj;
  4827.  
  4828. However, in a C++ program, the following declaration is required: 
  4829.  
  4830.    Foo *myobj;
  4831.  
  4832. If a C programmer uses the SOM Compiler option -maddstar, then the bindings 
  4833. generated for C will also require an explicit `*' in declarations. Thus, 
  4834.  
  4835.  Foo myobj;               in IDL requires 
  4836.  
  4837.  Foo *myobj;              in both C and C++ programs 
  4838.  
  4839.  This style of bindings for C is permitted for two reasons: 
  4840.  
  4841.      It more closely resembles the bindings for C++, thus making it easier to 
  4842.       change to the C++ bindings at a later date; and 
  4843.  
  4844.      It is required for compatibility with existing SOM OIDL code. 
  4845.  
  4846.  Note: The same C and C++ binding emitters should not be run in the same SOM 
  4847.  Compiler command. For example, 
  4848.  
  4849.      sc "-sh;xh" cls.idl    // Not valid.
  4850.  
  4851.  If you wish to generate both C and C++ bindings, you should issue the commands 
  4852.  separately: 
  4853.  
  4854.      sc -sh cls.idl
  4855.      sc -sxh cls.idl
  4856.  
  4857.  
  4858. ΓòÉΓòÉΓòÉ 5.2.3. Exception declarations ΓòÉΓòÉΓòÉ
  4859.  
  4860. IDL specifications may include exception declarations, which define data 
  4861. structures to be returned when an exception occurs during the execution of a 
  4862. method. (IDL exceptions are implemented by simply passing back error 
  4863. information after a method call, as opposed to the "catch/throw" model where an 
  4864. exception is implemented by a long jump or signal.)  Associated with each type 
  4865. of exception is a name and, optionally, a struct-like data structure for 
  4866. holding error information. Exceptions are declared as follows: 
  4867.  
  4868.       exception  identifier { member* }; 
  4869.  
  4870.  The "identifier" is the name of the exception, and each "member" has the 
  4871.  following form: 
  4872.  
  4873.       type-spec declarators ; 
  4874.  
  4875.  where "type-spec" is a valid IDL type specification and "declarators" is a 
  4876.  list of identifiers, array declarators, or pointer declarators, delimited by 
  4877.  commas. The members of an exception structure should contain information to 
  4878.  help the caller understand the nature of the error. The exception declaration 
  4879.  can be treated like a struct  definition; that is, whatever you can access in 
  4880.  an IDL struct, you can access in an exception declaration.  Alternatively, the 
  4881.  structure can be empty, whereby the exception is just identified by its name. 
  4882.  
  4883.  If an exception is returned as the outcome of a method, the exception 
  4884.  "identifier" indicates which exception occurred. The values of the members of 
  4885.  the exception provide additional information specific to the exception. The 
  4886.  topic "Method declarations" below describes how to indicate that a particular 
  4887.  method may raise a particular exception, and Using SOM Classes in Client 
  4888.  Programs, describes how exceptions are handled, in the section entitled 
  4889.  "Exceptions and error handling." 
  4890.  
  4891.  Following is an example declaration of a "BAD_FLAG" exception: 
  4892.  
  4893.      exception BAD_FLAG { long ErrCode; char Reason[80]; };
  4894.  
  4895.  The SOM Compiler will map the above exception declaration to the following C 
  4896.  language constructs: 
  4897.  
  4898.      #define ex_BAD_FLAG "::BAD_FLAG"
  4899.      typedef struct BAD_FLAG {
  4900.          long  ErrCode;
  4901.          char  Reason[80];
  4902.      } BAD_FLAG;
  4903.  
  4904.  Thus, the ex_BAD_FLAG symbol can be used as a shorthand for naming the 
  4905.  exception. 
  4906.  
  4907.  An exception declaration within an interface "Hello", such as this: 
  4908.  
  4909.      interface Hello {
  4910.          exception LOCAL_EXCEPTION { long ErrCode; };
  4911.      };
  4912.  
  4913.  would map onto: 
  4914.  
  4915.      #define ex_Hello_LOCAL_EXCEPTION "::Hello::LOCAL_EXCEPTION"
  4916.      typedef struct Hello_LOCAL_EXCEPTION {
  4917.          long  ErrCode;
  4918.      } Hello_LOCAL_EXCEPTION;
  4919.      #define ex_LOCAL_EXCEPTION ex_Hello_LOCAL_EXCEPTION
  4920.  
  4921.  In addition to user-defined exceptions, there are several predefined 
  4922.  exceptions for system run-time errors. The standard exceptions as prescribed 
  4923.  by CORBA are shown in the table "Standard Exceptions Defined by CORBA". These 
  4924.  exceptions correspond to standard run-time errors that may occur during the 
  4925.  execution of any method (regardless of the list of exceptions listed in its 
  4926.  IDL specification). 
  4927.  
  4928.  Each of the standard exceptions has the same structure: an error code (to 
  4929.  designate the subcategory of the exception) and a completion status code. For 
  4930.  example, the NO_MEMORY standard exception has the following definition: 
  4931.  
  4932.      enum completion_status {YES, NO, MAYBE};
  4933.      exception NO_MEMORY { unsigned long minor;
  4934.                            completion_status completed; };
  4935.  
  4936.  The "completion_status" value indicates whether the method was never initiated 
  4937.  (NO), completed its execution prior to the exception (YES), or the completion 
  4938.  status is indeterminate (MAYBE). 
  4939.  
  4940.  Since all the standard exceptions have the same structure,  somcorba.h 
  4941.  (included by som.h) defines a generic StExcep typedef which can be used 
  4942.  instead of the specific typedefs: 
  4943.  
  4944.      typedef struct StExcep {
  4945.           unsigned long minor;
  4946.           completion_status completed;
  4947.      } StExcep;
  4948.  
  4949.  The standard exceptions shown in the table "Standard Exceptions Defined by 
  4950.  CORBA". are defined in an IDL module called StExcep, in the file called 
  4951.  stexcep.idl, and the C definitions can be found in stexcep.h. 
  4952.  
  4953.  Standard Exceptions Defined by CORBA 
  4954.  
  4955.   module StExcep {
  4956.     #define ex_body { unsigned long minor; completion_status completed; }
  4957.  
  4958.     enum completion_status { YES, NO, MAYBE };
  4959.  
  4960.     enum exception_type {NO_EXCEPTION, USER_EXCEPTION, SYSTEM_EXCEPTION};
  4961.  
  4962.     exception UNKNOWN              ex_body;   // the unknown exception
  4963.     exception BAD_PARAM            ex_body;   // an invalid parameter was passed
  4964.     exception NO_MEMORY            ex_body;   // dynamic memory allocation failure
  4965.     exception IMP_LIMIT            ex_body;   // violated implementation limit
  4966.     exception COMM_FAILURE         ex_body;   // communication failure
  4967.     exception INV_OBJREF           ex_body;   // invalid object reference
  4968.     exception NO_PERMISSION        ex_body;   // no permission for attempted op.
  4969.     exception INTERNAL             ex_body;   // ORB internal error
  4970.     exception MARSHAL              ex_body;   // error marshalling param/result
  4971.     exception INITIALIZE           ex_body;   // ORB initialization failure
  4972.     exception NO_IMPLEMENT         ex_body;   // op. implementation unavailable
  4973.     exception BAD_TYPECODE         ex_body;   // bad typecode
  4974.     exception BAD_OPERATION        ex_body;   // invalid operation
  4975.     exception NO_RESOURCES         ex_body;   // insufficient resources for
  4976.                                    request
  4977.     exception NO_RESPONSE          ex_body;   // response to req. not yet
  4978.                                    available
  4979.     exception PERSIST_STORE        ex_body;   // persistent storage failure
  4980.     exception BAD_INV_ORDER        ex_body;   // routine invocations out
  4981.                                    of order
  4982.     exception TRANSIENT            ex_body;   // transient failure - reissue
  4983.                                    request
  4984.     exception FREE_MEM             ex_body;   // cannot free memory
  4985.     exception INV_IDENT            ex_body;   // invalid identifier syntax
  4986.     exception INV_FLAG             ex_body;   // invalid flag was specified
  4987.     exception INTF_REPOS           ex_body;   // error accessing interface
  4988.                                    repository
  4989.     exception CONTEXT              ex_body;   // error processing context object
  4990.     exception OBJ_ADAPTER          ex_body;   // failure detected by object adapter
  4991.     exception DATA_CONVERSION      ex_body;   // data conversion error
  4992.   };
  4993.  
  4994.  
  4995. ΓòÉΓòÉΓòÉ 5.2.4. Interface declarations ΓòÉΓòÉΓòÉ
  4996.  
  4997. The IDL specification for a class of objects must contain a declaration of the 
  4998. interface these objects will support. Because, in SOM, objects are implemented 
  4999. using classes, the interface name is always used as a class name as well. 
  5000. Therefore, an interface declaration can be understood to specify a class name, 
  5001. and its parent (direct base) class names. This is the approach used in the 
  5002. following description of an interface declaration. In addition to the class 
  5003. name and its parents names, an interface indicates new methods (operations), 
  5004. and any constants, type definitions, and exception structures that the 
  5005. interface exports. An interface declaration has the following syntax: 
  5006.  
  5007.   interface class-name [: parent-class1, parent-class2, ...]
  5008.   {
  5009.   constant declarations     (optional)
  5010.   type declarations       (optional)
  5011.   exception declarations     (optional)
  5012.   attribute declarations     (optional)
  5013.   method declarations      (optional)
  5014.   implementation statement    (optional)
  5015.   };
  5016.  
  5017. Many class implementers distinguish a "class-name" by using an initial capital 
  5018. letter, but that is optional. The "parent-class" (or base-class) names specify 
  5019. the interfaces from which the interface of "class-name" instances is derived. 
  5020. Parent-class names are required only for the immediate parent(s). Each parent 
  5021. class must have its own IDL specification (which must be #included in the 
  5022. subclass's .idl file). A parent class cannot be named more than once in the 
  5023. interface statement header. 
  5024.  
  5025. Note: In general, an "interface class-name" header must precede any subsequent 
  5026. implementation that references "class-name." For more discussion of multiple 
  5027. interface statements, refer to the later topic "Module declarations to define 
  5028. multiple interfaces in an .idl file." 
  5029.  
  5030. The following topics describe the various declarations/statements that can be 
  5031. specified within the body of an interface declaration. The order in which these 
  5032. declarations are specified is usually optional, and declarations of different 
  5033. kinds can be intermixed. Although all of the declarations/statements are listed 
  5034. above as "optional," in some cases using one of them may mandate another. For 
  5035. example, if a method raises an exception, the exception structure must be 
  5036. defined beforehand. In general, types, constants, and exceptions, as well as 
  5037. interface declarations, must be defined before they are referenced, as in 
  5038. C/C++. 
  5039.  
  5040.  
  5041. ΓòÉΓòÉΓòÉ 5.2.5. Constant, type, and exception declarations ΓòÉΓòÉΓòÉ
  5042.  
  5043. The form of a constant, type, or exception declaration within the body of an 
  5044. interface declaration is the same as described previously in this chapter. 
  5045. Constants and types defined within an interface for a class are transferred by 
  5046. the SOM Compiler to the binding files it generates for that class, whereas 
  5047. constants and types defined outside of an interface are not. 
  5048.  
  5049. Global types (such as, those defined outside of an interface and module) can be 
  5050. emitted by surrounding them with the following #pragmas: 
  5051.  
  5052.    #pragma somemittypes on
  5053.         typedef sequence <long,10> vec10;
  5054.         exception BAD_FLAG { long ErrCode; char Reason[80]; };
  5055.         typedef long long_t;
  5056.    #pragma somemittypes off
  5057.  
  5058. Types, constants, and exceptions defined in a parent class are also accessible 
  5059. to the child class. References to them, however, must be unambiguous. Potential 
  5060. ambiguities can be resolved by prefacing a name with the name of the class that 
  5061. defines it, separated by the characters "::" as illustrated below: 
  5062.  
  5063.    MyParentClass::myType
  5064.  
  5065. The child class can redefine any of the type, constant, and exception names 
  5066. that have been inherited, although this is not advised. The derived class 
  5067. cannot, however, redefine attributes or methods. It can only replace the 
  5068. implementation of methods through overriding (as in example 3 of the Tutorial). 
  5069. To refer to a constant, type, or exception "name" defined by a parent class and 
  5070. redefined by "class-name," use the "parent-name::name" syntax as before. 
  5071.  
  5072. Note: A name reference such as MyParentClass::myType required in IDL syntax is 
  5073. equivalent to MyParentClass_myType in C/C++. For a full discussion of name 
  5074. recognition in SOM, see "Scoping and name resolution" later in this chapter. 
  5075.  
  5076.  
  5077. ΓòÉΓòÉΓòÉ 5.2.6. Attribute declarations ΓòÉΓòÉΓòÉ
  5078.  
  5079. Declaring an attribute as part of an interface is equivalent to declaring two 
  5080. accessor methods: one to retrieve the value of the attribute (a "get" method, 
  5081. named "_get_<attributeName>") and one to set the value of the attribute (a 
  5082. "set" method, named "_set_<attributeName>"). 
  5083.  
  5084. Attributes are declared as follows: 
  5085.  
  5086.       [ readonly ]  attribute  type-spec declarators ; 
  5087.  
  5088.  where "type-spec" specifies any valid IDL type and "declarators" is a list of 
  5089.  identifiers or pointer declarators, delimited by commas. (An array declarator 
  5090.  cannot be used directly when declaring an attribute, but the type of an 
  5091.  attribute can be a user-defined type that is an array.) The optional readonly 
  5092.  keyword specifies that the value of the attribute can be accessed but not 
  5093.  modified by client programs.  (In other words, a readonly attribute has no 
  5094.  "set" method.) Below are examples of attribute declarations, which are 
  5095.  specified within the body of an interface statement for a class: 
  5096.  
  5097.      interface Goodbye: Hello, SOMObject
  5098.      {
  5099.        void  sayBye();
  5100.  
  5101.        attribute short xpos;
  5102.        attribute char c1, c2;
  5103.        readonly attribute float xyz;
  5104.      };
  5105.  
  5106.  The preceding attribute declarations are equivalent to defining the following 
  5107.  methods: 
  5108.  
  5109.      short _get_xpos();
  5110.      void  _set_xpos(in short xpos);
  5111.      char  _get_c1();
  5112.      void  _set_c1(in char c1);
  5113.      char  _get_c2();
  5114.      void  _set_c2(in char c2);
  5115.      float _get_xyz();
  5116.  
  5117.  Note: Although the preceding attribute declarations are equivalent to the 
  5118.  explicit method declarations above, these method declarations are not legal 
  5119.  IDL, because the method names begin with an `_'. All IDL identifiers must 
  5120.  begin with an alphabetic character, not including `_'. 
  5121.  
  5122.  Attributes are inherited from ancestor classes (indirect base classes). An 
  5123.  inherited attribute name cannot be redefined to be a different type. 
  5124.  
  5125.  
  5126. ΓòÉΓòÉΓòÉ 5.2.7. Method (operation) declarations ΓòÉΓòÉΓòÉ
  5127.  
  5128. Method (operation) declarations define the interface of each method introduced 
  5129. by the class. A method declaration is similar to a C/C++ function definition: 
  5130.  
  5131.       [oneway] type-spec identifier ( parameter-list) 
  5132.       [raises-expr]  [context-expr] ; 
  5133.  where "identifier" is the name of the method and "type-spec" is any valid IDL 
  5134.  type (or the keyword void, indicating that the method returns no value). 
  5135.  Unlike C and C++ procedures, methods that do not return a result must specify 
  5136.  void as their return type. The remaining syntax of a method declaration is 
  5137.  elaborated in the following subtopics. 
  5138.  
  5139.  Note:  Although IDL does not allow methods to receive and return values whose 
  5140.  type is a pointer to a function, it does allow methods to receive and return 
  5141.  method names (as string values). Thus, rather than defining methods that pass 
  5142.  pointers to functions (and that subsequently invoke those functions), 
  5143.  programmers should instead define methods that pass method names (and 
  5144.  subsequently invoke those methods using one of the SOM-supplied 
  5145.  method-dispatching or method-resolution methods or functions, such as 
  5146.  somDispatch). 
  5147.  
  5148.  
  5149. ΓòÉΓòÉΓòÉ 5.2.7.1. Oneway keyword ΓòÉΓòÉΓòÉ
  5150.  
  5151. The optional oneway keyword specifies that when a client invokes the method, 
  5152. the invocation semantics are "best-effort", which does not guarantee delivery 
  5153. of the call. "Best-effort" implies that the method will be invoked at most 
  5154. once. A oneway method should not have any output parameters and should have a 
  5155. return type of void. A oneway method also should not include a "raises 
  5156. expression" (see below), although it may raise a standard exception. 
  5157.  
  5158. If the oneway keyword is not specified, then the method has "at-most-once" 
  5159. invocation semantics if an exception is raised, and it has "exactly-once" 
  5160. semantics if the method succeeds. This means that a method that raises an 
  5161. exception has been executed zero or one times, and a method that succeeds has 
  5162. been executed exactly once. 
  5163.  
  5164. Note: Currently the "oneway" keyword, although accepted, has no effect on the 
  5165. C/C++ bindings that are generated. 
  5166.  
  5167.  
  5168. ΓòÉΓòÉΓòÉ 5.2.7.2. Parameter list ΓòÉΓòÉΓòÉ
  5169.  
  5170. The "parameter-list" contains zero or more parameter declarations for the 
  5171. method, delimited by commas. (The target object for the method is not 
  5172. explicitly specified as a method parameter in IDL, nor are the Environment or 
  5173. Context parameters.)  If there are no explicit parameters, the syntax "( )" 
  5174. must be used, rather than "(void)". A parameter declaration has the following 
  5175. syntax: 
  5176.  
  5177. { in Γöé out Γöé inout }  type-spec  declarator 
  5178.  
  5179. where "type-spec" is any valid IDL type and "declarator" is an identifier, 
  5180. array declarator, or pointer declarator. 
  5181.  
  5182. In, out, inout parameters:  The required inΓöéoutΓöéinout directional attribute 
  5183. indicates whether the parameter is to be passed from client to server (in), 
  5184. from server to client (out), or in both directions (inout). A method must not 
  5185. modify an in  parameter. If a method raises an exception, the values of the 
  5186. return result and the values of the out and inout parameters (if any) are 
  5187. undefined. When an unbounded string or sequence is passed as an inout 
  5188. parameter, the returned value must be no longer than the input value. 
  5189.  
  5190. The following are examples of valid method declarations in SOM IDL: 
  5191.  
  5192.    short meth1(in char c, out float f);
  5193.    oneway void meth2(in char c);
  5194.    float meth3();
  5195.  
  5196. Classes derived from SOMObject can declare methods that take a pointer to a 
  5197. block of memory containing a variable number of arguments, using a final 
  5198. parameter of type va_list. The va_list must use the parameter name "ap", as in 
  5199. the following example: 
  5200.  
  5201.    void MyMethod(in short numArgs, in va_list ap);
  5202.  
  5203. For in parameters of type array, C and C++ clients must pass the address of the 
  5204. first element of the array. For in parameters of type struct,  union, sequence 
  5205. or any, C/C++ clients must pass the address of a variable of that type, rather 
  5206. than the variable itself. 
  5207.  
  5208. For all IDL types except arrays, if a parameter of a method is out or inout, 
  5209. then C/C++ clients must pass the address of a variable of that type (or the 
  5210. value of a pointer to that variable) rather than the variable itself. (For 
  5211. example, to invoke method "meth1" above, a pointer to a variable of type float 
  5212. must be passed in place of parameter "f".) For arrays, C/C++ clients must pass 
  5213. the address of the first element of the array. 
  5214.  
  5215. If the return type of a method is a struct, union, sequence, or any type, then 
  5216. for C/C++ clients, the method returns the value of the C/C++ struct 
  5217. representing the IDL struct, union, sequence, or any. If the return type is 
  5218. string, then the method returns a pointer to the first character of the string. 
  5219. If the return type is array, then the method returns a pointer to the first 
  5220. element of the array. 
  5221.  
  5222. The pointers implicit in the parameter types and return types for IDL method 
  5223. declarations are made explicit in SOM's C and C++ bindings. Thus, the stub 
  5224. procedure that the SOM Compiler generates for method "meth1", above, has the 
  5225. following signature: 
  5226.  
  5227.    SOM_Scope short  SOMLINK meth1(char c, float *f)
  5228.  
  5229. For C and C++ clients, if a method has an out parameter of type  string 
  5230. sequence, or any, then the method must allocate the storage for the string, for 
  5231. the "_buffer" member of the struct that represents the sequence, or for the 
  5232. "_value" member of the struct that represents the any. It is then the 
  5233. responsibility of the client program to free the storage when it is no longer 
  5234. needed. Similarly, if the return type of a method is string, sequence, array, 
  5235. or any, then storage must be allocated by the method, and it will be the 
  5236. responsibility of the client program to subsequently free it. 
  5237.  
  5238. Note: The foregoing description also applies for the _get_ <attributeName> 
  5239. method associated with an attribute of type string, sequence, any, or array. 
  5240. Hence, the attribute should be specified with a "noget" modifier to override 
  5241. automatic implementation of the attribute's "get" method.  Then, needed memory 
  5242. can be allocated by the developer's "get" method implementation and 
  5243. subsequently deallocated by the caller.  (The "noget" modifier is described in 
  5244. Modifier statements.) 
  5245.  
  5246.  
  5247. ΓòÉΓòÉΓòÉ 5.2.7.3. Raises expression ΓòÉΓòÉΓòÉ
  5248.  
  5249. The optional raises expression ("raises-expr") in a method declaration 
  5250. indicates which exceptions the method may raise. (IDL exceptions are 
  5251. implemented by simply passing back error information after a method call, as 
  5252. opposed to the "catch/throw" model where an exception is implemented by a long 
  5253. jump or signal.)  A raises expression is specified as follows: 
  5254.  
  5255.       raises ( identifier1, identifier2,... ) 
  5256.  
  5257.  where each "identifier" is the name of a previously defined exception. In 
  5258.  addition to the exceptions listed in the raises expression, a method may also 
  5259.  signal any of the standard exceptions. Standard exceptions, however, should 
  5260.  not appear in a raises expression. If no raises expression is given, then a 
  5261.  method can raise only the standard exceptions. (See the earlier topic 
  5262.  "Exception declarations" for information on defining exceptions and for the 
  5263.  list of standard exceptions. See "Exceptions and error handling," in Chapter 3 
  5264.  for information on using exceptions.) 
  5265.  
  5266.  
  5267. ΓòÉΓòÉΓòÉ 5.2.7.4. Context expression ΓòÉΓòÉΓòÉ
  5268.  
  5269. The optional context expression ("context-expr") in a method declaration 
  5270. indicates which elements of the client's context the method may consult. A 
  5271. context expression is specified as follows: 
  5272.  
  5273.       context ( identifier1, identifier2, ... ) 
  5274.  
  5275.  where each "identifier" is a string literal made up of alphanumeric 
  5276.  characters, periods, underscores, and asterisks. (The first character must be 
  5277.  alphabetic, and an asterisk can only appear as the last character, where it 
  5278.  serves as a wildcard matching any characters. If convenient, identifiers may 
  5279.  consist of period-separated valid identifier names, but that form is 
  5280.  optional.) 
  5281.  
  5282.  The Context is a special object that is specified by the CORBA standard.  It 
  5283.  contains a properly list - a set of property-name/string-value pairs that the 
  5284.  client can use to store information about its environment that methods may 
  5285.  find useful.  It is used in much the same way as environment variables.  It is 
  5286.  passed as an additional (third) parameter to CORBA-compliant methods that are 
  5287.  defined as "context-sensitive" in IDL, along with the CORBA-defined 
  5288.  Environment structure. 
  5289.  
  5290.  The context expression of a mehod declaration in IDL specifies which property 
  5291.  names the method uses.  If these properties are present in the Context object 
  5292.  supplied by the client, they will be passed to the object implementation, 
  5293.  which can access them via the get_values method of the Context object. 
  5294.  However, the argument that is passed to the method having a context expression 
  5295.  is a Context object, not the names of the properties.  The client program must 
  5296.  either create a Context object and use the set_values or set_one_value method 
  5297.  of the Context class to set the context properties, or use the 
  5298.  get_default_context method. The client program then passes the Context object 
  5299.  in the method invocation.  Note that the CORBA standard also allows properties 
  5300.  in addition to those in the context expression to be passed in the Context 
  5301.  object. 
  5302.  
  5303.  In Chapter 3, "Using SOM Classes in Client Programs," the topic "Invoking 
  5304.  Methods" describes the placement of a context parameter in a method call. See 
  5305.  also Chapter 6 of The Common Object Request Broker: Architecture and 
  5306.  Specification for a discussion of how clients associate values with context 
  5307.  identifiers. A description of the Context class and its methods is contained 
  5308.  in the SOM Programming Reference. 
  5309.  
  5310.  
  5311. ΓòÉΓòÉΓòÉ 5.2.8. Implementation statements ΓòÉΓòÉΓòÉ
  5312.  
  5313. A SOM IDL interface statement for a class may contain an implementation 
  5314. statement, which specifies information about how the class will be implemented 
  5315. (version numbers for the class, overriding of inherited methods, what 
  5316. resolution mechanisms the bindings for a particular method will support, and so 
  5317. forth). If the implementation statement is omitted, default information is 
  5318. assumed. 
  5319.  
  5320. Because the implementation statement is specific to SOM IDL (and is not part of 
  5321. the CORBA standard), the implementation statement should be preceded by an 
  5322. "#ifdef _ _SOMIDL_ _" directive and followed by an "#endif" directive. (See 
  5323. Example 3 in the SOM IDL Tutorial presented earlier.) 
  5324.  
  5325. The syntax for the implementation statement is as follows: 
  5326.  
  5327.    #ifdef __SOMIDL__
  5328.    implementation
  5329.    {
  5330.      implementation*
  5331.    };
  5332.    #endif
  5333.  
  5334. where each "implementation" can be a modifier  statement, a passthru statement, 
  5335. or a declarator of an instance variable, terminated by a semicolon. These 
  5336. constructs are described below. An interface statement may not contain multiple 
  5337. implementation statements. 
  5338.  
  5339.  
  5340. ΓòÉΓòÉΓòÉ 5.2.8.1. Modifier statements ΓòÉΓòÉΓòÉ
  5341.  
  5342. A modifier statement gives additional implementation information about IDL 
  5343. definitions, such as interfaces, attributes, methods, and types. Modifiers can 
  5344. be unqualified or qualified: An unqualified modifier is associated with the 
  5345. interface it is defined in. An unqualified modifier statement has the following 
  5346. two syntactic forms: 
  5347.  
  5348.   modifier
  5349.   modifier = value
  5350. where "modifier" is either a SOM Compiler-defined identifier or a user-defined 
  5351. identifier, and where "value" is an identifier, a string enclosed in double 
  5352. quotes (" "), or a number. 
  5353.  
  5354. For example: 
  5355.  
  5356.    filestem = foo;
  5357.    nodata;
  5358.    persistent;
  5359.    dllname = "E:/som/dlls";
  5360.  
  5361. A qualified modifier is associated with a qualifier.  The qualified modifier 
  5362. has the syntax: 
  5363.  
  5364.    qualifier : modifier
  5365.    qualifier : modifier = value
  5366.    #pragma modifier qualifier : modifier
  5367.    #pragma modifier qualifier : modifier = value
  5368.  
  5369. where "qualifier" is the identifier of an IDL definition or is user defined. If 
  5370. the "qualifier" is an IDL definition introduced in the current interface, 
  5371. module, or global scope, then the modifier is attached to that definition. 
  5372. Otherwise, if the qualifier is user defined, the modifier is attached to the 
  5373. interface it occurs in. If a user-defined modifier is defined outside of an 
  5374. interface body (by using #pragma modifier), then it is ignored. 
  5375.  
  5376. For example, consider the following IDL file.  (Notice that qualified modifiers 
  5377. can be defined with the "qualifier" and "modifier[=value]" in either order. 
  5378. Also observe that additional modifiers can be included by separating them with 
  5379. commas.) 
  5380.  
  5381.    #include <somobj.idl>
  5382.    #include <somcls.idl>
  5383.  
  5384.  
  5385.    typedef long newInt;
  5386.    #pragma somemittypes on
  5387.    #pragma modifier newInt : nonportable;
  5388.    #pragma somemittypes off
  5389.    module M {
  5390.        typedef long long_t;
  5391.        module  N {
  5392.            typedef short short_t;
  5393.            interface M_I : SOMClass {
  5394.                implementation {
  5395.                    somInit : override;
  5396.                };
  5397.            };
  5398.            interface I : SOMObject {
  5399.                void op ();
  5400.                #pragma modifier op : persistent;
  5401.  
  5402.  
  5403.                typedef char char_t;
  5404.                implementation {
  5405.                    releaseorder : op;
  5406.                    metaclass = M_I;
  5407.                    callstyle = oidl;
  5408.                    mymod : a, b;
  5409.                    mymod : c, d;
  5410.                    e     : mymod;
  5411.                    f     : mymod;
  5412.                    op : persistent;
  5413.                };
  5414.           };
  5415.        };
  5416.     };
  5417.  
  5418. From the preceding IDL file, we associate modifiers with the following 
  5419. definitions: 
  5420.  
  5421.    TypeDef "::newInt"             1  modifier: nonportable
  5422.    InterfaceDef "::M::N::M_I"     1  modifier: override = somInit
  5423.    InterfaceDef "::M::N::I"       9 modifiers: metaclass = M_I,
  5424.                                                releaseorder = op
  5425.                                                callstyle = oidl
  5426.                                                mymod = a,b,c,d,e,f
  5427.                                                a = mymod
  5428.                                                b = mymod
  5429.                                                c = mymod
  5430.                                                d = mymod
  5431.                                                e = mymod
  5432.                                                f = mymod
  5433.    OperationDef "::M::N::I::op"   1 modifier: persistent
  5434.  
  5435. Notice, how the modifiers for the user-defined qualifier "mymod": 
  5436.  
  5437.    mymod : a, b;
  5438.    mymod : c, d;
  5439.    e     : mymod;
  5440.    f     : mymod;
  5441.  
  5442. map onto: 
  5443.  
  5444.    mymod = a,b,c,d,e,f
  5445.    a     = mymod
  5446.    b     = mymod
  5447.    c     = mymod
  5448.    d     = mymod
  5449.    e     = mymod
  5450.    f     = mymod
  5451.  
  5452. This enables users to look up the modifiers with "mymod", either by looking for 
  5453. "mymod" or by using each individual value that uses "mymod". These user-defined 
  5454. modifiers are available for Emitter writers and from the Interface Repository 
  5455. (see Chapter 7, "The Interface Repository Framework"). 
  5456.  
  5457.  
  5458. ΓòÉΓòÉΓòÉ 5.2.8.2. SOM Compiler unqualified modifiers ΓòÉΓòÉΓòÉ
  5459.  
  5460. Unqualified modifiers (described below) include the SOM Compiler-defined 
  5461. identifiers abstract, baseproxyclass, callstyle, classinit, directinitclasses, 
  5462. dllname, filestem, functionprefix, majorversion, metaclass, memory_management, 
  5463. minorversion, somallocte and somdeallocate. 
  5464.  
  5465.  abstract                 Specifies that the class is intended for use as a 
  5466.                           parent for subclass derivations, but not for creating 
  5467.                           instances. 
  5468.  
  5469.  baseproxyclass =class    Specifies the base proxy class to be used by DSOM 
  5470.                           when dynamically creating a proxy class for the 
  5471.                           current class. The base proxy class must be derived 
  5472.                           from the class SOMDClientProxy  The SOMDClientProxy 
  5473.                           class will be used if the baseproxyclass modifier is 
  5474.                           unspecified. (See chapter 6, "distributed SOM," for a 
  5475.                           discussion on customizing proxy classes.) 
  5476.  
  5477.  callstyle = oidl         Specifies that the method stub procedures generated 
  5478.                           by SOM's C/C++ bindings will not include the 
  5479.                           CORBA-specified (Environment *ev) and (context *ctx) 
  5480.                           parameters. 
  5481.  
  5482.  classinit = procedure    Specifies a user-written procedure that will be 
  5483.                           executed to complete the initialization of a class 
  5484.                           object after it is created. The classinit modifier is 
  5485.                           needed if something should happen exactly once when a 
  5486.                           class is created. (That is, you want to define an 
  5487.                           action that will not be inherited when subclasses are 
  5488.                           created. One example of this is for staticdata 
  5489.                           variables.) When the classinit modifier is specified 
  5490.                           in the .idl file for a class, the implementation file 
  5491.                           generated by the SOM Compiler provides a template for 
  5492.                           the procedure, which includes a parameter that is a 
  5493.                           pointer to the class. The class implementor can then 
  5494.                           fill in the body of this procedure template. (For an 
  5495.                           example, see the examples following the staticdata 
  5496.                           modifier under "SOM Compiler qualified modifiers.") 
  5497.  
  5498.  directinitclasses ="ancestor1, ancestor2, ..." 
  5499.  
  5500.  
  5501.                           Specifies the ancestor class(es) whose initializers 
  5502.                           (and destructors) will be directly invoked by this 
  5503.                           class's initialization (and destruction) routines. 
  5504.                           If this modifier is not explicitly specified, the 
  5505.                           default setting is the parents of the class. For 
  5506.                           further information, see "Initializing and 
  5507.                           Uninitializing Objects" in Chapter 5, "Implementing 
  5508.                           Classes in SOM." 
  5509.  
  5510.  dllname = filename       Specifies the name of the library file that will 
  5511.                           contain the class's implementation. If filename 
  5512.                           contains special characters (e.g., periods, 
  5513.                           backslashes), then filename should be surrounded by 
  5514.                           double quotes (""). The filename specified can be 
  5515.                           either a full pathname, or an unqualified (or 
  5516.                           partially qualified) filename. In the latter cases, 
  5517.                           the PATH environment variable is used to locate the 
  5518.                           file. 
  5519.  
  5520.  filestem  = stem         Specifies how the SOM Compiler will construct file 
  5521.                           names for the binding files it generates (<stem>.h, 
  5522.                           <stem>.c, etc.). The default stem is the file stem of 
  5523.                           the .idl file for the class. 
  5524.  
  5525.  functionprefix  = prefix Directs the SOM Compiler to construct 
  5526.                           method-procedure names by prefixing method names with 
  5527.                           "prefix". For example, "functionprefix = xx;"  within 
  5528.                           an implementation statement would result in a 
  5529.                           procedure name of xxfoo for method foo.  The default 
  5530.                           for this attribute is the empty string. If an 
  5531.                           interface is defined in a module, then the default 
  5532.                           function prefix is the fully scooped interface name. 
  5533.                           Tip:  Using a function prefix with the same name as 
  5534.                           the class makes it easier to remember 
  5535.                           method-procedure names when debugging. 
  5536.  
  5537.                           When an .idl file defines multiple interfaces not 
  5538.                           contained within a module, use of a function prefix 
  5539.                           for each interface is essential to avoid name 
  5540.                           collisions. For example, if one interface introduces 
  5541.                           a method and another interface in the same .idl file 
  5542.                           overrides it, then the implementation file for the 
  5543.                           classes will contain two method procedures of the 
  5544.                           same name (unless function prefixes are defined for 
  5545.                           one of the classes), resulting in a name collision at 
  5546.                           compile time. 
  5547.  
  5548.  majorversion = number    Specifies the major version number of the current 
  5549.                           class definition. The major version number of a class 
  5550.                           definition usually changes only when a significant 
  5551.                           enhancement or incompatible change is made to the 
  5552.                           class. The "number" must be a positive integer less 
  5553.                           than 2[32]-1.  If a non-zero major version number is 
  5554.                           specified, SOM will verify that any code that 
  5555.                           purports to implement the class has the same major 
  5556.                           version number. The default major version number is 
  5557.                           zero. 
  5558.  
  5559.  memory_management = corba Specifies that all methods introduced by the class 
  5560.                           follow the CORBA specification for parameter memory 
  5561.                           management, except where a particular method has an 
  5562.                           explicit modifier indicating otherwise (either 
  5563.                           "object_owns_result" or "object_owns_parameters"). 
  5564.                           See the section in Chapter 6 entitled "Memory 
  5565.                           Management" for a discussion of the CORBA 
  5566.                           memory-management requirements. 
  5567.  
  5568.  metaclass = class        Specifies the class's metaclass. The specified 
  5569.                           metaclass (or one automatically derived from it at 
  5570.                           run time) will be used to create the class object for 
  5571.                           the class. If a metaclass is specified, its .idl file 
  5572.                           (if separate) must be included in the include section 
  5573.                           of the class's .idl file. If no metaclass is 
  5574.                           specified, the metaclass will be defined 
  5575.                           automatically. 
  5576.  
  5577.  minorversion = number    Specifies the minor version number of the current 
  5578.                           class definition. The minor version number of a class 
  5579.                           definition changes whenever minor enhancements or 
  5580.                           fixes are made to a class. Class implementers usually 
  5581.                           maintain backward compatibility across changes in the 
  5582.                           minor version number. The "number" must be a positive 
  5583.                           integer less than 2[32]-1. If a non-zero minor 
  5584.                           version number is specified, SOM will verify that any 
  5585.                           code that purports to implement the class has the 
  5586.                           same or a higher minor version number. The default 
  5587.                           minor version number is zero. 
  5588.  
  5589.  somallocate=procedure    Specifies a user-written procedure that will be 
  5590.                           executed to allocate memory for class instances when 
  5591.                           the somAllocate class method is invoked. 
  5592.  
  5593.  somdeallocate=procedure  Specifies a user-written procedure that will be 
  5594.                           executed to deallocate memory for class instances 
  5595.                           when the somDeallocate class method is invoked. 
  5596.  
  5597.  The following example illustrates the specification of unqualified interface 
  5598.  modifiers: 
  5599.  
  5600.      implementation
  5601.      {
  5602.        filestem = hello;
  5603.        functionprefix = hel;
  5604.        majorversion = 1;
  5605.        minorversion = 2;
  5606.        classinit = helloInit;
  5607.        metaclass = M_Hello;
  5608.      };
  5609.  
  5610.  
  5611. ΓòÉΓòÉΓòÉ 5.2.8.3. SOM Compiler qualified modifiers ΓòÉΓòÉΓòÉ
  5612.  
  5613. Qualified modifiers are categorized according to the IDL component (class, 
  5614. attribute, method, or type) to which each modifier applies. Listed below are 
  5615. the SOM Compiler-defined identifiers used as qualified modifiers, along with 
  5616. the IDL component to which it applies. Descriptions of all qualified modifiers 
  5617. are then given in alphabetical order. Recall that qualified modifiers are 
  5618. defined using the syntax qualifier: modifier[=value]. 
  5619.  
  5620.  For classes: 
  5621.       releaseorder 
  5622.  
  5623.  For attributes: 
  5624.       indirect, nodata, noget, noset 
  5625.  
  5626.  For methods: 
  5627.       caller_owns_parameters, caller_owns_result, const, init, method, migrate, 
  5628.       namelookup, nocall, noenv, nonstatic, nooverride, noself, 
  5629.       object_owns_parameters, object_owns_result, offset, override, procedure, 
  5630.       reintroduce, and select 
  5631.  
  5632.  For variables: 
  5633.       staticdata 
  5634.  
  5635.  For types: 
  5636.       impctx 
  5637.  
  5638.  caller_owns_parameters ="p1,p2,...,pn" Specifies the names of the method's 
  5639.                           parameters whose ownership is retained by (in the 
  5640.                           case of "in"parameters) or transferred to (for 
  5641.                           "inout" or "out" parameters) the caller. This 
  5642.                           modifier is only valid in the interface specification 
  5643.                           of the method's introducing class.  This modifier 
  5644.                           only makes sense for parameters whose IDL type is a 
  5645.                           data item that can be freed (string, object, array, 
  5646.                           pointer, or TypeCode), or a data item containing 
  5647.                           memory that can be freed (for example, a sequence or 
  5648.                           any), or a struct or union. 
  5649.  
  5650.                           For parameters whose type is an object, ownership 
  5651.                           applies to the object reference rather than to the 
  5652.                           object (that is, the caller should invoke release on 
  5653.                           the parameter, rather than somFree). 
  5654.  
  5655.  caller_owns_result       Specifies that ownership of the return result of  the 
  5656.                           method is transferred to the caller, and that the 
  5657.                           caller is responsible for freeing the memory. This 
  5658.                           modifier is only valid in the interface specification 
  5659.                           of the method's introducing class. This modifier only 
  5660.                           makes sense when the method's return type is a data 
  5661.                           type that can be freed (string, object, array, 
  5662.                           pointer, or TypeCode), or a data item containing 
  5663.                           memory that can be freed (for example, a sequence or 
  5664.                           any). For methods that return an object, ownership 
  5665.                           applies to the object reference rather than to the 
  5666.                           object (that is, the caller should invoke release on 
  5667.                           the result, rather than somFree). 
  5668.  
  5669.  const                    Indicates that implementations of the related method 
  5670.                           should not modify their target argument. SOM provides 
  5671.                           no way to verify or guarantee that implementations do 
  5672.                           not modify the targets of such methods, and the 
  5673.                           information provided by this modifier is not 
  5674.                           currently of importance to any of the Toolkit 
  5675.                           emitters. However, the information may prove useful 
  5676.                           in the future. For example, since modifiers are 
  5677.                           available in the Interface Repository, there may be 
  5678.                           future uses of this information by DSOM. 
  5679.  
  5680.  impctx                   Supports types that cannot be fully defined using 
  5681.                           IDL. For full information, see "Using the tk_foreign 
  5682.                           TypeCode" in Chapter 7, "The Interface Repository 
  5683.                           Framework." 
  5684.  
  5685.  indirect                 Directs the SOM Compiler to generate "get" and "set" 
  5686.                           methods for the attribute that take and return a 
  5687.                           pointer to the attribute's value, rather than the 
  5688.                           attribute value itself. For example, if an attribute 
  5689.                           x of type float is declared to be an indirect 
  5690.                           attribute, then the "_get_x" method will return a 
  5691.                           pointer to a float, and the input to the "_set_x" 
  5692.                           method must be a pointer to a float. (This modifier 
  5693.                           is provided for OIDL compatibility only.) 
  5694.  
  5695.  init                     Indicates that a method is an initializer method. 
  5696.                           For information concerning the use of this modifier, 
  5697.                           see "Initializing and Uninitializing Objects: in 
  5698.                           Chapter 5, "Implementing Classes in SOM" 
  5699.  
  5700.  method or nonstatic or  procedure Indicates the category of method 
  5701.                           implementation. Refer to the topic "The four kinds of 
  5702.                           SOM methods" in Chapter 5, "Implementing Classes in 
  5703.                           SOM," for an explanation of the meanings of these 
  5704.                           different method modifiers.  If none of these 
  5705.                           modifiers is specified, the default is method. 
  5706.                           Methods with the procedure modifier cannot be invoked 
  5707.                           remotely using DSOM. 
  5708.  
  5709.  migrate  = ancestor      Indicates that a method originally introduced by this 
  5710.                           interface has been moved upward to a specified 
  5711.                           <ancestor> interface. When this is done, the method 
  5712.                           introduction must be removed from this interface 
  5713.                           (because the method is now inherited). However, the 
  5714.                           original  releaseorder entry for the method should be 
  5715.                           retained, and migrate should be used to assure that 
  5716.                           clients compiled based on the original interface will 
  5717.                           not require recompilation. The ancestor interface is 
  5718.                           specified using a C-scoped interface name. For 
  5719.                           example, "Module_InterfaceName", not 
  5720.                           "Module::InterfaceName". See the later topic "Name 
  5721.                           usage in client programs" for an explanation of 
  5722.                           C-scoped names. 
  5723.  
  5724.  namelookup               See "offset or namelookup." 
  5725.  
  5726.  nocall                   Specifies that the related method should not be 
  5727.                           invoked on an instance of this class even though it 
  5728.                           is supported by the interface. 
  5729.  
  5730.  nodata                   Directs the SOM Compiler not to define an instance 
  5731.                           variable corresponding to the attribute. For example, 
  5732.                           a "time" attribute would not require an instance 
  5733.                           variable to maintain its value, because the value can 
  5734.                           be obtained from the operating system.  The "get" and 
  5735.                           "set" methods for "nodata" attributes must be defined 
  5736.                           by the class implementer; stub method procedures for 
  5737.                           them are automatically generated in the 
  5738.                           implementation template for the class by the SOM 
  5739.                           Compiler. 
  5740.  
  5741.  noenv                    Indicates that a direct-call procedure does not 
  5742.                           receive an environment as an argument. 
  5743.  
  5744.  noget                    Directs the SOM Compiler not to automatically 
  5745.                           generate a "get" method procedure for the attribute 
  5746.                           in the .ih/.xih binding file for the class. Instead, 
  5747.                           the "get" method must be implemented by the class 
  5748.                           implementer. A stub method procedure for the "get" 
  5749.                           method is automatically generated in the 
  5750.                           implementation template for the class by the SOM 
  5751.                           Compiler, to be filled in by the implementer. 
  5752.  
  5753.  nonstatic                See "method or nonstatic or procedure." 
  5754.  
  5755.  nooverride               Indicates that the method should not be overridden by 
  5756.                           subclasses. The SOM Compiler will generate an error 
  5757.                           if this method is overridden. 
  5758.  
  5759.  noself                   Indicates that a direct-call procedure does not 
  5760.                           receive a target object as an argument. 
  5761.  
  5762.  noset                    Directs the SOM Compiler not  to automatically 
  5763.                           generate a "set" method procedure for the attribute 
  5764.                           in the .ih/.xih binding file for the class. Instead, 
  5765.                           the "set" method must be implemented by the class 
  5766.                           implementer. A stub method procedure for the "set" 
  5767.                           method is automatically generated in the 
  5768.                           implementation template for the class by the SOM 
  5769.                           Compiler. 
  5770.  
  5771.                           Note: The "set" method procedure that the SOM 
  5772.                           Compiler generates by default for an attribute in the 
  5773.                           .h/.xh binding file (when the noset modifier is not 
  5774.                           used) does a shallow copy of the value that is passed 
  5775.                           to the attribute. For some attribute types, including 
  5776.                           strings and pointers, this may not be appropriate. 
  5777.                           For instance, the "set" method for an attribute of 
  5778.                           type string should perform a string copy, rather than 
  5779.                           a shallow copy, if the attribute's value may be 
  5780.                           needed after the client program has freed the memory 
  5781.                           occupied by the string. In such situations, the class 
  5782.                           implementer should specify the noset attribute 
  5783.                           modifier and implement the attribute's "set" method 
  5784.                           manually, rather than having SOM implement the "set" 
  5785.                           method automatically. 
  5786.  
  5787.  object_owns_parameters  ="p1, p2, ..., pn" 
  5788.  
  5789.  
  5790.                           Specifies the names of the method's parameters whose 
  5791.                           ownership is transferred to (in the case of "in" 
  5792.                           parameters) or is retained by (for "inout" or "out" 
  5793.                           parameters) the object.  For "in" parameters, the 
  5794.                           object can free the parameter at any time after 
  5795.                           receiving it. (Hence, the caller should not reuse the 
  5796.                           parameter or pass it as any other object-owned 
  5797.                           parameter in the same method call.) For "inout" and 
  5798.                           "out" parameters, the object is responsible for 
  5799.                           freeing the parameter sometime before the object is 
  5800.                           destroyed. This modifier is only valid in the 
  5801.                           interface specification of the method's introducing 
  5802.                           class. This modifier only makes sense for parameters 
  5803.                           whose IDL type is a data item that can be freed 
  5804.                           (string, object, array, pointer, or TypeCode), or a 
  5805.                           data item containing memory that can be freed (for 
  5806.                           example, a sequence or any), or a struct or union. 
  5807.  
  5808.                           For parameters whose type is an object, ownership 
  5809.                           applies to the object reference  rather than to the 
  5810.                           object (that is, the object will invoke release on 
  5811.                           the parameter, rather than somFree). For "in" and 
  5812.                           "out" parameters whose IDL-to-C/C++ mapping 
  5813.                           introduces a pointer, ownership applies only to the 
  5814.                           data item itself, and not to the introduced pointer. 
  5815.                           (For example, even if an "out string" IDL parameter 
  5816.                           (which becomes a "string *" C/C++ parameter) is 
  5817.                           designated as "object-owned,"  the object assumes 
  5818.                           ownership of the string, but not of the pointer to 
  5819.                           the string.) 
  5820.  
  5821.  object_owns_result       Specifies that the object retains ownership of the 
  5822.                           return result of the method, and that the caller must 
  5823.                           not free the memory. The object is responsible for 
  5824.                           freeing the memory sometime before the object is 
  5825.                           destroyed. This modifier is only valid in the 
  5826.                           interface specification of the method's introducing 
  5827.                           class. This modifier only makes sense when the 
  5828.                           method's return type is a data type that can be freed 
  5829.                           (string, object, array, pointer, or TypeCode), or a 
  5830.                           data item containing memory that can be freed (for 
  5831.                           example, a sequence or any). For methods that return 
  5832.                           an object, ownership applies to the object reference 
  5833.                           rather than to the object (that is, the object will 
  5834.                           be responsible for invoking release on the result, 
  5835.                           rather than somFree). 
  5836.  
  5837.  offset or namelookup     Indicates whether the SOM Compiler should generate 
  5838.                           bindings for invoking the method using offset 
  5839.                           resolution or name lookup. Offset resolution requires 
  5840.                           that the class of the method's target object be known 
  5841.                           at compile time. When different methods of the same 
  5842.                           name are defined by several classes, namelookup is a 
  5843.                           more appropriate technique for method resolution than 
  5844.                           is offset resolution. (See Chapter 3, the section 
  5845.                           entitled "Invoking Methods.")  The default modifier 
  5846.                           is offset. 
  5847.  
  5848.  override                 Indicates that the method is one introduced by an 
  5849.                           ancestor class and that this class will re-implement 
  5850.                           the method. See also the related modifier, select. 
  5851.  
  5852.  procedure                See "method or nonstatic or procedure." 
  5853.  
  5854.  reintroduce              Indicates that this interface will "hide" a method 
  5855.                           introduced by some ancestor interface, and will 
  5856.                           replace it with another implementation. Methods 
  5857.                           introduced as direct-call procedures or nonstatic 
  5858.                           methods can be reintroduced. However, static methods 
  5859.                           (the default implementation category for SOM met 
  5860.                           hods) cannot be reintroduced. 
  5861.  
  5862.  releaseorder: a, b, c, ... Specifies the order in which the SOM Compiler will 
  5863.                           place the class's methods in the data structures it 
  5864.                           builds to represent the class. Maintaining a 
  5865.                           consistent release order for a class allows the 
  5866.                           implementation of a class to change without requiring 
  5867.                           client programs to be recompiled. 
  5868.  
  5869.                           The release order should contain every method name 
  5870.                           introduced by the class (private and nonprivate), but 
  5871.                           should not include any inherited methods, even if 
  5872.                           they are overridden by the class. The "get" and "set" 
  5873.                           methods defined automatically for each new attribute 
  5874.                           (named "_get_<attributeName>" and 
  5875.                           "_set_<attributeName>") should also be included in 
  5876.                           the release order list. The order of the names on the 
  5877.                           list is unimportant except that once a name is on the 
  5878.                           list and the class has client programs, it should not 
  5879.                           be reordered or removed, even if the method is no 
  5880.                           longer supported by the class, or the client programs 
  5881.                           will require recompilation. New methods should be 
  5882.                           added only to the end of the list. If a method named 
  5883.                           on the list is to be moved up in the class hierarchy, 
  5884.                           its name should remain on the current list, but it 
  5885.                           should also be added to the release order list for 
  5886.                           the class that will now introduce it. 
  5887.  
  5888.                           If not explicitly specified, the release order will 
  5889.                           be determined by the SOM Compiler, and a warning will 
  5890.                           be issued for each missing method. If new methods or 
  5891.                           attributes are subsequently added to the class, the 
  5892.                           default release order might change; programs using 
  5893.                           the class would then require recompilation. Thus, it 
  5894.                           is advisable to explicitly give a release order. 
  5895.  
  5896.  select = parent          Used in conjunction with the override modifier, this, 
  5897.                           indicates that an inherited static method will use 
  5898.                           the implementation inherited from the indicated 
  5899.                           <parent> class. The parent is specified using the 
  5900.                           C-scoped name. For example, "Module_InterfaceName", 
  5901.                           not "Module:: InterfaceName". See the later topic 
  5902.                           "Name usage in client programs" for an explanation of 
  5903.                           C-scoped names. 
  5904.  
  5905.  staticdata               Indicates that the declared variable is not stored 
  5906.                           within objects, but, instead, that the ClassData 
  5907.                           structure for the implementing class will contain a 
  5908.                           pointer to the staticdata variable. This is similar 
  5909.                           in concept to C++ static data members. The staticdata 
  5910.                           variable must also be included in the releaseorder. 
  5911.                           The class implementor has responsibility for 
  5912.                           allocating the staticdata variable and for loading 
  5913.                           the ClassData structure's pointer to the staticdata 
  5914.                           variable during class initialization. (The pointer is 
  5915.                           accessible as <className>ClassData.<variableName>.) 
  5916.                           The implementor's responsibility can be facilitated 
  5917.                           by writing a special class initialization function 
  5918.                           and indicating its name using the classinit 
  5919.                           unqualified modifier. (See also the examples that 
  5920.                           follow.) 
  5921.  
  5922.                           Note:  Attributes can be declared as staticdata. This 
  5923.                                  is an important implementation technique that 
  5924.                                  allows classes to introduce attributes whose 
  5925.                                  backing storage is not inherited by 
  5926.                                  subclasses. 
  5927.  
  5928.  The following example illustrates the specification of qualified modifiers: 
  5929.  
  5930.   implementation
  5931.   {
  5932.     releaseorder : op1, op3, op2, op5, op6, x, y, _set_z, _get_z;
  5933.     op1 : persistent;
  5934.     somDefaultInit : override, init;
  5935.     op2: reintroduce, procedure;
  5936.     op3: reintroduce, nonstatic;
  5937.     op4: override, select = ModuleName_parentInterfaceName;
  5938.     op5: migrate = ModuleName_ancestorInterfaceName;
  5939.     op6: procedure, noself, noenv;
  5940.     long x;
  5941.     x: staticdata;
  5942.     y: staticdata; // y and z are attributes
  5943.     _set_z: object_owns_parameters = "name";
  5944.     _get_z: object_owns_result;
  5945.     mymod : a, b;
  5946.   };
  5947.  
  5948.  As shown above for attribute z, separate modifiers can be declared for an 
  5949.  attribute's _set and _get methods, using method modifiers. This capability may 
  5950.  be useful for DSOM applications. (See the DSOM sample program "animal" that is 
  5951.  distributed with the SOMobjects Toolkit.) 
  5952.  
  5953.  The next example for classes "X" and "Y" illustrates the use of a staticdata 
  5954.  modifier, along with its corresponding classinit modifier and the template 
  5955.  procedure generated for classinit by the SOM Compiler. 
  5956.  
  5957.   size='auto'.
  5958.   /* IDL for staticdata and classinit example: */
  5959.  
  5960.   #include <somobj.idl>
  5961.  
  5962.   interface X : SOMObject {
  5963.           attribute long staticAttribute;
  5964.           attribute long normalAttribute;
  5965.           implementation {
  5966.                   staticAttribute: staticdata;
  5967.                   classinit = Xinit;
  5968.                   releaseorder: staticAttribute,
  5969.                                       _get_staticAttribute,
  5970.                                       _set_staticAttribute,
  5971.                                       _get_normalAttribute,
  5972.                                       _set_normalAttribute;
  5973.           };
  5974.   };
  5975.  
  5976.   interface Y : X { };
  5977.  
  5978.   /* Template procedure for classInit: */
  5979.  
  5980.   #ifndef SOM_Module_classinit_Source
  5981.   #define SOM_Module_classinit_Source
  5982.   #endif
  5983.   #define X_Class_Source
  5984.  
  5985.   #include "classInit.ih"
  5986.  
  5987.   static long holdStaticAttribute = 1234;
  5988.   void SOMLINK Xinit(SOMClass *cls)
  5989.   {
  5990.           XClassData.staticAttribute = &holdStaticAttribute;
  5991.   }
  5992.  
  5993.   main()
  5994.   {
  5995.           X *x = XNew();
  5996.           Y *y = YNew();
  5997.  
  5998.           somPrintf("initial staticAttribute = x(%d) = y(%d)\n",
  5999.                                   _get_staticAttribute(x,0),
  6000.                                   _get_staticAttribute(y,0));
  6001.  
  6002.           _set_staticAttribute(x,0,42);
  6003.           _set_staticAttribute(y,0,4321);
  6004.  
  6005.           somPrintf("changed staticAttribute = x(%d) = y(%d)\n",
  6006.                                   _get_staticAttribute(x,0),
  6007.                                   _get_staticAttribute(y,0));
  6008.   }
  6009.  
  6010.   /* Program output:
  6011.  
  6012.           initial staticAttribute = x(1234) = y(1234)
  6013.           changed staticAttribute = x(4321) = y(4321)
  6014.           after setting normalAttribute, x(10) != y(20)
  6015.   */
  6016.  
  6017.  
  6018. ΓòÉΓòÉΓòÉ 5.2.8.4. Passthru statements ΓòÉΓòÉΓòÉ
  6019.  
  6020. A passthru statement (used within the body of an implementation statement, 
  6021. described above) allows a class implementer to specify blocks of code (for 
  6022. C/C++ programmers, usually only #include directives) that the SOM compiler will 
  6023. pass into the header files it generates. 
  6024.  
  6025. Passthru statements are included in SOM IDL primarily for backward 
  6026. compatibility with the SOM OIDL language, and their use by C and C++ 
  6027. programmers should be limited to #include directives. C and C++ programmers 
  6028. should use IDL type and constant declarations rather than passthru statements 
  6029. when possible. (Users of other languages, however, may require passthru 
  6030. statements for type and constant declarations.) 
  6031.  
  6032. The contents of the passthru lines are ignored by the SOM compiler and can 
  6033. contain anything that needs to placed near the beginning of a header file for a 
  6034. class. Even comments contained in passthru lines are processed without 
  6035. modification. The syntax for specifying passthru lines is one of the following 
  6036. forms: 
  6037.  
  6038.  passthru language_suffix      = literal+ ; 
  6039.  passthru language_suffix_before = literal+ ; 
  6040.  passthru language_suffix_after = literal+ ; 
  6041.  
  6042.  where "language" specifies the programming language and "suffix" indicates 
  6043.  which header files will be affected. The SOM Compiler supports suffixes h, ih, 
  6044.  xh, and xih. For both C and C++, "language" is specified as C. 
  6045.  
  6046.  Each "literal" is a string literal (enclosed in double quotes) to be placed 
  6047.  verbatim into the specified header file.  [Double quotes within the passthru 
  6048.  literal should be preceded by a backslash. No other characters escaped with a 
  6049.  backslash will be interpreted, and formatting characters (newlines, tab 
  6050.  characters, etc.) are passed through without processing.]  The last literal 
  6051.  for a passthru statement must not end in a backslash (put a space or other 
  6052.  character between a final backslash and the closing double quote). 
  6053.  
  6054.  When either of the first two forms is used, passthru  lines are placed before 
  6055.  the #include statements in the header file. When the third form is used, 
  6056.  passthru lines are placed just after the #include statements in the header 
  6057.  file. 
  6058.  
  6059.  For example, the following passthru statement 
  6060.  
  6061.      implementation
  6062.      {
  6063.        passthru C_h = "#include <foo.h>";
  6064.      };
  6065.  
  6066.  results in the directive #include <foo.h> being placed at the beginning of the 
  6067.  .h C binding file that the SOM Compiler generates. 
  6068.  
  6069.  For any given target file (as indicated by language_suffix), only one passthru 
  6070.  statement may be defined within each implementation section. You may, however, 
  6071.  define multiple #include statements in a single passthru. For legibility, each 
  6072.  #include should begin on a new line, optionally with a blank line to precede 
  6073.  and follow the #include list. For an example, see "Introducing non-IDL data 
  6074.  types or classes" later in this section. 
  6075.  
  6076.  
  6077. ΓòÉΓòÉΓòÉ 5.2.8.5. Declaring instance variables and staticdata variables ΓòÉΓòÉΓòÉ
  6078.  
  6079. Declarators are used within the body of an implementation statement (described 
  6080. above) to specify the instance variables that are introduced by a class, and 
  6081. the staticdata variables pointed to by the class's ClassData structure. These 
  6082. variables are declared using ANSI C syntax for variable declarations, 
  6083. restricted to valid SOM IDL types (see "Type and constant declarations," 
  6084. above). For example, the following implementation statement declares two 
  6085. instance variables, x and y, and a staticdata variable, z, for class "Hello," : 
  6086.  
  6087. implementation
  6088. {
  6089.   short x;
  6090.   long y;
  6091.   double z;
  6092.   z: staticdata;
  6093. };
  6094.  
  6095. Instance variables are normally intended to be accessed only by the class's 
  6096. methods and not by client programs or subclasses' methods. For data to be 
  6097. accessed by client programs or subclass methods, attributes should be used 
  6098. instead of instance variables. (Note, however, that declaring an attribute has 
  6099. the effect of also declaring an instance variable of the same name, unless the 
  6100. "nodata" attribute modifier is specified.) 
  6101.  
  6102. Staticdata variables, by contrast, are publicly available and are associated 
  6103. specifically with their introducing class. They are, however, very different in 
  6104. concept from class variables. Class variables are really instance variables 
  6105. introduced by a metaclass, and are therefore present in any class that is an 
  6106. instance of the introducing metaclass (or of any metaclass derived from this 
  6107. metaclass). As a result, class variables present in any given class will also 
  6108. be present in any class derived from this class (that is, class variables are 
  6109. inherited). In contrast, staticdata variables are introduced by a class (not a 
  6110. metaclass) and are (only) accessed from the class's ClassData structure - they 
  6111. are not inherited. 
  6112.  
  6113.  
  6114. ΓòÉΓòÉΓòÉ 5.2.8.6. Introducing non-IDL data types or classes ΓòÉΓòÉΓòÉ
  6115.  
  6116. On occasion, you may want a new .idl file to reference some element that the 
  6117. SOM Compiler would not recognize, such as a user-defined class or an instance 
  6118. variable or attribute with a user-defined data type. You can reference such 
  6119. elements if they already exist in .h or .xh files that the SOM Compiler can 
  6120. #include with your new .idl file, as follows: 
  6121.  
  6122.      To introduce a non-IDL class, insert an interface statement that is a 
  6123.       forward reference to the existing user-defined class. It must precede the 
  6124.       interface statement for the new class in the .idl file. 
  6125.  
  6126.      To declare an instance variable or attribute that is not a valid IDL 
  6127.       type, declare a dummy typedef preceding the interface declaration. 
  6128.  
  6129.      In each case above, in the implementation section use a passthru 
  6130.       statement to pass an #include statement into the language-specific 
  6131.       binding file(s) of the new .idl file (a) for the existing user-defined 
  6132.       class or (b) for the real typedef. 
  6133.  
  6134.  In the following example, the generic SOM type somToken is used in the .idl 
  6135.  file for the user's types "myRealType" and "myStructType". The passthru 
  6136.  statement then causes an appropriate #include statement to be emitted into the 
  6137.  C/C++ binding file, so that the file defining types "myRealType" and 
  6138.  "myStructType" will be included when the binding files process. In addition, 
  6139.  an interface declaration for "myOtherClass" is defined as a forward reference, 
  6140.  so that an instance of that class can be used within the definition of 
  6141.  "myCurrentClass". The passthru statement also #includes the binding file for 
  6142.  "myOtherClass": 
  6143.  
  6144.   typedef somToken myRealType;
  6145.   typedef somToken myStructType;
  6146.  
  6147.   interface myOtherClass;
  6148.  
  6149.   interface myCurrentClass : SOMObject {
  6150.   . . .
  6151.           implementation {
  6152.                   . . .
  6153.                   myRealType myInstVar;
  6154.                   attribute myStructType st1;
  6155.                   passthru C_h =
  6156.                           ""
  6157.                           "#include <myTypes.h>"
  6158.                           "#include <myOtherClass.h>"
  6159.                           "";
  6160.           };
  6161.   };
  6162.  
  6163.  Note: See also the section "Using the tk_foreign TypeCode" in Chapter 7, "The 
  6164.  Interface Repository Framework." 
  6165.  
  6166.  
  6167. ΓòÉΓòÉΓòÉ 5.2.9. Comments within a SOM IDL file ΓòÉΓòÉΓòÉ
  6168.  
  6169. SOM IDL supports both C and C++ comment styles. The characters "//" start a 
  6170. line comment, which finishes at the end of the current line. The characters 
  6171. "/*" start a block comment that finishes with the "*/". Block comments do not 
  6172. nest. The two comment styles can be used interchangeably. 
  6173.  
  6174. Comments in a SOM IDL specification must be strictly associated with particular 
  6175. syntactic elements, so that the SOM Compiler can put them at the appropriate 
  6176. place in the header and implementation files it generates. Therefore, comments 
  6177. may appear only in these locations (in general, following the syntactic unit 
  6178. being commented): 
  6179.  
  6180.      At the beginning of the IDL specification 
  6181.  
  6182.      After a semicolon 
  6183.  
  6184.      Before or after the opening brace of a module, interface statement, 
  6185.       implementation statement, structure definition, or union definition 
  6186.  
  6187.      After a comma that separates parameter declarations or enumeration 
  6188.       members 
  6189.  
  6190.      After the last parameter in a prototype (before the closing parenthesis) 
  6191.  
  6192.      After the last enumeration name in an enumeration definition (before the 
  6193.       closing brace) 
  6194.  
  6195.      After the colon following a case label of a union definition 
  6196.  
  6197.      After the closing brace of an interface statement 
  6198.  
  6199.  Numerous examples of the use of comments can be found in the Tutorial of 
  6200.  Chapter 2. 
  6201.  
  6202.  Because comments appearing in a SOM IDL specification are transferred to the 
  6203.  files that the SOM Compiler generates, and because these files are often used 
  6204.  as input to a programming language compiler, it is best within the body of 
  6205.  comments to avoid using characters that are not generally allowed in comments 
  6206.  of most programming languages. For example, the C language does not allow "*/" 
  6207.  to occur within a comment, so its use is to be avoided, even when using C++ 
  6208.  style comments in the .idl file. 
  6209.  
  6210.  SOM IDL also supports throw-away comments. They may appear anywhere in an IDL 
  6211.  specification, because they are ignored by the SOM Compiler and are not 
  6212.  transferred to any file it generates. Throw-away comments start with the 
  6213.  string "//#" and end at the end of the line. Throw-away comments can be used 
  6214.  to "comment out" portions of an IDL specification. 
  6215.  
  6216.  To disable comment processing (that is, to prevent the SOM Compiler from 
  6217.  transferring comments from the IDL specification to the binding files it 
  6218.  generates), use the -c option of the sc command when running the SOM Compiler 
  6219.  (See Section 4.3, "The SOM Compiler").  When comment processing is disabled, 
  6220.  comment placement is not restricted and comments can appear anywhere in the 
  6221.  IDL specification. 
  6222.  
  6223.  
  6224. ΓòÉΓòÉΓòÉ 5.2.10. Designating `private' methods and attributes ΓòÉΓòÉΓòÉ
  6225.  
  6226. To designate methods or attributes within an IDL specification as "private," 
  6227. the declaration of the method or attribute must be surrounded with the 
  6228. preprocessor commands #ifdef __PRIVATE__ (with two leading underscores and two 
  6229. following underscores) and #endif. For example, to declare a method "foo" as a 
  6230. private method, the following declaration would appear within the interface 
  6231. statement: 
  6232.  
  6233.    #ifdef __PRIVATE__
  6234.    void foo();
  6235.    #endif
  6236.  
  6237. Any number of methods and attributes can be designated as private, either 
  6238. within a single #ifdef or in separate ones. 
  6239.  
  6240. When compiling an .idl file, the SOM Compiler normally recognizes only public 
  6241. (nonprivate) methods and attributes, as that is generally all that is needed. 
  6242. To generate header files for client programs that do need to access private 
  6243. methods and attributes, or for use when implementing a class library containing 
  6244. private methods, the -p option should be included when running the SOM 
  6245. Compiler. The resulting header files will then include bindings for private, as 
  6246. well as public, methods and attributes. Both the implementation bindings (.ih 
  6247. or .xih file) and the usage bindings to be #included in the implementation (.h 
  6248. or .xh file) should be generated under the -p option. The -p option is 
  6249. described in the topic "Running the SOM Compiler" later in this chapter. 
  6250.  
  6251. The SOMobjects Toolkit also provides a pdl (Public Definition Language) emitter 
  6252. that can be used with the SOM Compiler to generate a copy of an .idl file which 
  6253. has the portions designated as private removed. The next main section of this 
  6254. chapter describes how to invoke the SOM Compiler and the various emitters. 
  6255.  
  6256.  
  6257. ΓòÉΓòÉΓòÉ 5.2.11. Module declarations to define multiple interfaces in a .idl file ΓòÉΓòÉΓòÉ
  6258.  
  6259. A single .idl file can define multiple interfaces. This allows, for example, a 
  6260. class and its metaclass to be defined in the same file. When a file defines two 
  6261. (or more) interfaces that reference one another, forward declarations can be 
  6262. used to declare the name of an interface before it is defined. This is done as 
  6263. follows: 
  6264.  
  6265. interface class-name ; 
  6266.  
  6267. The actual definition of the interface for "class-name" must appear later in 
  6268. the same .idl file. 
  6269.  
  6270. If multiple interfaces are defined in the same .idl file, and the classes are 
  6271. not a class-metaclass pair, they can be grouped into modules, by using the 
  6272. following syntax: 
  6273.  
  6274. module module-name { definition+ }; 
  6275.  
  6276. where each "definition" is a type declaration, constant declaration, exception 
  6277. declaration, interface statement, or nested module statement. Modules are used 
  6278. to scope identifiers (see below). 
  6279.  
  6280. Alternatively, multiple interfaces can be defined in a single .idl file without 
  6281. using a module to group the interfaces. Whether or not a module is used for 
  6282. grouping multiple interfaces, the languages bindings produced from the .idl 
  6283. file will include support for all of the defined interfaces. 
  6284.  
  6285. Note:  When multiple interfaces are defined in a single .idl file and a module 
  6286.        statement is not used for grouping these interfaces, it is necessary to 
  6287.        use the functionprefix modifier to assure that different names exist for 
  6288.        functions that provide different implementations for a method.  In 
  6289.        general, it is a good idea to always use the functionprefix modifier, 
  6290.        but in this case it is essential. 
  6291.  
  6292.  
  6293. ΓòÉΓòÉΓòÉ 5.2.12. Scoping and name resolution ΓòÉΓòÉΓòÉ
  6294.  
  6295. A .idl file forms a naming scope (or scope). Modules, interface statements, 
  6296. structures, unions, methods, and exceptions form nested scopes. An identifier 
  6297. can only be defined once in a particular scope. Identifiers can be redefined in 
  6298. nested scopes. 
  6299.  
  6300. Names can be used in an unqualified form within a scope, and the name will be 
  6301. resolved by successively searching the enclosing scopes. Once an unqualified 
  6302. name is defined in an enclosing scope, that name cannot be redefined. 
  6303.  
  6304. Fully qualified names are of the form: 
  6305.  
  6306. scoped-name::identifier 
  6307.  
  6308. For example, method name "meth" defined within interface "Test" of module "M1" 
  6309. would have the fully qualified name: 
  6310.  
  6311.   M1::Test::meth
  6312.  
  6313. A qualified name is resolved by first resolving the "scoped-name" to a 
  6314. particular scope S, then locating the definition of "identifier" within that 
  6315. scope. Enclosing scopes of S are not searched. 
  6316.  
  6317. Qualified names of the form: 
  6318.  
  6319.       ::identifier 
  6320.  
  6321.  These names are resolved by locating the definition of "identifier" within the 
  6322.  smallest enclosing module. 
  6323.  
  6324.  Every name defined in an IDL specification is given a global name, constructed 
  6325.  as follows: 
  6326.  
  6327.      Before the SOM Compiler scans an .idl file, the name of the current root 
  6328.       and the name of the current scope are empty. As each module is 
  6329.       encountered, the string "::" and the module name are appended to the name 
  6330.       of the current root. At the end of the module, they are removed. 
  6331.  
  6332.      As each interface, struct, union, or exception definition is encountered, 
  6333.       the string "::" and the associated name are appended to the name of the 
  6334.       current scope. At the end of the definition, they are removed. While 
  6335.       parameters of a method declaration are processed, a new unnamed scope is 
  6336.       entered so that parameter names can duplicate other identifiers. 
  6337.  
  6338.      The global name of an IDL definition is then the concatenation of the 
  6339.       current root, the current scope, a "::", and the local name for the 
  6340.       definition. 
  6341.  
  6342.  The names of types, constants, and exceptions defined by the parents of a 
  6343.  class are accessible in the child class. References to these names must be 
  6344.  unambiguous. Ambiguities can be resolved  by using a scoped name (prefacing 
  6345.  the name with the name of the class that defines it and the characters "::", 
  6346.  as in "parent-class::identifier). Scope names can also be used to refer to a 
  6347.  constant, type, or exception name defined by a parent class but redefined by 
  6348.  the child class. 
  6349.  
  6350.  
  6351. ΓòÉΓòÉΓòÉ 5.2.12.1. Name usage in client programs ΓòÉΓòÉΓòÉ
  6352.  
  6353. Within a C or C++ program, the global name for a type, constant, or exception 
  6354. corresponding to an IDL scoped name is derived by converting the string "::" to 
  6355. an underscore ("_") and removing the leading underscore. Such names are 
  6356. referred to as C-scoped names. This means that types, constants, and exceptions 
  6357. defined within the interface statement for a class can be referenced in a C/C++ 
  6358. program by prepending the class name to the name of the type, constant, or 
  6359. exception. For example, consider the types defined in the following IDL 
  6360. specification: 
  6361.  
  6362.    typedef sequence<long,10> mySeq;
  6363.    interface myClass : SOMObject
  6364.    {
  6365.       enum color {red, white, blue};
  6366.       typedef string<100> longString;
  6367.       ...
  6368.    }
  6369.  
  6370. These types could be accessed within a C or C++ program with the following 
  6371. global names: 
  6372.  
  6373. mySeq,
  6374. myClass_color,
  6375. myClass_red,
  6376. myClass_white,
  6377. myClass_blue, and
  6378. myClass_longString.
  6379.  
  6380. Type, constant, and exception names defined within modules similarly have the 
  6381. module name prepended. When using SOM's C/C++ bindings, the short form of type, 
  6382. constant, and exception names (such as, color, longString) can also be used 
  6383. where unambiguous, except that enumeration names must be referred to using the 
  6384. long form (for example, myClass_red and not simply red). 
  6385.  
  6386. Because replacing "::" with an underscore to create global names can lead to 
  6387. ambiguity if an IDL identifier contains underscores, it is best to avoid the 
  6388. use of underscores when defining IDL identifiers. 
  6389.  
  6390.  
  6391. ΓòÉΓòÉΓòÉ 5.2.13. Extensions to CORBA IDL permitted by SOM IDL ΓòÉΓòÉΓòÉ
  6392.  
  6393. The following topics describe several SOM-unique extensions of the standard 
  6394. CORBA syntax that are permitted by SOM IDL for convenience. These constructs 
  6395. can be used in an .idl file without generating a SOM Compiler error. 
  6396.  
  6397. If you want to verify that an IDL file contains only standard CORBA 
  6398. specifications, the SOM Compiler option -mcorba turns off each of these 
  6399. extensions and produces compiler errors wherever non-CORBA specifications are 
  6400. used. (The SOM Compiler command and options are described in the topic "Running 
  6401. the SOM Compiler" later in this chapter.) 
  6402.  
  6403.  
  6404. ΓòÉΓòÉΓòÉ 5.2.13.1. Pointer `*' types ΓòÉΓòÉΓòÉ
  6405.  
  6406. In addition to the base CORBA types, SOM IDL permits the use of pointer types 
  6407. (`*'). As well as increasing the range of base types available to the SOM IDL 
  6408. programmer, using pointer types also permits the construction of more complex 
  6409. data types, including self-referential and mutually recursive structures and 
  6410. unions. 
  6411.  
  6412. If self-referential structures and unions are required, then, instead of using 
  6413. the CORBA approach for IDL sequences, such as the following: 
  6414.  
  6415.    struct X {
  6416.        ...
  6417.        sequence <X> self;
  6418.        ...
  6419.    };
  6420.  
  6421. it is possible to use the more typical C/C++ approach. For example: 
  6422.  
  6423.    struct X {
  6424.        ...
  6425.        X *self;
  6426.        ...
  6427.    };
  6428.  
  6429. SOM IDL does not permit an explicit `*' in sequence declarations. If a sequence 
  6430. is required for a pointer type, then it is necessary to typedef the pointer 
  6431. type before use.  For example: 
  6432.  
  6433.    sequence <long *> long_star_seq;        // error.
  6434.  
  6435.    typedef long * long_star;
  6436.    sequence <long_star> long_star_seq;      // OK.
  6437.  
  6438.  
  6439. ΓòÉΓòÉΓòÉ 5.2.13.2. Unsigned types ΓòÉΓòÉΓòÉ
  6440.  
  6441. SOM IDL permits the syntax "unsigned <type>", where <type> is a previously 
  6442. declared type mapping onto "short" or "long".  (Note that CORBA permits only 
  6443. "unsigned short" and "unsigned long".) 
  6444.  
  6445.  
  6446. ΓòÉΓòÉΓòÉ 5.2.13.3. Implementation section ΓòÉΓòÉΓòÉ
  6447.  
  6448. SOM IDL permits an implementation section in an IDL interface specification to 
  6449. allow the addition of instance variables, method overrides, metaclass 
  6450. information, passthru information, and "pragma-like" information, called 
  6451. modifiers, for the emitters. See the topic "Implementation statements" earlier 
  6452. in this chapter. 
  6453.  
  6454.  
  6455. ΓòÉΓòÉΓòÉ 5.2.13.4. Comment processing ΓòÉΓòÉΓòÉ
  6456.  
  6457. The SOM IDL Compiler by default does not remove comments in the input source; 
  6458. instead, it attaches them to the nearest preceding IDL statement. This facility 
  6459. is useful, since it allows comments to be emitted in header files, C template 
  6460. files, documentation files, and so forth. However, if this capability is 
  6461. desired, this does mean that comments cannot be placed with quite as much 
  6462. freedom as with an ordinary IDL compiler. To turn off comment processing so 
  6463. that you can compile .idl files containing comments placed anywhere, you can 
  6464. use the compiler option -c or use "throw-away" comments throughout the .idl 
  6465. file (that is, comments preceded by //#); as a result, no comments will be 
  6466. included in the output files. 
  6467.  
  6468.  
  6469. ΓòÉΓòÉΓòÉ 5.2.13.5. Generated header files ΓòÉΓòÉΓòÉ
  6470.  
  6471. CORBA expects one header file, <file>.h, to be generated from <file>.idl. 
  6472. However, SOM IDL permits use of a class modifier, filestem, that changes this 
  6473. default output file name.  (See "Running the SOM Compiler" later in this 
  6474. chapter.) 
  6475.  
  6476.  
  6477. ΓòÉΓòÉΓòÉ 5.3. The SOM Compiler ΓòÉΓòÉΓòÉ
  6478.  
  6479. The SOM Compiler translates the IDL definition of a SOM class into a set of 
  6480. "binding files" appropriate for the language that will implement the class's 
  6481. methods and the language(s) that will use the class. These bindings make it 
  6482. more convenient for programmers to implement and use SOM classes. The SOM 
  6483. Compiler currently produces binding files for the C and C++ languages. 
  6484.  
  6485. Important Note: C and C++ bindings can not both be generated during the same 
  6486. execution of the SOM compiler. 
  6487.  
  6488.  
  6489. ΓòÉΓòÉΓòÉ 5.3.1. Generating binding files ΓòÉΓòÉΓòÉ
  6490.  
  6491. The SOM Compiler operates in two phases: 
  6492.  
  6493.      A precompile phase, in which a precompiler analyzes an OIDL or IDL class 
  6494.       definition, and 
  6495.  
  6496.      An emission phase, in which one or more  emitter programs produce 
  6497.       binding files. 
  6498.  
  6499.  Each binding file is generated by a separate emitter program. Setting the 
  6500.  SMEMIT environment variable determines which emitters will be used, as 
  6501.  described below. Note: In the discussion below, the <filesystem> is determined 
  6502.  by default from the name of the source .idl file with the ".idl" extension 
  6503.  removed. Otherwise, a "filestem" modifier can be defined in the .idl file to 
  6504.  specify another file name (see Modifier statements). 
  6505.  
  6506.  Note: If changes to definitions in the .idl file later become necessary, the 
  6507.  SOM Compiler should be rerun to update the current implementation template 
  6508.  file, provided that the c or xc emitter is specified (either with the -s 
  6509.  option or the SMEMIT environment variable, as described below). For more 
  6510.  information on generating updates, see "Running incremental updates of the 
  6511.  implementation template file" later in this chapter. 
  6512.  
  6513.  The emitters for the C language produce the following binding files: 
  6514.  
  6515.  <filestem>.c             (produced by the c emitter) 
  6516.  
  6517.                           This is a template for a C source program that 
  6518.                           implements a class's methods. This will become the 
  6519.                           primary source file for the class. (The other binding 
  6520.                           files can be generated from the .idl file as needed.) 
  6521.                           This template implementation file contains "stub" 
  6522.                           procedures for each method introduced or overridden 
  6523.                           by the class. (The stub procedures are empty of code 
  6524.                           except for required initialization and debugging 
  6525.                           statements.) 
  6526.  
  6527.                           After the class implementer has supplied the code for 
  6528.                           the method procedures, running the c emitter again 
  6529.                           will update the implementation file to reflect 
  6530.                           changes made to the class definition (in the .idl 
  6531.                           file). These updates include adding new stub 
  6532.                           procedures, adding comments, and changing method 
  6533.                           prototypes to reflect changes made to the method 
  6534.                           definitions in the IDL specification. Existing code 
  6535.                           within method procedures is not disturbed, however. 
  6536.  
  6537.                           The .c file contains an #include directive for the 
  6538.                           .ih file, described below. 
  6539.  
  6540.                           The contents of the C source template is controlled 
  6541.                           by the Emitter Framework file 
  6542.                           <SOMBASE>/include/ctm.efw. This file can be 
  6543.                           customized to change the template produced. 
  6544.  
  6545.  <filestem>.h             (produced by the h emitter) 
  6546.  
  6547.                           This is the header file to be included by C client 
  6548.                           programs (programs that use the class). It contains 
  6549.                           the C usage bindings for the class, including macros 
  6550.                           for accessing the class's methods and a macro for 
  6551.                           creating new instances of the class. This header file 
  6552.                           includes the header files for the class's parent 
  6553.                           classes and its metaclass, as well as the header file 
  6554.                           that defines SOM's generic C bindings, som.h. 
  6555.  
  6556.  <filestem>.ih            (produced by the ih emitter) 
  6557.  
  6558.                           This is the header file to be included in the 
  6559.                           implementation file (the file that implements the 
  6560.                           class's methods-the .c file). It contains the 
  6561.                           implementation bindings for the class, including: 
  6562.  
  6563.                               a struct defining the class's instance 
  6564.                                variables, 
  6565.                               macros for accessing instance variables, 
  6566.                               macros for invoking parent methods the class 
  6567.                                overrides, 
  6568.                               the <className>GetData  macro used by the method 
  6569.                                procedures in the <filestem>.c file (see "Stub 
  6570.                                procedures for methods" in Chapter 5.) 
  6571.                               a <className>NewClass procedure for constructing 
  6572.                                the class object at run time, and 
  6573.                               any IDL types and constants defined in the IDL 
  6574.                                interface. 
  6575.  
  6576.  The emitters for the C++ language produce the following binding files: 
  6577.  
  6578.  <filestem>.cpp           (produced by the xc emitter) 
  6579.  
  6580.                           This is a template for a C++ source program that 
  6581.                           implements a class's methods. This will become the 
  6582.                           primary source file for the class. (The other binding 
  6583.                           files can be generated from the .idl file as needed.) 
  6584.                           This template implementation file contains "stub" 
  6585.                           procedures for each method introduced or overridden 
  6586.                           by the class. (The stub procedures are empty of code 
  6587.                           except for required initialization and debugging 
  6588.                           statements.) 
  6589.  
  6590.                           After the class implementer has supplied the code for 
  6591.                           the method procedures, running the xc emitter again 
  6592.                           will update this file to reflect changes made to the 
  6593.                           class definition (in the .idl file). These updates 
  6594.                           include adding new stub procedures, adding comments, 
  6595.                           and changing method prototypes to reflect changes 
  6596.                           made to the method definitions in the IDL 
  6597.                           specification. Existing code within method procedures 
  6598.                           is not disturbed, however. 
  6599.  
  6600.                           The C++ implementation file contains an #include 
  6601.                           directive for the .xih file, described below. 
  6602.  
  6603.                           The contents of the C++ source template is controlled 
  6604.                           by the Emitter Framework file 
  6605.                           <SOMBASE>/include/ctm.efw. This file can be 
  6606.                           customized to change the template produced. 
  6607.  
  6608.  <filestem>.xh            (produced by the xh emitter) 
  6609.  
  6610.                           This is the header file to be included by C++ client 
  6611.                           programs that use the class. It contains the usage 
  6612.                           bindings for the class, including a C++ definition of 
  6613.                           the class, macros for accessing the class's methods, 
  6614.                           and the new operator for creating new instances of 
  6615.                           the class. This header file includes the header files 
  6616.                           for the class's parent classes and its metaclass, as 
  6617.                           well as the header file that defines SOM's generic 
  6618.                           C++ bindings, som.xh. 
  6619.  
  6620.  <filestem>.xih           (produced by the xih emitter) 
  6621.  
  6622.                           This is the header file to be included in the 
  6623.                           implementation file (the file that implements the 
  6624.                           class's methods). It contains the implementation 
  6625.                           bindings for the class, including: 
  6626.  
  6627.                               a struct defining the class's instance 
  6628.                                variables, 
  6629.                               macros for accessing instance variables, 
  6630.                               macros for invoking parent methods the class 
  6631.                                overrides, 
  6632.                               the <className>GetData  macro (see section 5.4), 
  6633.                               a <className>NewClass procedure for constructing 
  6634.                                the class object at run time, and 
  6635.                               any IDL types and constants defined in the IDL 
  6636.                                interface. 
  6637.  
  6638.  Other files the SOM Compiler generates: 
  6639.  
  6640.  <filestem>.hh            (produced by the hh emitter) 
  6641.  
  6642.                           This file is a DirectToSOM C++ header file that 
  6643.                           describes a SOMobjects class in a way appropriate to 
  6644.                           DTS C++. When running this emitter, you must include 
  6645.                           the noqualitytypes command-line modifier for the -m 
  6646.                           optionof the SOM Compiler command sc or somc. 
  6647.  
  6648.  <filestem>.pdl           (produced by the pdl emitter) This file is the same 
  6649.                           as the .idl file from which it is produced except 
  6650.                           that all items within the .idl file that are marked 
  6651.                           as "private" have been removed.  (an item is marked 
  6652.                           as private by surrounding it with "#ifdef_PRIVATE_" 
  6653.                           and "#endif" directives.  Thus, the pdl (Public 
  6654.                           Definition Lnguage) emitter can be used to generate a 
  6655.                           "public" version of the .idl file. 
  6656.  
  6657.  <filestem>.def           (produced by the def emitter) 
  6658.  
  6659.                           This file is used by the linker to package a class as 
  6660.                           a library. To combine several classes into a single 
  6661.                           library, you must merge the exports statements from 
  6662.                           each of their .def  files into a single .def file for 
  6663.                           the entire library. When packaging multiple classes 
  6664.                           in a single library, you must also write a simple C 
  6665.                           procedure named SOMInitModule and add it to the 
  6666.                           export list. This procedure should call the routine 
  6667.                           <className>NewClass for each class packaged in the 
  6668.                           library. The SOMInitModule procedure is called by the 
  6669.                           SOM Class Manager when the library is dynamically 
  6670.                           loaded. 
  6671.  
  6672.  The Interface Repository (produced by the ir emitter) 
  6673.  
  6674.                           See Chapter 7 for a discussion on the Interface 
  6675.                           Repository. 
  6676.  Note: The C/C++ bindings generated by the SOM Compiler have the following 
  6677.  limitation: If two classes named "ClassName" and "ClassNameC" are defined, the 
  6678.  bindings for these two classes will clash. That is, if a client program uses 
  6679.  the C/C++ bindings (includes the .h/.xh header file) for both classes, a name 
  6680.  conflict will occur. Thus, class implementers should keep this limitation in 
  6681.  mind when naming their classes. 
  6682.  
  6683.  SOM users can extend the SOM Compiler to generate additional files by writing 
  6684.  their own emitters. 
  6685.  
  6686.  Note re:  porting SOM classes: The header files (binding files) that the SOM 
  6687.  Compiler generates will only work on the platform (operating system) on which 
  6688.  they were generated. Thus, when porting SOM classes from the platform where 
  6689.  they were developed to another platform, the header files must be regenerated 
  6690.  from the .idl file by the SOM Compiler on that target platform. 
  6691.  
  6692.  
  6693. ΓòÉΓòÉΓòÉ 5.3.2. Environment variables affecting the SOM Compiler ΓòÉΓòÉΓòÉ
  6694.  
  6695. To execute the SOM Compiler on one or more files that contain IDL 
  6696. specifications for one or more classes, use the sc. as follows: 
  6697.  
  6698.       sc [-options] files 
  6699.  
  6700.  where "files" specifies one or more .idl files. 
  6701.  
  6702.  Available "-options" for the command are detailed in the next topic. The 
  6703.  operation of the SOM Compiler (whether it produces C binding files or C++ 
  6704.  binding files, for example) is also controlled by a set of environment 
  6705.  variables that can be set before the sc command is issued. The applicable 
  6706.  environment variables are as follows: 
  6707.  
  6708.  SMEMIT              Determines which output files the SOM Compiler produces. 
  6709.                      Its value consists of a list of items separated by 
  6710.                      semicolons Each item designates an emitter to execute. 
  6711.                      For example, the statement: 
  6712.  
  6713.                      SET SMEMIT=c;h;ih             (for C binding files) 
  6714.  
  6715.                      directs the SOM Compiler to produce the C binding files 
  6716.                      "hello.c", "hello.h", and"hello.ih" from the "hello.idl" 
  6717.                      input specification. By comparison, 
  6718.  
  6719.                      SET SMEMIT=xc;xh;xih 
  6720.  
  6721.                      directs the SOM Compiler to produce C++ binding files 
  6722.  
  6723.                                            "hello.cpp" (for OS/2)
  6724.                      , "hello.xh", and "hello.xih" from the "hello.idl" input 
  6725.                      specification. 
  6726.  
  6727.                      By default, all output files are placed in the same 
  6728.                      directory as the input file. If the SMEMIT environment 
  6729.                      variable is not set, then a default value of "h;ih" is 
  6730.                      assumed. 
  6731.  
  6732.  SMINCLUDE           Specifies where the SOM Compiler should look for .idl 
  6733.                      files #included by the .idl file being compiled. Its value 
  6734.                      should be one or more directory names separated by a 
  6735.                      semicolon Directory names can be specified with absolute 
  6736.                      or relative pathnames. For example: 
  6737.  
  6738.                      SET SMINCLUDE=.;..\MYSCDIR;C:\TOOLKT20\C\INCLUDE; 
  6739.  
  6740.                      The default value of the SMINCLUDE environment variable is 
  6741.                      the "include" subdirectory of the directory into which SOM 
  6742.                      has been installed. 
  6743.  
  6744.  SMTMP               Specifies the directory that the SOM Compiler should use 
  6745.                      to hold intermediate output files. This directory should 
  6746.                      not coincide with the directory of the input or output 
  6747.                      files. AIX, the default setting of SMTMP is /tmp; for 
  6748.                      OS/2, the default setting of SMTMP is the root directory 
  6749.                      of the current drive. For example: 
  6750.  
  6751.                                              SET SMTMP=..\MYSCDIR\GARBAGE
  6752.  
  6753.                      tells the SOM Compiler to place the temporary files in the 
  6754.                      GARBAGE directory. 
  6755.  
  6756.  
  6757.                      Or, : 
  6758.  
  6759.                                              SET SMTMP=%TMP%
  6760.  
  6761.                      tells the SOM Compiler to use the same directory for 
  6762.                      temporary files as given by the setting of the TMP 
  6763.                      environment variable (the defult location for temporary 
  6764.                      system files). 
  6765.  
  6766.  SMKNOWNEXTS         Specifies additional emitters to which the SOM Compiler 
  6767.                      should add a header. For example, if you were to write a 
  6768.                      new emitter for Pascal, called "emitpas", then by default 
  6769.                      the SOM Compiler would not add any header comments to it. 
  6770.                      However, by setting SMKNOWNEXTS=pas, as shown: 
  6771.  
  6772.                        set SMKNOWNEXTS=pas 
  6773.  
  6774.                      the SOM Compiler will add a header to files generated with 
  6775.                      the "emitpas" emitter. The "header" added is a SOM 
  6776.                      Compiler-generated message plus any comments, such as 
  6777.                      copyright statements, that appear at the head of your .idl 
  6778.                      input file. 
  6779.  
  6780.  SOMIR               Specifies the name (or list of names) of the Interface 
  6781.                      Repository file. The ir emitter, if run, creates the 
  6782.                      Interface Repository, or checks it for consistency if it 
  6783.                      already exists. If the -u option is specified when 
  6784.                      invoking the SOM Compiler, the ir emitter also updates an 
  6785.                      existing Interface Repository. 
  6786.  
  6787.  SMADDSTAR           When defined, causes all interface references to have a 
  6788.                      "*" added to them for the C bindings. The command-line 
  6789.                      options -maddstar and -mnoaddstar supercede and override 
  6790.                      the SMADDSTAR setting, however. 
  6791.  
  6792.  Note:  Environment variables that affect the SOM Compiler can be set for any 
  6793.         -m options of the SOM Compiler command. See the -m option in the 
  6794.         following topic, "Running the SOM Compiler." Also, the -E option in the 
  6795.         following topic can be used to set an environment variable. 
  6796.  
  6797.  
  6798. ΓòÉΓòÉΓòÉ 5.3.3. Running the SOM Compiler ΓòÉΓòÉΓòÉ
  6799.  
  6800. The syntax of the command for running the SOM Compiler takes the forms: 
  6801.  
  6802.       sc  [-options] files 
  6803.  
  6804.  The "files" specified in the sc command denote one or more files containing 
  6805.  the IDL class definitions to be compiled. If no extension is specified, .idl 
  6806.  is assumed. By default, the <filestem> of the .idl file determines the 
  6807.  filestem of each emitted file. Otherwise, a "filestem" modifier can be defined 
  6808.  in the .idl file to specify another name (see Modifier statements). 
  6809.  
  6810.  Selected "-options" can be specified individually, as a string of option 
  6811.  characters, or as a combination of both. Any option that takes an argument 
  6812.  either must be specified individually or must appear as the final option in a 
  6813.  string of option characters. Available options and their purposes are as 
  6814.  follows: 
  6815.  
  6816.  -C n        Sets the maximum allowable size for a simple comment in the .idl 
  6817.              file (default: 32767). This is only needed for very large single 
  6818.              comments. 
  6819.  
  6820.  -D name[=def] Defines name as in a #define directive. The default def is 1. 
  6821.              This option is the same as the -D option for the C compiler. Note: 
  6822.              This option can be used to define __PRIVATE__ so that the SOM 
  6823.              Compiler will also compile any methods and attributes that have 
  6824.              been defined as private using the directive  #ifdef__PRIVATE__; 
  6825.              however, the -p option does the same thing more easily. When a 
  6826.              class contains private methods or attributes, both the 
  6827.              implementation bindings and the usage bindings to be #included in 
  6828.              the implementation should be generated using either the -p or 
  6829.              -D_PRIVATE_ option. 
  6830.  
  6831.  -E variable=value Sets an environment variable. (See the previous topic for a 
  6832.              discussion of the available environment variables: SMADDSTAR, 
  6833.              SMEMIT, SMINCLUDE, SMTMP, SMKNOWNEXTS, and SOMIR.) 
  6834.  
  6835.  -I dir      When looking for #included files, looks first in dir, then in the 
  6836.              standard directories (same as the C compiler -I option). 
  6837.  
  6838.  -S n        Sets the total allowable amount of unique string space used in the 
  6839.              IDL specification for names and passthru lines (default: 32767). 
  6840.              This is only needed for very large .idl files. 
  6841.  
  6842.  -U name     Removes any initial definition (via a #define preprocessor 
  6843.              directive) of symbol name. 
  6844.  
  6845.  -V          Displays version information about the SOM Compiler. 
  6846.  
  6847.  -c          Turns off comment processing. This allows comments to appear 
  6848.              anywhere within an IDL specification (rather than in restricted 
  6849.              places), and it causes comments not to be transferred to the 
  6850.              output files that the SOM Compiler produces. 
  6851.  
  6852.  -d  directory Specifies a directory where all output files should be placed. 
  6853.              If the -d option is not used, all output files are placed in the 
  6854.              same directory as the input file. 
  6855.  
  6856.  -h or -?    Produces a listing of this option list. (This option is typically 
  6857.              used in an sc or command that does not include a .idl file name) 
  6858.  
  6859.  -i filename Specifies the name of the class definition file. Use this option 
  6860.              to override the built-in assumption that the input file will have 
  6861.              a .idl extension. Any filename supplied with the -i option is used 
  6862.              exactly as it is specified. 
  6863.  
  6864.  -m name[=value] Adds a global modifier. (See the following Note on the -m 
  6865.              options, which explains how to convert any "-m name" modifier to 
  6866.              an environment variable.) 
  6867.  
  6868.              Note:  All command-line -m modifier options can be specified in 
  6869.                     the environment by changing them to UPPERCASE and 
  6870.                     prepending "SM" to them. For example, if you want to always 
  6871.                     set the options "-mnotc" and "-maddstar", set corresponding 
  6872.                     environment variables as follows: 
  6873.  
  6874.                                             set SMNOTC=1
  6875.                                             set SMADDSTAR=1
  6876.  
  6877.              The currently supported global modifiers for the -m name[=value] 
  6878.              option are as follows: 
  6879.  
  6880.              addprefixes         Adds `functionprefixes' to the method 
  6881.                                  procedure prototypes during an incremental 
  6882.                                  update of the implementation template file. 
  6883.                                  This option applies only when rerunning the c 
  6884.                                  or xc emitter on an IDL file that previously 
  6885.                                  did not specify a functionprefix. A class 
  6886.                                  implementor who later decides to use prefixes 
  6887.                                  should add a line in the `implementation' 
  6888.                                  section of the .idl file containing the 
  6889.                                  specification: 
  6890.  
  6891.                                  functionprefix = prefix 
  6892.  
  6893.                                  (as described in Modifier statements) and then 
  6894.                                  rerun the c or xc emitter using the 
  6895.                                  -maddprefixes option. The method procedure 
  6896.                                  prototypes in the implementation file will 
  6897.                                  then be updated so that each method name 
  6898.                                  includes the assigned prefix. (This option 
  6899.                                  does not support changes to existing prefix 
  6900.                                  names, nor does it apply for OIDL files.) 
  6901.  
  6902.              addstar             This option causes all interface references to 
  6903.                                  have a `*' added to them for the C bindings. 
  6904.                                  See the earlier section entitled "Object 
  6905.                                  types" for further details. 
  6906.  
  6907.              comment=comment string where comment string can be either of the 
  6908.                                  designations: "/*"  or "//". This option 
  6909.                                  indicates that comments marked in the 
  6910.                                  designated manner in the .idl file are to be 
  6911.                                  completely ignored by the SOM Compiler and 
  6912.                                  will not be included in the output files. 
  6913.                                  Note: Comments on lines beginning with "//#" 
  6914.                                  are always ignored by the SOM Compiler. 
  6915.  
  6916.              corba               This option directs the SOM Compiler to 
  6917.                                  compile the input definition according to 
  6918.                                  strict CORBA-defined IDL syntax. This means, 
  6919.                                  for example, that comments may appear anywhere 
  6920.                                  and that pointers are not allowed. When the 
  6921.                                  -mcorba option is used, parts of a .idl file 
  6922.                                  surrounded by #ifdef__SOMIDL__ and #endif 
  6923.                                  directives are ignored. This option can be 
  6924.                                  used to determine whether all nonstandard 
  6925.                                  constructs (those specific to SOM IDL) are 
  6926.                                  properly protected by #ifdef__SOMIDL__ and 
  6927.                                  #endif directives. 
  6928.  
  6929.              csc                 This option forces the OIDL compiler to be 
  6930.                                  run. This is required only if you want to 
  6931.                                  compile an OIDL file that does not have an 
  6932.                                  extension of .csc or .sc. 
  6933.  
  6934.              emitappend          This option causes emitted files to be 
  6935.                                  appended at the end of existing files of the 
  6936.                                  same name. 
  6937.  
  6938.              noaccessors         This option turns off the automatic creation 
  6939.                                  of OperationDef entries in the Interface 
  6940.                                  Repository for attribute accessors (that is, 
  6941.                                  for an attribute's _set and _get methods). 
  6942.  
  6943.              noaddstar           This option ensures that interface references 
  6944.                                  will not have a "*" added to them for the C 
  6945.                                  bindings. This is the default setting; it is 
  6946.                                  the opposite of the -m compiler option 
  6947.                                  addstar. 
  6948.  
  6949.              noint               This option directs the SOM Compiler not to 
  6950.                                  warn about the portability problems of using 
  6951.                                  int's in the source. 
  6952.  
  6953.              nolock              This option causes the Interface Repository 
  6954.                                  Emitter emitir (see Chapter 7, "Interface 
  6955.                                  Repository Framework") to leave the IR 
  6956.                                  unlocked when updates are made to it. This can 
  6957.                                  improve performance on networked file systems. 
  6958.                                  By not locking the IR, however, there is the 
  6959.                                  risk of multiple processes attempting to write 
  6960.                                  to the same IR, with unpredictable results. 
  6961.                                  This option should only be used when you know 
  6962.                                  that only one process is updating an IR at 
  6963.                                  once. 
  6964.  
  6965.              nopp                This option directs the SOM Compiler not to 
  6966.                                  run the SOM preprocessor on the .idl input 
  6967.                                  file. 
  6968.  
  6969.              noqualifytypes      This option prevents the use od C-scoped names 
  6970.                                  in emitter output, and is used in conjunction 
  6971.                                  with the .hh emitter. 
  6972.  
  6973.              notc                This option directs the SOM Compiler not to 
  6974.                                  create TypeCode information when emitting IDL 
  6975.                                  files that contain some undeclared types. This 
  6976.                                  option is only used when compiling converted 
  6977.                                  .csc files (that is, OIDL files originally) 
  6978.                                  that have not had typing information added. 
  6979.  
  6980.              nouseshort          This option directs the SOM Compiler not to 
  6981.                                  generate short forms for type names in the .h 
  6982.                                  and .xh public header files. This can be 
  6983.                                  useful to save disk space. 
  6984.  
  6985.              pbl                 This option tells the SOM Compiler that, in 
  6986.                                  declarations containing a linkage specifier, 
  6987.                                  the "*" will appear before the linkage 
  6988.                                  specifier. This is required when using any C++ 
  6989.                                  compiler (Watcom is a known example) that 
  6990.                                  cannot handle declarations in the default 
  6991.                                  format where the "*" follows the linkage 
  6992.                                  specifier. A default example is the 
  6993.                                  declaration: 
  6994.  
  6995.                                                                   typedef void (SOMLINK * somTD_SOMObject_somFree)
  6996.                                                                                (SOMObject *somSelf);
  6997.  
  6998.                                  Under the -mpbl option of the SOM Compiler 
  6999.                                  command, the same example would be declared 
  7000.                                  as: 
  7001.  
  7002.                                                                   typedef void (* SOMLINK somTD_SOMObject_somFree)
  7003.                                                                                (SOMObject *somSelf);
  7004.  
  7005.              pp=preprocessor     This option directs the SOM Compiler to use 
  7006.                                  the specified preprocessor as the SOM 
  7007.                                  preprocessor, rather than the default 
  7008.                                  "somcpp". Any standard C/C++ preprocessor can 
  7009.                                  be used as a preprocessor for IDL 
  7010.                                  specifications. 
  7011.  
  7012.              tcconsts            This option directs the SOM Compiler to 
  7013.                                  generate TypeCode constants in the h and .xh 
  7014.                                  public header files. Please refer to the 
  7015.                                  Interface Repository (described in Chapter 7) 
  7016.                                  for more details. 
  7017.  
  7018.  -p          Causes the "private" sections of the IDL file to be included in 
  7019.              the compilation (that is, sections preceded by #ifdef __PRIVATE__ 
  7020.              that contain private methods and attributes). Note: If -p is used, 
  7021.              it must be applied for both the implementation bindings (.ih or 
  7022.              .xih file) and the usage bindings (.h or .xh file) to be #included 
  7023.              in the implementation. 
  7024.  
  7025.  -r          Checks that all names specified in the release order statement are 
  7026.              valid method names (default: FALSE). 
  7027.  
  7028.  -s string   Substitutes string in place of the contents of the SMEMIT 
  7029.              environment variable for the duration of the current sc command. 
  7030.              This determines which emitters will be run and, hence, which 
  7031.              output files will be produced. (If a list of values is given, the 
  7032.              list must be enclosed in double quotes.) 
  7033.  
  7034.              The -s option is a convenient way to override the SMEMIT 
  7035.              environment variable. The command: 
  7036.  
  7037.                              > SC -s"h;c" EXAMPLE
  7038.  
  7039.              is equivalent to the following sequence of commands: 
  7040.  
  7041.                              > SET OLDSMEMIT=%SMEMIT%
  7042.                              > SET SMEMIT=H;C
  7043.                              > SC EXAMPLE
  7044.                              > SET SMEMIT=%OLDSMEMIT%
  7045.  
  7046.  -u          Updates the Interface Repository (default: no update). With this 
  7047.              option, the Interface Repository will be updated even if the ir 
  7048.              emitter is not explicitly requested in the SMEMIT environment 
  7049.              variable or the -s option. 
  7050.  
  7051.  -v          Uses verbose mode to display informational messages (default: 
  7052.              FALSE). This option is primarily intended for debugging purposes 
  7053.              and for writers of emitters. 
  7054.  
  7055.  -w          Suppresses warning messages (default: FALSE). 
  7056.  
  7057.  The following sample commands illustrate various options for the sc command: 
  7058.  
  7059.  sc -sc hello.idl         Generates file "hello.c". 
  7060.  
  7061.  sc -hV                   Generates a help message and displays the version of 
  7062.                           the SOM Compiler currently available. 
  7063.  
  7064.  sc -vsh";"ih hello.idl   Generates "hello.h" and "hello.ih" with informational 
  7065.                           messages. 
  7066.  
  7067.  sc -sxc -doutdir hello.idl Generates "hello.xc" in directory "outdir". 
  7068.  
  7069.  
  7070. ΓòÉΓòÉΓòÉ 5.4. The `pdl' Facility ΓòÉΓòÉΓòÉ
  7071.  
  7072. As discussed earlier in this chapter, the SOM Compiler provides a pdl (Public 
  7073. Definition Language) emitter. This emitter generates a file that is the same as 
  7074. the .idl file from which it is produced, except that it removes all items 
  7075. within the .idl file that are marked as "private." An item is marked as private 
  7076. by surrounding it with "#ifdef_ _PRIVATE_ _" and "#endif" directives. Thus, the 
  7077. pdl emitter can be used to generate a "public" version of a .idl file. 
  7078. (Generally, client programs will need only the "public" methods and 
  7079. attributes.) 
  7080.  
  7081. The SOMobjects Toolkit also provides a separate program, pdl, which performs 
  7082. the same function as the pdl emitter, but can be invoked independently of the 
  7083. SOM Compiler. In addition, the pdl program can remove any kind of items in the 
  7084. .idl file that are preceded by a user-specified "#ifdef" directive and followed 
  7085. by an "#endif" directive:  The pdl  program is invoked as follows: 
  7086.  
  7087.         pdl [ -c | d | f | h | s |/]  files 
  7088.  
  7089.  where "files" specifies one or more .idl files whose specified "#ifdef" 
  7090.  sections are to be removed.  Filenames must be completely specified (with the 
  7091.  .idl extension).  If no "#ifdef" directive is specified (by including a 
  7092.  -/<string> option), then the "#ifdef_ _PRIVATE_ __"sections will be removed by 
  7093.  default. 
  7094.  
  7095.  The pdl command supports the following options.  (Selected options can be 
  7096.  specified individually, as a string of option characters, or as a combination 
  7097.  of both. Any option that takes an argument either must be specified 
  7098.  individually or must appear as the final option in a string of option 
  7099.  characters.) 
  7100.  
  7101.  -c cmd      Specifies that, for each .idl file, the pdl program is to run the 
  7102.              specified system command. This command may contain a single 
  7103.              occurrence of the string "%s", which will be replaced with the 
  7104.              source file name before the command is executed. For example the 
  7105.              option -c"sc -sh %s" has the same effect as issuing the sc command 
  7106.              with the -sh option. 
  7107.  
  7108.  -d dir      Specifies a directory in which the output files are to be placed. 
  7109.              (The output files are given the same name as the input files.) If 
  7110.              no directory is specified, the output files are named 
  7111.              <fileStem>.pdl (where fileStem is the file stem of the input file) 
  7112.              and are placed in the current working directory. 
  7113.  
  7114.  -h          Requests this description of the pdl command syntax and options. 
  7115.  
  7116.  -f          Specifies that output files are to replace existing files with the 
  7117.              same name, even if the existing files are read-only. By default, 
  7118.              files are replaced only if they have write access. 
  7119.  
  7120.  -s smemit   Specifies the SMEMIT variable with which the pdl program is to 
  7121.              invoke the SOM Compiler. 
  7122.  
  7123.  -/ <string> Specifies the "#ifdef" pattern for which the pdl program will 
  7124.              strip out .idl statements. The default is "#ifdef _ _PRIVATE_ _". 
  7125.  
  7126.  For example, to install public versions of the .idl files in the directory 
  7127.  "pubinclude", type: 
  7128.  
  7129.      pdl -d pubinclude *.idl
  7130.  
  7131.  
  7132. ΓòÉΓòÉΓòÉ 6. Implementing Classes in SOM ΓòÉΓòÉΓòÉ
  7133.  
  7134. This chapter begins with a more in-depth discussion of SOM concepts and the SOM 
  7135. run-time environment than was appropriate in Tutorial for Implementing SOM 
  7136. Classes. Subsequent sections then provide information about completing an 
  7137. implementation template file, updating the template file, compiling and 
  7138. linking, packaging classes in libraries, and other useful topics for class 
  7139. implementors. During this process, you can refer to Chapter 4, "SOM IDL and the 
  7140. SOM Compiler," if you want to read the reference information or see the full 
  7141. syntax related to topics discussed in this chapter. The current chapter ends 
  7142. with topics describing how to customize SOMobjects execution in various ways. 
  7143.  
  7144.  
  7145. ΓòÉΓòÉΓòÉ 6.1. The SOM Run-Time Environment ΓòÉΓòÉΓòÉ
  7146.  
  7147. The SOMobjects Developer Toolkit provides 
  7148.  
  7149.      The SOM Compiler, used when creating SOM class libraries, and 
  7150.  
  7151.      The SOM run-time library, for using SOM classes at execution time. 
  7152.  
  7153.  The SOM run-time library provides a set of functions used primarily for 
  7154.  creating objects and invoking methods on them. The data structures and objects 
  7155.  that are created, maintained, and used by the functions in the SOM run-time 
  7156.  library constitute the SOM run-time environment. 
  7157.  
  7158.  A distinguishing characteristic of the SOM run-time environment is that SOM 
  7159.  classes are represented by run-time objects; these objects are called class 
  7160.  objects.  By contrast, other object-oriented languages such as C++ treat 
  7161.  classes strictly as compile-time structures that have no properties at run 
  7162.  time. In SOM, however, each class has a corresponding run-time object. This 
  7163.  has three advantages:  First, application programs can access information 
  7164.  about a class at run time, including its relationships with other classes, the 
  7165.  methods it supports, the size of its instances, and so on. Second, because 
  7166.  much of the information about a class is established at run time rather than 
  7167.  at compile time, application programs needn't be recompiled when this 
  7168.  information changes. Finally, because class objects can be instances of 
  7169.  user-defined classes in SOM, users can adapt the techniques for subclassing 
  7170.  and inheritance in order to build object-oriented solutions to problems that 
  7171.  are otherwise not easily addressed within an OOP context. 
  7172.  
  7173.  
  7174. ΓòÉΓòÉΓòÉ 6.1.1. Run-time environment initialization ΓòÉΓòÉΓòÉ
  7175.  
  7176. When the SOM run-time environment is initialized, four primitive SOM objects 
  7177. are automatically created. Three of these are class objects (SOMObject, 
  7178. SOMClass, and SOMClassMgr), and one is an instance of SOMClassMgr, called the 
  7179. SOMClassMgrObject. Once loaded, application programs can invoke methods on 
  7180. these class objects to perform tasks such as creating other objects, printing 
  7181. the contents of an object, freeing objects, and the like. These four primitive 
  7182. objects are discussed below. 
  7183.  
  7184. In addition to creating the four primitive SOM objects, initialization of the 
  7185. SOM run-time environment also involves initializing global variables to hold 
  7186. data structures that maintain the state of the environment.  Other functions in 
  7187. the SOM run-time library rely on these global variables. 
  7188.  
  7189. For application programs written in C or C++ that use the language-specific 
  7190. bindings provided by SOM, the SOM run-time environment is automatically 
  7191. initialized the first time any object is created.  Programmers using other 
  7192. languages must initialize the run-time environment explicitly by calling the 
  7193. somEnvironmentNew function (provided by the SOM run-time library) before using 
  7194. any other SOM functions or methods. 
  7195.  
  7196.  
  7197. ΓòÉΓòÉΓòÉ 6.1.1.1. SOMObject class object ΓòÉΓòÉΓòÉ
  7198.  
  7199. SOMObject is the root class for all SOM classes. It defines the essential 
  7200. behavior common to all SOM objects.  All user-defined SOM classes are derived, 
  7201. directly or indirectly, from this class. That is, every SOM class is a subclass 
  7202. of SOMObject or of some other class derived from SOMObject. SOMObject has no 
  7203. instance variables, thus objects that inherit from SOMObject incur no size 
  7204. increase. They do inherit a suite of methods that provide the behavior required 
  7205. of all SOM objects. 
  7206.  
  7207.  
  7208. ΓòÉΓòÉΓòÉ 6.1.1.2. SOMClass class object ΓòÉΓòÉΓòÉ
  7209.  
  7210. Because SOM classes are run-time objects, and since all run-time objects are 
  7211. instances of some class, it follows that a SOM class object must also be an 
  7212. instance of some class. The class of a class is called a metaclass. Hence, the 
  7213. instances of an ordinary class are individuals (nonclasses), while the 
  7214. instances of a metaclass are class objects. 
  7215.  
  7216. In the same way that the class of an object defines the "instance methods" that 
  7217. the object can perform, the metaclass of a class defines the "class methods" 
  7218. that the class itself can perform. Class methods (sometimes called factory 
  7219. methods or constructors) are performed by class objects. Class methods perform 
  7220. tasks such as creating new instances of a class, maintaining a count of the 
  7221. number of instances of the class, and other operations of a "supervisory" 
  7222. nature. Also, class methods facilitate inheritance of instance methods from 
  7223. parent classes. For information on the distinction between parent classes and 
  7224. metaclasses, see the section "Parent Class vs. metaclass," later in this 
  7225. chapter. 
  7226.  
  7227. SOMClass is the root class for all SOM metaclasses.  That is, all SOM 
  7228. metaclasses must be subclasses of SOMClass or of some metaclass derived from 
  7229. SOMClass. SOMClass defines the essential behavior common to all SOM class 
  7230. objects.  In particular, SOMClass provides: 
  7231.  
  7232.      Six class methods for creating new class instances: somNew, somNewNoInit, 
  7233.       somRenew, somRenewNoInit, somRenewNoZero  and somRenewNoInitNoZero. 
  7234.  
  7235.      A number of class methods that dynamically obtain or update information 
  7236.       about a class and its methods at run time, including: 
  7237.  
  7238.         -  somInitMIClass, for implementing multiple inheritance from parent 
  7239.            classes, 
  7240.  
  7241.         -  somOverrideSMethod, for overriding inherited methods, and 
  7242.  
  7243.         -  somAddStaticMethod and somAddDynamicMethod, for including new 
  7244.            methods. 
  7245.  
  7246.  SOMClass is a subclass (or child) of SOMObject. Hence, SOM class objects can 
  7247.  also perform the same set of basic instance methods common to all SOM objects. 
  7248.  This is what allows SOM classes to be real objects in the SOM run-time 
  7249.  environment. SOMClass also has the unique distinction of being its own 
  7250.  metaclass (that is, SOMClass defines its own class methods). 
  7251.  
  7252.  A user-defined class can designate as its metaclass either SOMClass or another 
  7253.  user-written metaclass descended from SOMClass. If a metaclass is not 
  7254.  explicitly specified, SOM determines one automatically. 
  7255.  
  7256.  
  7257. ΓòÉΓòÉΓòÉ 6.1.1.3. SOMClassMgr class object and SOMClassMgrObject ΓòÉΓòÉΓòÉ
  7258.  
  7259. The third primitive SOM class is SOMClassMgr. A single instance of the 
  7260. SOMClassMgr class is created automatically during SOM initialization. This 
  7261. instance is referred to as the SOMClassMgrObject, because it is pointed to by 
  7262. the global variable SOMClassMgrObject. The object SOMClassMgrObject has the 
  7263. responsibility to 
  7264.  
  7265.      Maintain a registry (a run-time directory) of all SOM classes that exist 
  7266.       within the current process, and to 
  7267.  
  7268.      Assist in the dynamic loading and unloading of class libraries. 
  7269.  
  7270.  For C/C++ application programs using the SOM C/C++ language bindings, the 
  7271.  SOMClassMgrObject automatically loads the appropriate library file and 
  7272.  constructs a run-time object for the class the first time an instance of a 
  7273.  class is created. For programmers using other languages, SOMClassMgr provides 
  7274.  a method, somFindClass, for directing the SOMClassMgrObject to load the 
  7275.  library file for a class and create its class object. 
  7276.  
  7277.  Again, the primitive classes supplied with SOM are SOMObject, SOMClass, and 
  7278.  SOMClassMgr.  During SOM initialization, the latter class generates an 
  7279.  instance called SOMClassMgrObject. The SOMObject class is the parent class of 
  7280.  SOMClass and SOMClassMgr. The SOMClass class is the metaclass of itself, of 
  7281.  SOMObject, and of SOMClassMgr, which are all class objects at run time. 
  7282.  SOMClassMgr is the class of SOMClassMgrObject. 
  7283.  
  7284.  
  7285. ΓòÉΓòÉΓòÉ 6.1.2. Parent class vs. metaclass ΓòÉΓòÉΓòÉ
  7286.  
  7287. There is a distinct difference between the notions of "parent" (or base) class 
  7288. and "metaclass." Both notions are related to the fact that a class defines the 
  7289. methods and variables of its instances, which are therefore called instance 
  7290. methods and instance variables. 
  7291.  
  7292. A parent of a given class is a class from which the given class is derived  by 
  7293. subclassing. (Thus, the given class is called a child or a subclass  of the 
  7294. parent.) A parent class is a class from which instance methods and instance 
  7295. variables are inherited. For example, the parent of class "Dog" might be class 
  7296. "Animal". Hence, the instance methods and variables introduced by "Animal" 
  7297. (such as methods for breathing and eating, or a variable for storing an 
  7298. animal's weight) would also apply to instances of "Dog", because "Dog" inherits 
  7299. these from "Animal", its parent class. As a result, any given dog instance 
  7300. would be able to breath and eat, and would have a weight. 
  7301.  
  7302. A metaclass is a class whose instances are class objects, and whose instance 
  7303. methods and instance variables (as described above) are therefore the methods 
  7304. and variables of class objects. For this reason, a metaclass is said to define 
  7305. class methods-the methods that a class object performs. For example, the 
  7306. metaclass of "Animal" might be "AnimalMClass", which defines the methods that 
  7307. can be invoked on class "Animal" (such as, to create Animal instances-objects 
  7308. that are not classes, like an individual pig or cat or elephant or dog). 
  7309.  
  7310. Note: It is important to distinguish the methods of a class object (that is, 
  7311. the methods that can be invoked on the class object, which are defined by its 
  7312. metaclass) from the methods that the class defines for its instances. 
  7313.  
  7314. To summarize: the parent of a class provides inherited methods that the class's 
  7315. instances can perform; the metaclass of a class provides class methods that the 
  7316. class itself can perform.  These distinctions are further summarized below: The 
  7317. distinctions between parent class and metaclass are summarized in A class has 
  7318. both parent classes and a metaclass. 
  7319.  
  7320.  
  7321. A class has both parent classes and a metaclass
  7322.  
  7323. Any class "C" has both a metaclass and one or more parent class(es). 
  7324.  
  7325.      The parent class(es) of "C" provide the inherited instance methods that 
  7326.       individual instances (objects "O{i}") of class "C" can perform. Instance 
  7327.       methods that an instance "O{i}" performs might include (a) initializing 
  7328.       itself, (b) performing computations using its instance variables, (c) 
  7329.       printing its instance variables, or (d) returning its size. New instance 
  7330.       methods are defined by "C" itself, in addition to those inherited from 
  7331.       C's parent classes. 
  7332.  
  7333.      The metaclass "M"defines the class methods that class "C" can perform. 
  7334.       For example, class methods defined by metaclass "M" include those that 
  7335.       allow "C" to (a) inherit its parents' instance methods and instance 
  7336.       variables, (b) tell its own name, (c) create new instances, and (d) tell 
  7337.       how many instance methods it supports. These methods are inherited from 
  7338.       SOMClass. Additional methods supported by "M" might allow "C" to count 
  7339.       how many instances it creates. 
  7340.  
  7341.      Each class "C" has one or more parent classes and exactly one metaclass. 
  7342.       (The single exception is SOMObject, which has no parent class.)  Parent 
  7343.       class(es) must be explicitly identified in the IDL declaration of a 
  7344.       class. (SOMObject is given as a parent if no subsequently-derived class 
  7345.       applies.)  If a metaclass is not explicitly listed, the SOM run time will 
  7346.       determine an applicable metaclass. 
  7347.  
  7348.      An instance of a metaclass is always another class object. For example, 
  7349.       class "C" is an instance of metaclass "M".  SOMClass is the SOM-provided 
  7350.       metaclass from which all subsequent metaclasses are derived. 
  7351.  
  7352.  A metaclass has its own inheritance hierarchy (through its parent classes) 
  7353.  that is independent of its instances' inheritance hierarchies. For example, 
  7354.  suppose a series of classes is defined (or derived), stemming from SOMObject. 
  7355.  The child class (or subclass) at the end of this line ("C[2]") inherits 
  7356.  instance methods from all of its ancestor classes (here, SOMObject  and 
  7357.  "C[1]"). An instance created by "C2" can perform any of these instance 
  7358.  methods.  In an analogous manner, a line of metaclasses can be defined, 
  7359.  stemming from SOMClass. Just as a new class is derived from an existing class 
  7360.  (such as SOMObject), a new metaclass is derived from an existing metaclass 
  7361.  (such as SOMClass). 
  7362.  
  7363.  
  7364.   Parent classes and metaclasses each have their own independent inheritance hierrarchies
  7365.  
  7366.  
  7367. ΓòÉΓòÉΓòÉ 6.1.3. SOM-derived metaclasses ΓòÉΓòÉΓòÉ
  7368.  
  7369. As previously discussed, a class object can perform any of the class methods 
  7370. that its metaclass defines. New metaclasses are typically created to modify 
  7371. existing class methods or introduce new class method(s). Chapter 8, "Metaclass 
  7372. Framework," discusses metaclass programming. 
  7373.  
  7374. Three factors are essential for effective use of metaclasses in SOM: 
  7375.  
  7376.      First, every class in SOM is an object that is implemented by a 
  7377.       metaclass. 
  7378.  
  7379.      Second, programmers can define and name new metaclasses, and can use 
  7380.       these metaclasses when defining new SOM classes. 
  7381.  
  7382.      Finally, and most importantly, metaclasses cannot interfere with the 
  7383.       fundamental guarantee required of every OOP system: specifically, any 
  7384.       code that executes without method-resolution error on instances of a 
  7385.       given class will also execute without method-resolution errors on 
  7386.       instances of any subclass of this class. 
  7387.  
  7388.  Surprisingly, SOM is currently the only OOP system that can make this final 
  7389.  guarantee while also allowing programmers to explicitly define and use named 
  7390.  metaclasses. This is possible because SOM automatically determines an 
  7391.  appropriate metaclass that supports this guarantee, automatically deriving new 
  7392.  metaclasses by subclassing at run time when this is necessary. As an example, 
  7393.  suppose class "A" is an instance of metaclass "AMeta". 
  7394.  
  7395.  Assume that "AMeta" supports a method "bar" and that "A" supports a method 
  7396.  "foo" that uses the expression "_bar( _somGetClass(somSelf ) )." That is, 
  7397.  method "foo" invokes "bar" on the class of the object on which "foo" is 
  7398.  invoked. For example, when method "foo" is invoked on an instance of class "A" 
  7399.  (say, object "O{1}"), this in turn invokes "bar" on class "A" itself. 
  7400.  
  7401.  Now consider what happens if class "A" were subclassed by "B," a class that 
  7402.  has the explicit metaclass "BMeta" declared in its SOM IDL source file (and 
  7403.  assuming "BMeta" is not derived from "AMeta"). Also assume that object "O{2}" 
  7404.  is an instance of class "B." 
  7405.  
  7406.  Recall that "AMeta" supports method "bar" and that class "A" supports method 
  7407.  "foo" (which incorporates "bar" in its definition). Given the hierarchy 
  7408.  described above, an invocation of "foo" on "O {2}" would fail, because 
  7409.  metaclass "BMeta" does not support the "bar" method. 
  7410.  
  7411.  
  7412.   Example of Metaclass Incompatibility
  7413.  
  7414.  There is only one way that "BMeta" can support this specific method-by 
  7415.  inheriting it from "AMeta" ("BMeta" could introduce another method named 
  7416.  "bar", but this would be a different method from the one introduced by 
  7417.  "AMeta"). Therefore, in this example, because "BMeta" is not a subclass of 
  7418.  "AMeta", "BMeta" cannot be allowed to be the metaclass of "B". That is, 
  7419.  "BMeta" is not compatible with the requirements placed on "B" by the 
  7420.  fundamental principle of OOP referred to above. This situation is referred to 
  7421.  as metaclass incompatibility. 
  7422.  
  7423.  SOM does not allow hierarchies with metaclass incompatibilities. Instead, SOM 
  7424.  automatically builds derived metaclasses when this is necessary. For example, 
  7425.  SOM would create a "DerivedMeta" metaclass that has both "AMeta" and "BMeta" 
  7426.  as parents. This ensures that the invocation of method "foo" on instances of 
  7427.  class "B" will not fail, and also ensures that the desired class methods 
  7428.  provided by "BMeta" will be available on class "B". 
  7429.  
  7430.  
  7431.   Example of a Derived Metaclass
  7432.  
  7433.  There are three important aspects of SOM's approach to derived metaclasses: 
  7434.  
  7435.      First, the creation of SOM-derived metaclasses is integrated with 
  7436.       programmer-specified metaclasses. If a programmer-specified metaclass 
  7437.       already supports all the class methods and variables needed by a new 
  7438.       class, then the programmer-specified metaclass will be used as is. 
  7439.  
  7440.      Second, if SOM must derive a different metaclass than the one explicitly 
  7441.       indicated by the programmer (in order to support all the necessary class 
  7442.       methods and variables), then the SOM-derived metaclass inherits from the 
  7443.       explicitly indicated metaclass first. As a result, the method procedures 
  7444.       defined by the specified metaclass take precedence over other 
  7445.       possibilities (see the following section on inheritance and the 
  7446.       discussion of resolution of ambiguity in the case of multiple 
  7447.       inheritance). 
  7448.  
  7449.      Finally, the class methods defined by the derived metaclass invoke the 
  7450.       appropriate initialization methods of its parents to ensure that the 
  7451.       class variables of its instances are correctly initialized. 
  7452.  
  7453.  As further explanation for the automatic derivation of metaclasses, consider 
  7454.  the following multiple-inheritance example. Class "C" (derived from classes 
  7455.  "A" and "B") does not have an explicit metaclass declaration in its SOM IDL, 
  7456.  yet its parents "A" and "B" do. As a result, class "C" requires a derived 
  7457.  metaclass. (If you still have trouble following the reasoning behind derived 
  7458.  metaclasses, ask yourself the following question: What class should "C" be an 
  7459.  instance of? After a bit of reflection, you will conclude that, if SOM did not 
  7460.  build the derived metaclass, you would have to do so yourself.) 
  7461.  
  7462.  
  7463.   Multiple Inheritance requires Derived Metaclasses
  7464.  
  7465.  In summary, SOM allows and encourages the definition and explicit use of named 
  7466.  metaclasses. With named metaclasses, programmers can not only affect the 
  7467.  behavior of class instances by choosing the parents of classes, but they can 
  7468.  also affect the behavior of the classes themselves by choosing their 
  7469.  metaclasses.  Because the behavior of classes in SOM includes the 
  7470.  implementation of inheritance itself, metaclasses in SOM provide an extremely 
  7471.  flexible and powerful capability allowing classes to package solutions to 
  7472.  problems that are otherwise very difficult to address within an OOP context. 
  7473.  
  7474.  At the same time, SOM is unique in that it relieves programmers of the 
  7475.  responsibility for avoiding metaclass incompatibility when defining a new 
  7476.  class. At first glance, this might seem to be merely a useful (though very 
  7477.  important) convenience. But, in fact, it is absolutely essential, because SOM 
  7478.  is predicated on binary compatibility with respect to changes in class 
  7479.  implementations. 
  7480.  
  7481.  A programmer might, at one point in time, know the metaclasses of all ancestor 
  7482.  classes of a new subclass, and, as a result, be able to explicitly derive an 
  7483.  appropriate metaclass for the new class. Nevertheless, SOM must guarantee that 
  7484.  this new class will still execute and perform correctly when any of its 
  7485.  ancestor class's implementations are changed (which could even include 
  7486.  specifying different metaclasses). Derived metaclasses allow SOM to make this 
  7487.  guarantee.  A SOM programmer need never worry about the problem of metaclass 
  7488.  incompatibility; SOM does this for the programmer. Instead, explicit 
  7489.  metaclasses can simply be used to "add in" whatever behavior is desired for a 
  7490.  new class. SOM automatically handles anything else that is needed. Chapter 8 
  7491.  provides useful examples of such metaclasses. A SOM programmer should find 
  7492.  numerous applications for the techniques that are illustrated there. 
  7493.  
  7494.  
  7495. ΓòÉΓòÉΓòÉ 6.2. Inheritance ΓòÉΓòÉΓòÉ
  7496.  
  7497. One of the defining aspects of an object model is its characterization of 
  7498. inheritance. This section describes SOM's model for inheritance. 
  7499.  
  7500. A class in SOM defines an implementation for objects that support a specific 
  7501. interface: 
  7502.  
  7503.      The interface defines the methods supported by objects of the class, and 
  7504.       is specified using SOM IDL. 
  7505.  
  7506.      The implementation  defines what instance variables implement an object's 
  7507.       state and what procedures implement its methods. 
  7508.  
  7509.  New classes are derived (by subclassing) from previously existing classes 
  7510.  through inheritance, specialization, and addition.  Subclasses inherit 
  7511.  interface from their parent classes: any method available on instances of a 
  7512.  class is also available on instances of any class derived from it (either 
  7513.  directly or indirectly).  Subclasses also inherit implementation (the 
  7514.  procedures that implement the methods) from their parent classes unless the 
  7515.  methods are overridden (redefined or specialized). In addition, a subclass may 
  7516.  introduce new instance methods and instance variables that will be inherited 
  7517.  by other classes derived from it. 
  7518.  
  7519.  SOM also supports multiple inheritance. That is, a class may be derived from 
  7520.  (and may inherit interface and implementation from) multiple parent classes. 
  7521.  Note: Multiple inheritance is available only to SOM classes whose interfaces 
  7522.  are specified in IDL, and not to SOM classes whose interfaces are specified in 
  7523.  SOM's earlier interface definition language, OIDL. See Appendix B for 
  7524.  information on how to automatically convert existing OIDL files to IDL. 
  7525.  
  7526.  It is possible under multiple inheritance to encounter potential conflicts or 
  7527.  ambiguities with respect to inheritance. All multiple inheritance models must 
  7528.  face these issues, and resolve the ambiguities in some way. For example, when 
  7529.  multiple inheritance is allowed, it is possible that a class will inherit the 
  7530.  same method or instance variable from different parents (because each of these 
  7531.  parents has some common ancestor that introduces the method or instance 
  7532.  variable). In this situation, a SOM subclass inherits only one implementation 
  7533.  of the method or instance variable. (The implementation of an instance 
  7534.  variable within an object is just the location where it is stored. The 
  7535.  implementation of a method is a procedure pointer, stored within a method 
  7536.  table.) The following illustration addresses the question of which method 
  7537.  implementation would be inherited. 
  7538.  
  7539.  Consider this situation: Class "W" defines a method "foo", implemented by 
  7540.  procedure "proc1". Class "W" has two subclasses, "X" and "Y". Subclass "Y" 
  7541.  overrides the implementation of "foo" with procedure "proc2". Subclass "X" 
  7542.  does not override "foo". In addition, classes "X" and "Y" share a common 
  7543.  subclass, "Z". That is, the IDL interface statement for class "Z" lists its 
  7544.  parents as "X" and "Y" in that order. (These relationships form a diamond 
  7545.  shape, with class "W" at the top.) 
  7546.  
  7547.  The question is thus: which implementation of method "foo" does class "Z" 
  7548.  inherit-procedure "proc1" defined by class "W", or procedure "proc2" defined 
  7549.  by class "Y"? The procedure for performing inheritance that is defined by 
  7550.  SOMClass resolves this ambiguity by using the left path precedence rule: when 
  7551.  the same method is inherited from multiple ancestors, the procedure used to 
  7552.  support the method is the one used by the leftmost ancestor from which the 
  7553.  method is inherited. (The ordering of parent classes is determined by the 
  7554.  order in which the class implementor lists the parents in the IDL 
  7555.  specification for the class.) 
  7556.  
  7557.  Class "Z" inherits the implementation of method "foo" defined by class "W" 
  7558.  (procedure "proc1"), rather than the implementation defined by class "Y" 
  7559.  (procedure "proc2"), because "X" is the leftmost ancestor of "Z" from which 
  7560.  the method "foo" is inherited. This rule may be interpreted as giving priority 
  7561.  to classes whose instance interfaces are mentioned first in IDL interface 
  7562.  definitions. 
  7563.  
  7564.  If a class implementor decides that the default inherited implementation is 
  7565.  not appropriate (for example, procedure "proc2" is desired), then SOM IDL 
  7566.  allows the class designer to select the parent whose implementation is 
  7567.  desired. For more information concerning this approach, see the Select 
  7568.  modifier, which is documented in the topic "Modifier statements" in Chapter 4, 
  7569.  "SOM IDL and the SOM Compiler." 
  7570.  
  7571.  Note:  Alternatively, an explicit metaclass for "Z" could be introduced to 
  7572.         change the way methods are inherited. However, this would be a fairly 
  7573.         serious step to take-it would also affect the semantics of inheritance 
  7574.         for all of Z's descendant classes. 
  7575.  
  7576.  Another conflict that may arise with the use of multiple inheritance is when 
  7577.  two ancestors of a class define different methods (in general, with different 
  7578.  signatures) of the same name. For example, suppose Class "X" defines a method 
  7579.  "bar" with type T1, and class "Y" defines a method "bar" with type T2. Class 
  7580.  "Z" is derived from both "X" and "Y", and "Z" does not override method "bar". 
  7581.  
  7582.  This example illustrates a method name that is "overloaded"-that is, used to 
  7583.  name two entirely different methods (note that overloading is completely 
  7584.  unrelated to overriding). This is not necessarily a difficult problem to 
  7585.  handle. Indeed, the run-time SOM API allows the construction of a class that 
  7586.  supports the two different "bar" methods. (They are implemented using two 
  7587.  different method-table entries, each of which is associated with its 
  7588.  introducing class.) 
  7589.  
  7590.  However, the interface to instances of such classes can not be defined using 
  7591.  IDL. IDL specifically forbids the definition of interfaces in which method 
  7592.  names are overloaded.  Furthermore, within SOM itself, the use of such classes 
  7593.  can lead to anomalous behavior unless care is taken to avoid the use of 
  7594.  name-lookup method resolution (discussed in the following section), since, in 
  7595.  this case, a method name alone does not identify a unique method. For this 
  7596.  reason, (statically declared) multiple-inheritance classes in SOM are 
  7597.  currently restricted to those whose instance interfaces can be defined using 
  7598.  IDL. Thus, the above example cannot be constructed with the aid of the SOM 
  7599.  Compiler. 
  7600.  
  7601.  
  7602. ΓòÉΓòÉΓòÉ 6.3. Method Resolution ΓòÉΓòÉΓòÉ
  7603.  
  7604. Method resolution is the step of determining which procedure to execute in 
  7605. response to a method invocation. For example, consider this scenario: 
  7606.  
  7607.      Class "Dog" introduces a method "bark", and 
  7608.  
  7609.      A subclass of "Dog", called "BigDog", overrides "bark", and 
  7610.  
  7611.      A client program creates an instance of either "Dog" or "BigDog" 
  7612.       (depending on some run-time criteria) and invokes method "bark" on that 
  7613.       instance. 
  7614.  
  7615.  Method resolution is the process of determining, at run time, which method 
  7616.  procedure to execute in response to the method invocation (either the method 
  7617.  procedure for "bark" defined by "Dog", or the method procedure for "bark" 
  7618.  defined by "BigDog"). This determination depends on whether the receiver of 
  7619.  the method (the object on which it is invoked) is an instance of "Dog" or 
  7620.  "BigDog" (or perhaps depending on some other criteria). 
  7621.  
  7622.  SOM allows class implementors and client programs considerable flexibility in 
  7623.  deciding how SOM performs method resolution. In particular, SOM supports three 
  7624.  mechanisms for method resolution, described in order of increased flexibility 
  7625.  and increased computational cost: offset resolution, name-lookup resolution, 
  7626.  and dispatch-function resolution. 
  7627.  
  7628.  
  7629. ΓòÉΓòÉΓòÉ 6.3.1. Offset resolution ΓòÉΓòÉΓòÉ
  7630.  
  7631. When using SOM's C and C++ language bindings, offset resolution is the default 
  7632. way of resolving methods, because it is the fastest. For those familiar with 
  7633. C++, it is roughly equivalent to the C++ "virtual function" concept. 
  7634.  
  7635. Although offset resolution is the fastest technique for method resolution, it 
  7636. is also the most constrained. Specifically, using offset resolution requires 
  7637. these constraints: 
  7638.  
  7639.      The name of the method to be invoked must be known at compile time, 
  7640.  
  7641.      The name of the class that introduces the method must be known at compile 
  7642.       time (although not necessarily by the programmer), and 
  7643.  
  7644.      The method to be invoked must be part of the introducing class's static 
  7645.       (IDL) interface definition. 
  7646.  
  7647.  To perform offset method resolution, SOM first obtains a method token from a 
  7648.  global data structure associated with the class that introduced the method. 
  7649.  This data structure is called the ClassData structure. It includes a method 
  7650.  token for each method the class introduces. The method token is then used as 
  7651.  an "index" into the receiver's method table, to access the appropriate method 
  7652.  procedure. Because it is known at compile time which class introduces the 
  7653.  method and where in that class's ClassData structure the method's token is 
  7654.  stored, offset resolution is quite efficient. The cost of offset method 
  7655.  resolution is currently about twice the cost of calling a C function using a 
  7656.  pointer loaded with the function address. 
  7657.  
  7658.  An object's method table is a table of pointers to the procedures that 
  7659.  implement the methods that the object supports. This table is constructed by 
  7660.  the object's class and is shared among the class instances. The method table 
  7661.  built by class (for its instances) is referred to as the class's instance 
  7662.  method table. This is useful terminology, since, in SOM, a class is itself an 
  7663.  object with a method table (created by its metaclass) used to support method 
  7664.  calls on the class. 
  7665.  
  7666.  Usually, offset method resolution is sufficient; however, in some cases, the 
  7667.  more flexible name-lookup resolution is required. 
  7668.  
  7669.  
  7670. ΓòÉΓòÉΓòÉ 6.3.2. Name-lookup resolution ΓòÉΓòÉΓòÉ
  7671.  
  7672. Name-lookup resolution is similar to the method resolution techniques employed 
  7673. by Objective-C and Smalltalk. It is currently about five times slower than 
  7674. offset resolution. It is more flexible, however. In particular, name-lookup 
  7675. resolution, unlike offset resolution, can be used when: 
  7676.  
  7677.      The name of the method to be invoked isn't known until run time, or 
  7678.  
  7679.      The method is added to the class interface at run time, or 
  7680.  
  7681.      The name of the class introducing the method isn't known until run time. 
  7682.  
  7683.  For example, a client program may use two classes that define two different 
  7684.  methods of the same name, and it might not be known until run time which of 
  7685.  the two methods should be invoked (because, for example, it will not be known 
  7686.  until run time which class's instance the method will be applied to). 
  7687.  
  7688.  Name-lookup resolution is always performed by a class, so it requires a method 
  7689.  call. (Offset resolution, by contrast, requires no method calls.) To perform 
  7690.  name-lookup method resolution, the class of the intended receiver object 
  7691.  obtains a method procedure pointer for the desired method  that is appropriate 
  7692.  for its instances. In general, this will require a name-based search through 
  7693.  various data structures maintained by ancestor classes. 
  7694.  
  7695.  Offset and name-lookup resolution achieve the same net effect (that is, they 
  7696.  select the same method procedure); they just achieve it differently (via 
  7697.  different mechanisms for locating the method's method token). Offset 
  7698.  resolution is faster, because it does not require searching for the method 
  7699.  token, but name-lookup resolution is more flexible. 
  7700.  
  7701.  When defining (in SOM IDL) the interface to a class of objects, the class 
  7702.  implementor can decide, for each method, whether the SOM Compiler will 
  7703.  generate usage bindings that support name-lookup resolution for invoking the 
  7704.  method. Regardless of whether this is done, however, application programs 
  7705.  using the class can have SOM use either technique, on a per-method-call basis. 
  7706.  Chapter 3, "Using SOM Classes in Client Programs," describes how client 
  7707.  programs invoke methods. 
  7708.  
  7709.  
  7710. ΓòÉΓòÉΓòÉ 6.3.3. Dispatch-function resolution ΓòÉΓòÉΓòÉ
  7711.  
  7712. Dispatch-function resolution is the slowest, but most flexible, of the three 
  7713. method-resolution techniques. Dispatch functions permit method resolution to be 
  7714. based on arbitrary rules associated with the class of which the receiving 
  7715. object is an instance. Thus, a class implementor has complete freedom in 
  7716. determining how methods invoked on its instances are resolved. 
  7717.  
  7718. With both offset and name-lookup resolution, the net effect is the same-the 
  7719. method procedure that is ultimately selected is the one supported by the class 
  7720. of which the receiver is an instance. For example, if the receiver is an 
  7721. instance of class "Dog", then Dog's method procedure will be selected; but if 
  7722. the receiver is an instance of class "BigDog", then BigDog's method procedure 
  7723. will be selected. 
  7724.  
  7725. By contrast, dispatch-function resolution allows a class of instances to be 
  7726. defined such that the method procedure is selected using some other criteria. 
  7727. For example, the method procedure could be selected on the basis of the 
  7728. arguments to the method call, rather than on the receiver. For more information 
  7729. on dispatch-function resolution, see the description and examples for the 
  7730. somDispatch and somOverrideMTab methods in the SOM Programming Reference. 
  7731.  
  7732.  
  7733. ΓòÉΓòÉΓòÉ 6.3.4. Customizing Method Resolution ΓòÉΓòÉΓòÉ
  7734.  
  7735. Customizing method resolution requires the use of metaclasses that override 
  7736. SOMClass methods.  This is not recommended without use of the Cooperative 
  7737. Metaclass that guarantees correct operation of SOMobjects in conjunction with 
  7738. such metaclasses.  SOMobjects users who require this functionality should 
  7739. request access to the experimental Cooperative Metaclass used to implement the 
  7740. SOMobjects Metaclass Framework. Metaclasses implemented using the Cooperative 
  7741. Metaclass may have to be reprogrammed in the future when SOMobjects introduces 
  7742. an oficially supported Cooperative Metaclass. 
  7743.  
  7744.  
  7745. ΓòÉΓòÉΓòÉ 6.3.5. The four kinds of SOM methods ΓòÉΓòÉΓòÉ
  7746.  
  7747. SOM supports four different kinds of methods:  static methods, nonstatic 
  7748. methods, dynamic methods, and direct-call procedures. The following paragraphs 
  7749. explain these four method categories and the kinds of method resolution 
  7750. available for each. 
  7751.  
  7752.  
  7753. ΓòÉΓòÉΓòÉ 6.3.5.1. Static methods ΓòÉΓòÉΓòÉ
  7754.  
  7755. These are similar in concept to C++ virtual functions. Static methods are 
  7756. normally invoked using offset resolution via a method table, as described 
  7757. above, but all three kinds of method resolution are applicable to static 
  7758. methods. Each different static method available on an object is given a 
  7759. different slot in the object's method table. When SOMobjects Toolkit language 
  7760. bindings are used to implement a class, the SOM IDL method modifier can be 
  7761. specified to indicate that a given method is static; however, this modifier is 
  7762. rarely used since it is the default for SOM methods. 
  7763.  
  7764. Static methods introduced by a class can be overridden (redefined) by any 
  7765. descendant classes of the class. When SOMobjects language bindings are used to 
  7766. implement a class, the SOM IDL override modifier is specified to indicate that 
  7767. a class overrides a given inherited method. When a static method is resolved 
  7768. using offset resolution, it is not important which interface is accessing the 
  7769. method - the actual class of the object determines the method procedure that is 
  7770. selected. 
  7771.  
  7772. Note:  All SOM IDL modifiers are described in the topic "Modifier statements" 
  7773. in Chapter 4, "SOM IDL and the SOM Compiler." 
  7774.  
  7775.  
  7776. ΓòÉΓòÉΓòÉ 6.3.5.2. Nonstatic methods ΓòÉΓòÉΓòÉ
  7777.  
  7778. These methods are similar in concept to C++ nonstatic member functions (that 
  7779. is, C++ functions that are not virtual member functions and are not static 
  7780. member functions). Nonstatic methods are normally invoked using offset 
  7781. resolution, but all three kinds of method resolution are applicable  to 
  7782. nonstatic methods. When the SOMobjects language bindings are used to implement 
  7783. a class, the SOM IDL nonstatic modifier is used to indicate that a given method 
  7784. is nonstatic. 
  7785.  
  7786. Like static methods, nonstatic methods are given individual positions in method 
  7787. tables. However, nonstatic methods cannot be overridden. Instead, descendants 
  7788. of a class that introduces a nonstatic method can use the SOM IDL reintroduce 
  7789. modifier to "hide" the original nonstatic method with another (nonstatic or 
  7790. static) method of the same name. When a nonstatic method is resolved, selection 
  7791. of the specific method procedure is determined by the interface that is used to 
  7792. access the method. 
  7793.  
  7794.  
  7795. ΓòÉΓòÉΓòÉ 6.3.5.3. Dynamic methods ΓòÉΓòÉΓòÉ
  7796.  
  7797. These methods are not declared when specifying an object interface using IDL. 
  7798. Instead, they are registered with a class object at run time using the method 
  7799. somAddDynamicMethod. Because there is no way for SOM to know about dynamic 
  7800. methods before run time, offset resolution is not available for dynamic 
  7801. methods. Only name-lookup or dispatch-function resolution  can be used to 
  7802. invoke dynamic methods. Dynamic methods cannot be overridden. 
  7803.  
  7804.  
  7805. ΓòÉΓòÉΓòÉ 6.3.5.4. Direct-call procedures ΓòÉΓòÉΓòÉ
  7806.  
  7807. These are similar in concept to C++ static member functions. Direct-call 
  7808. procedures are not given positions in SOM method tables, but are accessed 
  7809. directly from a class's ClassData structure. Strictly speaking, none of the 
  7810. previous method-resolution approaches apply for invoking a direct-call 
  7811. procedure, although SOMobjects language bindings provide the same invocation 
  7812. syntax for direct-call procedures as for static or nonstatic methods. 
  7813. Direct-call procedures cannot be overridden, but they can be reintroduced. When 
  7814. SOMobjects language bindings are used to implement a class, the SOM IDL 
  7815. procedure modifier is used to indicate that a given method is a direct-call 
  7816. procedure. Note: Methods having the procedure modifier cannot be invoked 
  7817. remotely using DSOM. 
  7818.  
  7819.  
  7820. ΓòÉΓòÉΓòÉ 6.4. Implementing SOM Classes ΓòÉΓòÉΓòÉ
  7821.  
  7822. The interface to a class of objects contains the information that a client must 
  7823. know to use an object - namely, the signatures of its methods and the names of 
  7824. its attributes. The interface is described in a formal language independent of 
  7825. the programming language used to implement the object's methods. In SOM, the 
  7826. formal language used to define object interfaces is the Interface Definition 
  7827. Language (described in Chapter 4, "SOM IDL and the SOM Compiler"). 
  7828.  
  7829. The implementation of a class of objects  (that is, the procedures that 
  7830. implement the methods and the instance variables that store an object's state) 
  7831. is written in the implementor's preferred programming language. This language 
  7832. can be object-oriented (for instance, C++) or procedural (for instance, C). 
  7833.  
  7834. A completely implemented class definition, then, consists of two main files: 
  7835.  
  7836.      An IDL specification of the interface to instances of the class - the 
  7837.       interface definition file (or .idl file) and 
  7838.  
  7839.      Method procedures written in the implementor's language of choice - the 
  7840.       implementation file. 
  7841.  
  7842.  The SOM Compiler provides the link between those two files: To assist users in 
  7843.  implementing classes, the SOM Compiler produces a template implementation file 
  7844.  - a type-correct guide for how the implementation of a class should look. 
  7845.  Then, the class implementor modifies this template file to fully implement the 
  7846.  class's methods.  That process is the subject of the remainder of this 
  7847.  chapter. 
  7848.  
  7849.  The SOM Compiler can also update the implementation file to reflect changes 
  7850.  subsequently made to a class's interface definition file (the .idl file). 
  7851.  These incremental updates include adding new stub procedures, adding comments, 
  7852.  and changing method prototypes to reflect changes made to the method 
  7853.  definitions in the IDL specification. These updates to the implementation 
  7854.  file, however, do not disturb existing code in the method procedures. These 
  7855.  updates are discussed further in "Running incremental updates of the 
  7856.  implementation template file" later in this section. 
  7857.  
  7858.  For C programmers, the SOM Compiler generates a <filestem>.c file. For C++ 
  7859.  programmers, the SOM Compiler generates a <filestem>.cpp file. To specify 
  7860.  whether the SOM Compiler should generate a C or C++ implementation template, 
  7861.  set the value of the SMEMIT environment variable, or use the -s option when 
  7862.  running the SOM Compiler. (See "The SOM Compiler" in Chapter 4, "SOM IDL and 
  7863.  the SOM Compiler.") 
  7864.  
  7865.  Note:  As this chapter describes, a SOM class can be implemented by using C++ 
  7866.         to define the instance variables introduced by the class and to define 
  7867.         the procedures that implement the overridden and introduced methods of 
  7868.         the class. Be aware, however, that the C++ class defined by the C++ 
  7869.         usage bindings for a SOM class (described in Chapter 3) cannot be 
  7870.         subclassed in C++ to create new C++ or SOM classes. [The reason why the 
  7871.         C++ implementation of a SOM class involves the definition of C++ 
  7872.         procedures (not C++ methods) to support SOM methods is that there is no 
  7873.         language-neutral way to call a C++ method. Only C++  code can call C++ 
  7874.         methods, and this calling code must be generated by the same compiler 
  7875.         that generates the method code. In contrast, the method procedures that 
  7876.         implement SOM methods must be callable from any language, without 
  7877.         knowledge on the part of the object client as to which language is used 
  7878.         to implement the resolved method procedure] 
  7879.  
  7880.  
  7881. ΓòÉΓòÉΓòÉ 6.4.1. The implementation template ΓòÉΓòÉΓòÉ
  7882.  
  7883. Consider the following IDL description of the "Hello" class: 
  7884.  
  7885.    #include <somobj.idl>
  7886.  
  7887.    interface Hello : SOMObject
  7888.    {
  7889.        void sayHello();
  7890.        // This method outputs the string "Hello, World!".
  7891.    };
  7892.  
  7893. From this IDL description, the SOM Compiler generates the following C 
  7894. implementation template, hello.c (a C++ implementation template, or hello.cpp, 
  7895. is identical except that the #included file is <hello.xih> rather than 
  7896. <hello.ih>): 
  7897.  
  7898.    #define Hello_Class_Source
  7899.    #include <hello.ih>
  7900.  
  7901.    /*
  7902.     *  This method outputs the string "Hello, World!".
  7903.     */
  7904.  
  7905.    SOM_Scope void   SOMLINK sayHello(Hello somSelf, Environment *ev)
  7906.    {
  7907.        /* HelloData *somThis = HelloGetData(somSelf); */
  7908.        HelloMethodDebug("Hello","sayHello");
  7909.    }
  7910.  
  7911. The first line defines the "Hello_Class_Source" symbol, which is used in the 
  7912. SOM-generated implementation header files for C to determine when to define 
  7913. various functions, such as "HelloNewClass."  For interfaces defined within a 
  7914. module, the directive "#define <className>_Class_Source" is replaced by the 
  7915. directive "#define SOM_Module_<moduleName>_Source". 
  7916.  
  7917. The second line (#include <hello.ih> for C, or #include <hello.xih> for C++) 
  7918. includes the SOM-generated implementation header file. This file defines a 
  7919. struct holding the class's instance variables, macros for accessing instance 
  7920. variables, macros for invoking parent methods, and so forth. 
  7921.  
  7922.  
  7923. ΓòÉΓòÉΓòÉ 6.4.1.1. Stub procedures for methods ΓòÉΓòÉΓòÉ
  7924.  
  7925. For each method introduced or overridden by the class, the implementation 
  7926. template includes a stub procedure-a procedure that is empty except for an 
  7927. initialization statement, a debugging statement, and possibly a return 
  7928. statement. The stub procedure for a method is preceded by any comments that 
  7929. follow the method's declaration in the IDL specification. 
  7930.  
  7931. For method "sayHello" above, the SOM Compiler generates the following prototype 
  7932. of the stub procedure: 
  7933.  
  7934.    SOM_Scope void SOMLINK sayHello(Hello somSelf, Environment *ev)
  7935.  
  7936. The "SOM_Scope" symbol is defined in the implementation header file as either 
  7937. "extern" or "static," as appropriate. The term "void" signifies the return type 
  7938. of method "sayHello". The "SOMLINK" symbol is defined by SOM; it represents the 
  7939. keyword needed to link to the C or C++ compiler, and its value is 
  7940. system-specific. Using the "SOMLINK" symbol allows the code to work with a 
  7941. variety of compilers without modification. 
  7942.  
  7943. Following the "SOMLINK" symbol is the name of the procedure that implements the 
  7944. method. If no functionprefix modifier has been specified for the class, then 
  7945. the procedure name is the same as the method name. If a functionprefix modifier 
  7946. is in effect, then the procedure name is generated by prepending the specified 
  7947. prefix to the method name. For example, if the class definition contained the 
  7948. following statement: 
  7949.  
  7950.    functionprefix = xx_;
  7951.  
  7952. then the prototype of the stub procedure for method "sayHello" would be: 
  7953.  
  7954.    SOM_Scope void SOMLINK xx_sayHello(Hello somSelf, Environment *ev)
  7955.  
  7956. The functionprefix can not be 
  7957.  
  7958.    <classname>_
  7959.  
  7960. since this is used in method invocation macros defined by the C usage bindings. 
  7961.  
  7962. Following the procedure name is the formal parameter list for the method 
  7963. procedure. Because each SOM method always receives at least one argument (a 
  7964. pointer to the SOM object that responds to the method), the first parameter 
  7965. name in the prototype of each stub procedure is called somSelf. (The macros 
  7966. defined in the implementation header file rely on this convention.) The somSelf 
  7967. parameter is a pointer to an object that is an instance of the class being 
  7968. implemented (here, class "Hello") or an instance of a class derived from it. 
  7969.  
  7970. Unless the IDL specification of the class included the callstyle=oidl modifier, 
  7971. then the formal parameter list will include one or two additional parameters 
  7972. before the parameters declared in the IDL specification: an (Environment *ev) 
  7973. input/output parameter, which permits the return of exception information, and, 
  7974. if the IDL specification of the method includes a context specification, a 
  7975. (Context *ctx) input parameter. These parameters are prescribed by the CORBA 
  7976. standard.  For more information on using the Environment  and Context 
  7977. parameters, see the section entitled "Exceptions and error handling" in Chapter 
  7978. 3, "Using SOM Classes in Client Programs," and the book The Common Object 
  7979. Request Broker: Architecture and Specification, published by Object Management 
  7980. Group and X/Open. 
  7981.  
  7982. The first statement in the stub procedure for method "sayHello" is the 
  7983. statement: 
  7984.  
  7985.    /* HelloData *somThis = HelloGetData(somSelf); */
  7986.  
  7987. This statement is enclosed in comments only when the class does not introduce 
  7988. any instance variables. The purpose of this statement, for classes that do 
  7989. introduce instance variables, is to initialize a local variable (somThis) that 
  7990. points to a structure representing the instance variables introduced by the 
  7991. class. The somThis pointer is used by the macros defined in the "Hello" 
  7992. implementation header file to access those instance variables. (These macros 
  7993. are described below.)  In this example, the "Hello" class introduces no 
  7994. instance variables, so the statement is commented out. If instance variables 
  7995. are later added to a class that initially had none, then the comment characters 
  7996. can be removed if access to the variable is required. 
  7997.  
  7998. The "HelloData" type and the "HelloGetData" macro used to initialize the 
  7999. somThis pointer are defined in the implementation header file. Within a method 
  8000. procedure, class implementers can use the somThis pointer to access instance 
  8001. data, or they can use the convenience macros defined for accessing each 
  8002. instance variable, as described below. 
  8003.  
  8004. To implement a method so that it can modify a local copy of an object's 
  8005. instance data without affecting the object's real instance data, declare a 
  8006. variable of type <className>Data (for example, "HelloData") and assign to it 
  8007. the structure that somThis points to; then make the somThis pointer point to 
  8008. the copy. For example: 
  8009.  
  8010.    HelloData myCopy = *somThis;
  8011.    somThis = &myCopy;
  8012.  
  8013. Next in the stub procedure for method "sayHello" is the statement: 
  8014.  
  8015.    HelloMethodDebug("Hello", "sayHello");
  8016.  
  8017. This statement facilitates debugging. The "HelloMethodDebug" macro is defined 
  8018. in the implementation header file. It takes two arguments, a class name and a 
  8019. method name. If debugging is turned on (that is, if global variable 
  8020. SOM_TraceLevel is set to one in the calling program), the macro produces a 
  8021. message each time the method procedure is entered. (See the next Chapter 3, 
  8022. "Using SOM Classes in Client Programs," for information on debugging with SOM.) 
  8023.  
  8024. Debugging can be permanently disabled (regardless of the setting of the 
  8025. SOM_TraceLevel setting in the calling program) by redefining the 
  8026. <className>MethodDebug macro to be SOM_NoTrace(c,m) following the #include 
  8027. directive for the implementation header file. (This can yield a slight 
  8028. performance improvement.) For example, to permanently disable debugging for the 
  8029. "Hello" class, insert the following lines in the hello.c implementation file 
  8030. following the line "#include hello.ih" (or "#include hello.xih," for classes 
  8031. implemented in C++): 
  8032.  
  8033.    #undef HelloMethodDebug
  8034.    #define HelloMethodDebug(c,m) SOM_NoTrace(c,m)
  8035.  
  8036. The way in which the stub procedure ends is determined by whether the method is 
  8037. a new or an overriding method. 
  8038.  
  8039.      For non-overriding (new) methods, the stub procedure ends with a return 
  8040.       statement (unless the return type of the method is void). The class 
  8041.       implementer should customize this return statement. 
  8042.  
  8043.      For overriding methods, the stub procedure ends by making a "parent 
  8044.       method call" for each of the class's parent classes. If the method has a 
  8045.       return type that is not void, the last of these parent method calls is 
  8046.       returned as the result of the method procedure. The class implementer can 
  8047.       customize this return statement if needed (for example, if some other 
  8048.       value is to be returned, or if the parent method calls should be made 
  8049.       before the method procedure's own processing). See the next section for a 
  8050.       discussion of parent method calls. 
  8051.  
  8052.  If a classinit modifier was specified to designate a user-defined procedure 
  8053.  that will initialize the "Hello" class object, as in the statement: 
  8054.  
  8055.      classinit = HInit;
  8056.  
  8057.  then the implementation template file would include the following stub 
  8058.  procedure for "HInit", in addition to the stub procedures for Hello's methods: 
  8059.  
  8060.      void  SOMLINK HInit(SOMClass *cls)
  8061.      {
  8062.  
  8063.      }
  8064.  
  8065.  This stub procedure is then filled in by the class implementer. If the class 
  8066.  definition specifies a functionprefix modifier, the classinit procedure name 
  8067.  is generated by prepending the specified prefix to the specified classinit 
  8068.  name, as with other stub procedures. 
  8069.  
  8070.  
  8071. ΓòÉΓòÉΓòÉ 6.4.2. Extending the implementation template ΓòÉΓòÉΓòÉ
  8072.  
  8073. To implement a method, add code to the body of the stub procedure.  In addition 
  8074. to standard C or C++ code, class implementers can also use any of the 
  8075. functions, methods, and macros SOM provides for manipulating classes and 
  8076. objects. Chapter 3, "Using SOM Classes in Client Programs," discusses these 
  8077. functions, methods, and macros. 
  8078.  
  8079. In addition to the functions, methods, and macros SOM provides for both class 
  8080. clients and class implementers, SOM provides two facilities especially for 
  8081. class implementers. They are for (1) accessing instance variables of the object 
  8082. responding to the method and (2) making parent method calls, as follows. 
  8083.  
  8084.  
  8085. ΓòÉΓòÉΓòÉ 6.4.2.1. Accessing internal instance variables ΓòÉΓòÉΓòÉ
  8086.  
  8087. To access internal instance variables, class implementers can use either of the 
  8088. following forms: 
  8089.  
  8090.       _variableName 
  8091.  
  8092.       somThis->variableName 
  8093.  
  8094.  To access internal instance variables "a", "b", and "c", for example, the 
  8095.  class implementer could use either _a, _b, and _c, or somThis->a, somThis->b, 
  8096.  and somThis->c. These expressions can appear on either side of an assignment 
  8097.  statement. The somThis  pointer must be properly initialized in advance using 
  8098.  the <className>GetData  procedure, as shown above. 
  8099.  
  8100.  Instance variables can be accessed only within the implementation file of the 
  8101.  class that introduces the instance variable, and not within the implementation 
  8102.  of subclasses or within client programs. (To allow access to instance data 
  8103.  from a subclass or from client programs, use an attribute rather than an 
  8104.  instance variable to represent the instance data.) For C++ programmers, the 
  8105.  _variableName form is available only if the macro  VARIABLE_MACROS is defined 
  8106.  (that is, #define VARIABLE_MACROS) in the implementation file prior to 
  8107.  including the .xih file for the class. 
  8108.  
  8109.  
  8110. ΓòÉΓòÉΓòÉ 6.4.2.2. Making parent method calls ΓòÉΓòÉΓòÉ
  8111.  
  8112. In addition to macros for accessing instance variables, the implementation 
  8113. header file that the SOM Compiler generates also contains definitions of macros 
  8114. for making "parent method calls." When a class overrides a method defined by 
  8115. one or more of its parent classes, often the new implementation simply needs to 
  8116. augment the functionality of the existing implementation(s). Rather than 
  8117. completely re-implementing the method, the overriding method procedure can 
  8118. conveniently invoke the procedure that one or more of the parent classes uses 
  8119. to implement that method, then perform additional computation (redefinition) as 
  8120. needed. The parent method call can occur anywhere within the overriding method. 
  8121. (See Example 3 of the SOM IDL tutorial.) 
  8122.  
  8123. The SOM-generated implementation header file defines the following macros for 
  8124. making parent-method calls from within an overriding method: 
  8125.  
  8126. <className>_parent_<parentClassName>_<methodName> 
  8127.  
  8128.              (for each parent class of the class overriding
  8129. the method), and 
  8130.  
  8131. <className>_parents_<methodName>. 
  8132.  
  8133. For example, given class "Hello" with parents "File" and "Printer" and 
  8134. overriding method somInit (the SOM method that initializes each object), the 
  8135. SOM Compiler defines the following macros in the implementation header file for 
  8136. "Hello": 
  8137.  
  8138.    Hello_parent_Printer_somInit
  8139.    Hello_parent_File_somInit
  8140.    Hello_parents_somInit
  8141.  
  8142. Each macro takes the same number and type of arguments as <methodName>. The 
  8143. <className>_parent_<parentClassName>_<methodName> macro invokes the 
  8144. implementation of <methodName> inherited from <parentClassName>. Hence, using 
  8145. the macro "Hello_parent_File_somInit" invokes the File's implementation of 
  8146. somInit. 
  8147.  
  8148. The <className>_parents_<  methodName> macro invokes the parent method for each 
  8149. parent of the child class that supports <methodName>. That is, 
  8150. "Hello_parents_somInit" would invoke File's implementation of somInit, followed 
  8151. by Printer's implementation of somInit. The <className>_parents_<methodName> 
  8152. macro is redefined in the binding file each time the class interface is 
  8153. modified, so that if a parent class is added or removed from the class 
  8154. definition, or if <methodName> is added to one of the existing parents, the 
  8155. macro <className>_parents_<methodName > will be redefined appropriately. 
  8156.  
  8157.  
  8158. ΓòÉΓòÉΓòÉ 6.4.2.3. Converting C++ classes to SOM classes ΓòÉΓòÉΓòÉ
  8159.  
  8160. For C++ programmers implementing SOM classes, SOM provides a macro that 
  8161. simplifies the process of converting C++ classes to SOM classes. This macro 
  8162. allows the implementation of one method of a class to invoke another new or 
  8163. overriding method of the same class on the same receiving object by using the 
  8164. following shorthand syntax: 
  8165.  
  8166.    _methodName(arg1, arg2, ...)
  8167.  
  8168. For example, if class X introduces or overrides methods m1 and m2, then the C++ 
  8169. implementation of method m1 can invoke method m2 on its somSelf argument using 
  8170. _m2(arg, arg2, ...), rather than somSelf->m2(arg1, arg2, ...), as would 
  8171. otherwise be required. (The longer form is also available.) Before the 
  8172. shorthand form in the implementation file is used, the macro METHOD_MACROS must 
  8173. be defined (that is, use #define METHOD_MACROS) prior to including the xih file 
  8174. for the class. 
  8175.  
  8176.  
  8177. ΓòÉΓòÉΓòÉ 6.4.2.4. Running incremental updates of the implementation template file ΓòÉΓòÉΓòÉ
  8178.  
  8179. Refining the .idl file for a class is typically an iterative process. For 
  8180. example, after running the IDL source file through the SOM Compiler and writing 
  8181. some code in the implementation template file, the class implementer realizes 
  8182. that the IDL class interface needs another method or attribute, a method needs 
  8183. a different parameter, or any such changes. 
  8184.  
  8185. As mentioned earlier, the SOM Compiler (when run using the c or xc emitter) 
  8186. assists in this development by reprocessing the .idl file and making 
  8187. incremental updates to the current implementation file. This modify-and-update 
  8188. process may in fact be repeated several times before the class declaration 
  8189. becomes final. Importantly, these updates do not disturb existing code for the 
  8190. method procedures. Included in the incremental update are these changes: 
  8191.  
  8192.      Stub procedures are inserted into the implementation file for any new 
  8193.       methods added to the .idl file. 
  8194.  
  8195.      New comments in the .idl file are transferred to the implementation file, 
  8196.       reformatted appropriately. 
  8197.  
  8198.      If the interface to a method has changed, a new method procedure 
  8199.       prototype is placed in the implementation file. As a precaution, however, 
  8200.       the old prototype is also preserved within comments. The body of the 
  8201.       method procedure is left untouched (as are the method procedures for all 
  8202.       methods). 
  8203.  
  8204.      Similarly left intact are preprocessor directives, data declarations, 
  8205.       constant declarations, non-method functions, and additional comments-in 
  8206.       essence, everything else in the implementation file. 
  8207.  
  8208.  Some changes to the .idl file are not reflected automatically in the 
  8209.  implementation file after an incremental update. The class implementer must 
  8210.  manually edit the implementation file after changes such as these in the .idl 
  8211.  file: 
  8212.  
  8213.      Changing the name of a class or a method. 
  8214.  
  8215.      Changing the parents of a class (see also "If you change the parents of a 
  8216.       class..." later in this topic). 
  8217.  
  8218.      Changing a functionprefix class modifier statement. 
  8219.  
  8220.      Changing the content of a passthru statement directed to the 
  8221.       implementation (.c, or cpp) file. As previously emphasized, however, 
  8222.       passthru statements are primarily recommended only for placing #include 
  8223.       statements in a binding file (.ih, xih, .h, or .xh file) used as a header 
  8224.       file in the implementation file or in a client program. 
  8225.  
  8226.      If the class implementer has placed "forward declarations" of the method 
  8227.       procedures in the implementation file, those are not updated. Updates 
  8228.       occur only for method prototypes that are part of the method procedures 
  8229.       themselves. 
  8230.  
  8231.  
  8232. ΓòÉΓòÉΓòÉ 6.4.2.5. Considerations to ensure that updates work ΓòÉΓòÉΓòÉ
  8233.  
  8234. To ensure that the SOM Compiler can properly update method procedure prototypes 
  8235. in the implementation file, class implementers should avoid editing changes 
  8236. such as the following: 
  8237.  
  8238.      A method procedure name should not be enclosed in parentheses in the 
  8239.       prototype. 
  8240.  
  8241.      A method procedure name must appear in the first line of the prototype, 
  8242.       excluding comments and white space. Thus, a new line must not be inserted 
  8243.       before the procedure name. 
  8244.  
  8245.  Error messages occur while updating an existing implementation file if it 
  8246.  contains syntax that is not ANSI C. For example, "old style" method 
  8247.  definitions such as the example on the left generate errors: 
  8248.  
  8249.  Invalid "old" syntax     Required  ANSI C 
  8250.  void foo(x)              void foo(short x) { 
  8251.  short x;                 ... 
  8252.  {                        } 
  8253.  ... 
  8254.  } 
  8255.  
  8256.  Similarly, error messages occur if anything in the .idl file would produce an 
  8257.  implementation file that is not syntactically valid for C/C++ (such as nested 
  8258.  comments). If update errors occur, either the .idl file or the implementation 
  8259.  file may be at fault. One way to track down the problem is to run the 
  8260.  implementation file through the C/C++ compiler. Or, move the existing 
  8261.  implementation file to another directory, generate a completely new one from 
  8262.  the .idl file, and then run it through the C/C++ compiler. One of these steps 
  8263.  should pinpoint the error, if the compiler is strict ANSI. 
  8264.  
  8265.  Conditional compilation (using #if and #ifdef directives) in the 
  8266.  implementation file can be another source of errors, because the SOM Compiler 
  8267.  does not invoke the preprocessor (it simply recognizes and ignores those 
  8268.  directives). The programmer should be careful when using conditional 
  8269.  compilation, to avoid a situation such as shown below; here, with apparently 
  8270.  two open braces and only one closing brace, the c or xc emitter would report 
  8271.  an unexpected end-of-file: 
  8272.  
  8273.  Invalid syntax           Required matching braces 
  8274.  
  8275.  #ifdef FOOBAR            #ifdef FOOBAR 
  8276.   {                        { 
  8277.  ...                      ... 
  8278.  #else                     } 
  8279.  {                        #else 
  8280.  ...                       { 
  8281.  #endif                   ... 
  8282.   }                        } 
  8283.                           #endif 
  8284.  
  8285.  
  8286. ΓòÉΓòÉΓòÉ 6.4.2.6. If you change the parents of a class... ΓòÉΓòÉΓòÉ
  8287.  
  8288. Because the implementation-file emitters never change any existing code within 
  8289. a previously generated implementation file, changing the parents of a class 
  8290. requires extremely careful attention by the programmer. For example, for 
  8291. overridden methods, changing a class's parents may invalidate previous 
  8292. parent-method calls provided by the template, and require the addition of new 
  8293. parent-method calls. Neither of these issues is addressed by the incremental 
  8294. update of previously generated method-procedure templates. 
  8295.  
  8296. The greatest danger from changing the parents of a class, however, concerns the 
  8297. ancestor-initializer calls provided in the stub procedures for initializer 
  8298. methods. (For further information on ancestor initializer calls, see 
  8299. "Initializing and Uninitializing Objects" later in this chapter.) Unlike 
  8300. parent-method calls, ancestor-initializer calls are not optional - they must be 
  8301. made t all classes specified in a directinitclasses modifier, and these calls 
  8302. should always include the parents of the class (the default when no 
  8303. directinitclasses modifier is given). When the parents of a class are changed, 
  8304. however, the ancestor-initializer calls (which must be made in a specific 
  8305. order) are not updated. 
  8306.  
  8307. The easiest way to deal with this problem is to change the method name of the 
  8308. previously generated initializer stub procedure in the implementation template 
  8309. file. Then, the SOM Compiler can correctly generate a completely new 
  8310. initializer stub procedure (while ignoring the renamed procedure). Once this is 
  8311. done, your customization code from the renamed initializer procedure can be 
  8312. "merged" into the newly generated one, after which the renamed initializer 
  8313. procedure can be deleted. 
  8314.  
  8315.  
  8316. ΓòÉΓòÉΓòÉ 6.4.3. Compiling and linking ΓòÉΓòÉΓòÉ
  8317.  
  8318. After you fill in the method stub procedures, the implementation template file 
  8319. can be compiled and linked with a client program as follows. (In these 
  8320. examples, the environment variable SOMBASE represents the directory in which 
  8321. SOM has been installed.) 
  8322.  
  8323. Note: If you are building an application that uses a combination of C and C++ 
  8324. compiled object modules, then the C++ linker must be used to link them. 
  8325.  
  8326. When the client program (main.c) and the implementation file (hello.c) are in 
  8327. C: 
  8328.  
  8329.    > set LIB=%SOMBASE%\lib;%LIB%
  8330.    > icc -I. -I%SOMBASE%\include -Fe .*hello
  8331.    hello.exe main.c hello.c somtk.lib
  8332.  
  8333. When the client program and the implementation file are written in C++: 
  8334.  
  8335.    > set LIB=%SOMBASE%\lib;%LIB%
  8336.    > icc -I. -I%SOMBASE%\include -Fe .*hello
  8337.    hello.exe main.cpp hello.cpp somtk.lib
  8338.  
  8339. If the class definition (in the .idl file) changes, run the SOM Compiler again. 
  8340. This will generate new header files, and it will update the implementation file 
  8341. to include any: 
  8342.  
  8343.      New comments, 
  8344.  
  8345.      Stub procedures for any new methods, and 
  8346.  
  8347.      Revised method procedure prototypes for methods whose signatures have 
  8348.       been changed in the .idl file. 
  8349.  
  8350.  After rerunning the SOM Compiler, add to the implementation file the code for 
  8351.  any newly added method procedures, and recompile the implementation file with 
  8352.  the client program. 
  8353.  
  8354.  
  8355. ΓòÉΓòÉΓòÉ 6.5. Initializing and Uninitializing Objects ΓòÉΓòÉΓòÉ
  8356.  
  8357. This section discusses the initialization and uninitialization of SOM objects. 
  8358. Subsequent topics introduce the methods and capabilities that the SOMobjects 
  8359. Developer Toolkit provides to facilitate this. 
  8360.  
  8361. Object creation is the act that enables the execution of methods on an object. 
  8362. In SOM, this means storing a pointer to a method table into a word of memory. 
  8363. This single act converts raw memory into an (uninitialized) SOM object that 
  8364. starts at the location of the method table pointer. 
  8365.  
  8366. Object initialization, on the other hand, is a separate activity from object 
  8367. creation in SOM. Initialization is a capability supported by certain methods 
  8368. available on an object. An object's class determines the implementation of the 
  8369. methods available on the object, and thus determines its initialization 
  8370. behavior. 
  8371.  
  8372. The instance variables encapsulated by a newly created object must be brought 
  8373. into a consistent state before the object can be used. This is the purpose of 
  8374. initialization methods. Because, in general, every ancestor of an object's 
  8375. class contributes instance data to an object, it is appropriate that each of 
  8376. these ancestors contribute to the initialization of the object. 
  8377.  
  8378. SOM thus recognizes initializers as a special kind of method. One advantage of 
  8379. this approach is that special metaclasses are not required for defining 
  8380. constructors (class methods) that take arguments. Furthermore, a class can 
  8381. define multiple initializer methods, thus enabling its different objects to be 
  8382. initialized supporting different characteristics or capabilities. This results 
  8383. in simpler designs and more efficient programs. 
  8384.  
  8385. The SOMobjects Toolkit provides an overall framework that class designers can 
  8386. easily exploit in order to implement default or customized initialization of 
  8387. SOM objects. This framework is fully supported by the SOM Toolkit emitters that 
  8388. produce the implementation template file. The following sections describe the 
  8389. declaration, implementation, and use of initializer (and uninitializer) 
  8390. methods. 
  8391.  
  8392. Important: All code written prior to SOMobjects Release 2.1 using documented 
  8393. guidelines for the earlier initialization approach based on the somInit method 
  8394. (as well as all existing class binaries) continues to be fully supported and 
  8395. useful. 
  8396.  
  8397.  
  8398. ΓòÉΓòÉΓòÉ 6.5.1. Initializer methods ΓòÉΓòÉΓòÉ
  8399.  
  8400. As noted above, in the SOMobjects Toolkit each ancestor of an object 
  8401. contributes to the initialization of that object. Initialization of an object 
  8402. involves a chain of ancestor-method calls that, by default, are automatically 
  8403. determined by the SOM Compiler emitters. The SOMobjects framework for 
  8404. initialization of objects is based on the following approach: 
  8405.  
  8406.    1. SOMobjects recognizes initializers as a special kind of method, and 
  8407.       supports a special mechanism for ordering the execution of 
  8408.       ancestor-initializer method procedures. The SOMObject class introduces an 
  8409.       initializer method, somDefaultInit that uses this execution mechanism. 
  8410.  
  8411.    2. The SOM Compiler's emitters provide special support for methods that are 
  8412.       declared as initializers in the .idl file. To supplement the 
  8413.       somDefaultInit method, SOM class designers can also declare additional 
  8414.       initializers in their own classes. 
  8415.  
  8416.  Two SOM IDL modifiers are provided for declaring initializer methods and 
  8417.  controlling their execution, init and directinitclasses: 
  8418.  
  8419.      The init modifier is required in order to designate a given method is a 
  8420.       initializer; that is, to indicate that the method both uses and supports 
  8421.       the object-initialization protocol described here. 
  8422.  
  8423.      The  directinitclasses modifier can be used to control the order of 
  8424.       execution of initializer method procedures provided by the different 
  8425.       ancestors of the class of an object. 
  8426.  
  8427.      For full definitions of init and directinitclasses, see the topic 
  8428.       "Modifier statements" in Chapter 4,"SOM IDL and the SOM Compiler." 
  8429.  
  8430.  Every SOM class has a list that defines (in sequential order) the ancestor 
  8431.  classes whose initializer method procedures the class should invoke. If a 
  8432.  class's IDL does not specify an explicit directinitclasses modifier, the 
  8433.  default for this list is simply the class's parents - in left-to-right order. 
  8434.  
  8435.  Using the directinitclasses list and the actual run-time class hierarchy above 
  8436.  itself, each class inherits from SOMClass the ability to create a data 
  8437.  structure of type somInitCtrl. This structure is used to control the execution 
  8438.  of initializers. Moreover, it represents a particular visit-ordering that 
  8439.  reaches each class in the transitive closure of directinitclasses exactly 
  8440.  once. To initialize a given object, this visit-ordering occurs as follows: 
  8441.  While recursively visiting each ancestor class whose initializer method 
  8442.  procedure should be run, SOMobjects first runs the initializer method 
  8443.  procedures of all of that class's directinitclasses if they have not already 
  8444.  been run by another class's initializers, with ancestor classes always taken 
  8445.  in left-to-right order. 
  8446.  
  8447.  The code that deals with the somInitCtrl data structure is generated 
  8448.  automatically within the implementation bindings for a class, and need not 
  8449.  concern a class implementor. 
  8450.  
  8451.  When an instance of a given class (or some descendant class) is initialized, 
  8452.  only one of the given class's initializers will be executed, and this will 
  8453.  happen exactly once (under control of the ordering determined by the class of 
  8454.  the object being initialized). 
  8455.  
  8456.  The somInitCtrl structure solves a problem originally created by the add 
  8457.  ition of multiple inheritance to SOMobjects 2.0. With multiple inheritance, 
  8458.  any class can appear at the top of a multiple inheritance diamond. Previously, 
  8459.  whenever this happened, the class could easily receive multiple initialization 
  8460.  calls. In the current version of the SOMobjects Toolkit, however, the 
  8461.  somInitCtrl structure prevents this from happening. 
  8462.  
  8463.  
  8464. ΓòÉΓòÉΓòÉ 6.5.1.1. Declaring new initializers in SOM IDL ΓòÉΓòÉΓòÉ
  8465.  
  8466. When defining SOMobjects classes, programmers can easily declare and implement 
  8467. new initializers. Classes can have as many initializers as desired, and 
  8468. subclassers can invoke whichever of these they want. When introducing new 
  8469. initializers, developers must adhere to the following rules: 
  8470.  
  8471.      All initializer methods take a somInitCtrl data structure as an initial 
  8472.       inout parameter (its type is defined in the SOMobjects header file 
  8473.       somapi.h), and 
  8474.  
  8475.      All initializers return void. 
  8476.  
  8477.  Accordingly, the somDefaultInit initializer introduced by SOMObject takes a 
  8478.  somInitCtrl structure as its (only) argument, and returns void. Here is the 
  8479.  IDL syntax for this method, as declared in somobj.idl: 
  8480.  
  8481.   void  somDefaultInit (inout somInitCtrl ctrl);
  8482.  
  8483.  When introducing a new initializer, it is also necessary to specify the init 
  8484.  modifier in the implementation section. The init modifier is what tells 
  8485.  emitters that the new method is actually an initializer, so the method can be 
  8486.  properly supported from the language bindings. As described below, this 
  8487.  support includes the generation of special initializer stub procedures in the 
  8488.  implementation template file, as well as bindings containing 
  8489.  ancestor-initialization macros and object constructors that invoke the class 
  8490.  implementor's new initializers. 
  8491.  
  8492.  It is a good idea to begin the names of initializer methods with the name of 
  8493.  the class (or some other string that can be unique for the class). This is 
  8494.  important because all initializers available on a class must be newly 
  8495.  introduced by that class (that is, you cannot override initializers - except 
  8496.  for somDefaultInit). Using a class-unique name means that subclasses will not 
  8497.  be unnecessarily constrained in their choice of initializer names. 
  8498.  
  8499.  Here are two classes that introduce new initializers: 
  8500.  
  8501.   interface Example1 : SOMObject
  8502.   {
  8503.      void Example1_withName (inout somInitCtrl ctrl,in string name);
  8504.      void Example1_withSize (inout somInitCtrl ctrl,in long size);
  8505.      void Example1_withNandS(inout somInitCtrl ctrl,in string name,
  8506.                                                      in long size);
  8507.           implementation {
  8508.                   releaseorder: Example1_withName,
  8509.                                 Example1_withSize,
  8510.                                 Example1_withNandS;
  8511.                   somDefaultInit: override, init;
  8512.                   somDestruct: override;
  8513.                   Example1_withName: init;
  8514.                   Example1_withSize: init;
  8515.                   Example1_withNandS: init;
  8516.           };
  8517.   };
  8518.  
  8519.   interface Example2 : Example1
  8520.   {
  8521.      void Example2_withName(inout somInitCtrl ctrl, in string name);
  8522.      void Example2_withSize(inout somInitCtrl ctrl, in long size);
  8523.           implementation {
  8524.                   releaseorder: Example2_withName,
  8525.                                 Example2_withSize;
  8526.                   somDefaultInit: override, init;
  8527.                   somDestruct: override;
  8528.                   Example2_withName: init;
  8529.                   Example2_withSize: init;
  8530.           };
  8531.   };
  8532.  
  8533.  Here, interface "Example1" declares three new initializers. Notice the use of 
  8534.  inout somInitCtrl as the first argument of each initializer, and also note 
  8535.  that the init modifier is used in the implementation section. These two things 
  8536.  are required to declare initializers. Any number of initializers can be 
  8537.  declared by a class. "Example2" declares two initializers. 
  8538.  
  8539.  "Example1" and "Example2" both override the somDefaultInit initializerThis 
  8540.  initializer method is introduced by SOMObject and is special for two resons: 
  8541.  First, somDefaultInit is the only initializer that can be overridden And, 
  8542.  second, SOMobjects arranges that this initializer will always be available on 
  8543.  any class (as further explained below). 
  8544.  
  8545.  Historically in the SOMobjects Toolkit, object#initialization methods by 
  8546.  default have invoked the somInit method, which class implementors could 
  8547.  override to customize initialization as appropriate. SOMobjects continues to 
  8548.  support this approach, so that existing code (and class binaries) will execute 
  8549.  correctly. However, the somDefaultInit method is now the preferred form of 
  8550.  initialization because it offers greatly improved efficiency. 
  8551.  
  8552.  Even if no specialized initialization is needed for a class, you should still 
  8553.  override the somDefaultInit method in the interest of efficiency. If you do 
  8554.  not override somDefaultInit, then a generic (and therefore less efficient) 
  8555.  somDefaultInit method procedure will be used for your class. This generic 
  8556.  method procedure first invokes somDefaultInit on the appropriate ancestor 
  8557.  classes. Then (for consistency with earlier versions of SOMobjects), it checks 
  8558.  to determine if the class overrides somInit and, if so, calls any customized 
  8559.  somInit code provided by the class. 
  8560.  
  8561.  When you override somDefaultInit, the emitter's implementation template file 
  8562.  will include a stub procedure similar to those used for other initializers, 
  8563.  and you can fill it in as appropriate (or simply leave it as is). Default 
  8564.  initialization for your class will then run much faster than with the generic 
  8565.  method procedure. Examples of initializer stub procedures (and customizations) 
  8566.  are given below. 
  8567.  
  8568.  In summary, the initializers available for any class of objects are 
  8569.  somDefaultInit (which you should always override) plus any new initializers 
  8570.  explicitly declared by the class designer. Thus, "Example1" objects may be 
  8571.  initialized using any of four different initializers (the three that are 
  8572.  explicitly declared, plus somDefaultInit). Likewise, there are three 
  8573.  initializers for the "Example2" objects. Some examples of using initializers 
  8574.  are provided below. 
  8575.  
  8576.  
  8577. ΓòÉΓòÉΓòÉ 6.5.1.2. Considerations for 'somInit' initialization from earlier SOM releases ΓòÉΓòÉΓòÉ
  8578.  
  8579. To re-emphasize: All code written prior to SOMobjects Release 2.1 using 
  8580. documented guidelines for the earlier initialization approach based on the 
  8581. somInit method (as well as all existing class binaries) continues to be fully 
  8582. supported and useful. 
  8583.  
  8584. Prior to SOMobjects 2.1, initialization was done with initializer methods that 
  8585. would simply "chain" parent-method calls upward, thereby allowing the execution 
  8586. of initializer method procedures contributed by all ancestors of an object's 
  8587. class. This chaining of initializer calls was not supported in any special way 
  8588. by the SOM API. Parent-method calls are simply one of the possible idioms 
  8589. available to users of OOP in SOM, easily available to a SOM class designer as a 
  8590. result of the support provided by the SOMobjects Toolkit emitters for 
  8591. parent-method calls. 
  8592.  
  8593. So, SOM did not constrain initialization to be done in any particular way or 
  8594. require the use of any particular ordering of the method procedures of ancestor 
  8595. classes.  But, SOM did provide an overall framework that class designers could 
  8596. easily utilize in order to implement default initialization of SOM objects. 
  8597. This framework is provided by the somInit object-initializatio method 
  8598. introduced by the SOMobject class and supported by the SOM Toolkit emitters. 
  8599. The emitters create an implementation template file with stub procedures for 
  8600. overridden methods that automatically chain parent-method calls upward through 
  8601. parent classes. Many of the class methods that perform object creation called 
  8602. somInit automatically. 
  8603.  
  8604. Note:  These will now call somDefaultInit, which in turn calls somInit for 
  8605.        legacy code, as described in the previous topic. 
  8606.  
  8607.  Because it takes no arguments, somInit best served the purpose of a default 
  8608.  initializer. SOM programmers also had the option of introducing additional 
  8609.  "non-default" initialization methods that took arguments. In addition, by 
  8610.  using metaclasses, they could introduce new class methods as object 
  8611.  constructors that first create an object (generally using somNewNoInit.) and 
  8612.  then invoke some non-default initializer on the new object. 
  8613.  
  8614.  For a number of reasons, the somInit framework has been augmented by 
  8615.  recognizing initializers special kind of method in SOMobjects. One advantage 
  8616.  of this approach is that special metaclasses are no longer required for 
  8617.  defining constructors that take arguments. Instead, because the init modifier 
  8618.  identifies initializers, usage-binding emitters can now provide these 
  8619.  constructors. This results in simpler designs and more efficient programs. 
  8620.  
  8621.  Although somDefaultInit replaces somInit  as the no-argument initializer used 
  8622.  for SOM objects, all previous use of somInit is still supported by the 
  8623.  SOMobjects Developers Toolkit. You may continue to use somInit  although this 
  8624.  is somewhat less efficient than using somDefaultInit. 
  8625.  
  8626.  However, you cannot use both methods. In particular, if a class overrides both 
  8627.  somDefaultInit  and somInit, its somInit code will never be executed. It is 
  8628.  recommended that you always override  somDefaultInit for object 
  8629.  initialization. For one thing, it is likely that when SOMobjects is ported to 
  8630.  new systems, somInit (and somUninit) may not be supported on those systems. 
  8631.  Thus, code written using these (obsolete) methods will be less portable. 
  8632.  
  8633.  
  8634. ΓòÉΓòÉΓòÉ 6.5.1.3. Implementing initializers ΓòÉΓòÉΓòÉ
  8635.  
  8636. When new initializers are introduced by a class, as in the preceding examples, 
  8637. the implementation template file generated by the SOM Toolkit C and C++ 
  8638. emitters automatically contains an appropriate stub procedure for each 
  8639. initializer method, for the class implementor's use. The body of an initializer 
  8640. stub procedure consists of two main sections: 
  8641.  
  8642.      The first section performs calls to ancestors of the class to invoke 
  8643.       their initializers. 
  8644.  
  8645.      The second section is used by the programmer to perform any "local" 
  8646.       initializations appropriate to the instance data of the class being 
  8647.       defined. 
  8648.  
  8649.  In the first section, by default, the parents of the new class are the 
  8650.  ancestors whose initializers are called. When something else is desired, the 
  8651.  IDL directinitclasses modifier can be used to explicitly designate the 
  8652.  ancestors whose initializer methods should be invoked by a new class's 
  8653.  initializers. 
  8654.  
  8655.  Important:  Under no circumstances can the number or the ordering of ancestor 
  8656.  initializer calls in the first section of an initializer stub procedure be 
  8657.  changed. The control masks used by initializers are based on these orderings. 
  8658.  (If you want to change the number or ordering of ancestor initializer calls, 
  8659.  you must use the directinitclasses modifier.) The ancestor initializer calls 
  8660.  themselves can be modified as described below. 
  8661.  
  8662.  Each call to an ancestor initializer is made using a special macro (much like 
  8663.  a parent call) that is defined for this purpose within the implementation 
  8664.  bindings. These macros are defined for all possible ancestor initialization 
  8665.  calls. Initially, an initializer stub procedure invokes the default ancestor 
  8666.  initializers provided by somDefaultInit. However, a class implementor can 
  8667.  replace any of these calls with a different initializer call, as long as it 
  8668.  calls the same ancestor (see the example in the next topic). Non-default 
  8669.  initializer calls generally take other arguments in addition to the control 
  8670.  argument. 
  8671.  
  8672.  In the second section of an initializer stub procedure, the programmer 
  8673.  provides any class-specific code that may be needed for initialization. For 
  8674.  example, the "Example2_withName" stub procedure is shown below. As with all 
  8675.  stub procedures produced by the SOMobjects implementation-template emitters, 
  8676.  this code requires no modification to run correctly. 
  8677.  
  8678.   SOM_Scope void SOMLINK Example2_withName(Example2 *somSelf,
  8679.                                            Environment *ev,
  8680.                                            somInitCtrl* ctrl,
  8681.                                            string name)
  8682.   {
  8683.       Example2Data *somThis; /* set by BeginInitializer */
  8684.       somInitCtrl globalCtrl;
  8685.       somBooleanVector myMask;
  8686.       Example2MethodDebug("Example2","withName");
  8687.  
  8688.       /*
  8689.        * first section -- calls to ancestor initializers
  8690.        */
  8691.        Example2_BeginInitializer_Example2_withName;
  8692.        Example2_Init_Example1_somDefaultInit(somSelf, ctrl);
  8693.  
  8694.       /*
  8695.        * second section -- local Example2 initialization code
  8696.        */
  8697.   }
  8698.  
  8699.  In this example, notice that the "Example2_withName" initializer is an IDL 
  8700.  callstyle method, so it  receives an Environment argument. In contrast, 
  8701.  somDefaultInit is introduced by the SOMObject class (so it has an OIDL 
  8702.  callstyle initializer, without an environment). 
  8703.  
  8704.  Important: If a class is defined where multiple initializers have exactly the 
  8705.  same signature, then the C++ usage bindings will not be able to differentiate 
  8706.  among them. That is, if there are multiple initializers defined with 
  8707.  environment and long arguments, for example, then C++ clients would not be 
  8708.  able to make a call using only the class name and arguments, such as: 
  8709.  
  8710.  
  8711.   new Example2(env, 123);
  8712.  
  8713.  Rather, C++ users would be forced to first invoke the somNewNoInit method on 
  8714.  the class to create an uninitialized object, and then separately invoke the 
  8715.  desired initializer method on the object. This call would pass a zero for the 
  8716.  control argument, in addition to passing values for the other arguments. For 
  8717.  further discussion of client usage, see "Using initializers when creating new 
  8718.  objects" later in this chapter. 
  8719.  
  8720.  
  8721. ΓòÉΓòÉΓòÉ 6.5.1.4. Selecting non-default ancestor initializer calls ΓòÉΓòÉΓòÉ
  8722.  
  8723. Often, it will be appropriate (in the first section of an initializer stub 
  8724. procedure) to change the invocation of an ancestor's somDefaultInit initializer 
  8725. to some other initializer available on the same class. The rule for making this 
  8726. change is simple: Replace somDefaultInit with the name of the desired ancestor 
  8727. initializer, and add any new arguments that are required by the replacement 
  8728. initializer. Important: Under no circumstances can you change anything else in 
  8729. the first section. 
  8730.  
  8731. This example shows how to change an ancestor-initializer call correctly. Since 
  8732. there is a known "Example1_withName" initializer, the following default 
  8733. ancestor-initializer call (produced within the stub procedure for 
  8734. "Example2_withName") can be changed from 
  8735.  
  8736.  
  8737. Example2_Init_Example1_somDefaultInit(somSelf, ctrl);
  8738.  
  8739. to
  8740.  
  8741. Example2_Init_Example1_Example1_withName(somSelf, ev, ctrl, name)
  8742.  
  8743. Notice that the revised ancestor-initializer call includes arguments for an 
  8744. Environment and a name, as defined by the "Example1_withname" initializer. 
  8745.  
  8746.  
  8747. ΓòÉΓòÉΓòÉ 6.5.1.5. Using initializers when creating new objects ΓòÉΓòÉΓòÉ
  8748.  
  8749. There are several ways that client programs can take advantage of the 
  8750. somDefaultInit object initialization. If desired, clients can use the SOM API 
  8751. directly (rather than taking advantage of the usage bindings). Also, the 
  8752. general object constructor, somNew, can always be invoked on a class to create 
  8753. and initialize objects. This call creates a new object and then invokes 
  8754. somDefaultInit on it 
  8755.  
  8756. To use the SOM API directly, the client code should first invoke the 
  8757. somNewNoInit method on the desired class object to create a new, uninitialized 
  8758. object. Then, the desired initializer is invoked on the new object, passing a 
  8759. null (that is, 0) control argument in addition to whatever other arguments may 
  8760. be required by the initializer. For example: 
  8761.  
  8762.  
  8763. /* first make sure the Example2 class object exists */
  8764. Example2NewClass(Example2_MajorVersion, Example2_MinorVersion);
  8765.  
  8766.  
  8767. /* then create a new, uninitialized Example2 object */
  8768. myObject = _somNewNoInit(_Example2);
  8769.  
  8770. (null)
  8771. /* then initialize it with the desired initializer */
  8772. Example2_withName(myObject, env, 0, "MyName");
  8773.  
  8774. Usage bindings hide the details associated with initializer use in various ways 
  8775. and make calls more convenient for the client. For example, the C usage 
  8776. bindings for any given class already provide a convenience macro, 
  8777. <className>New, that first assures existence of the class object, and then 
  8778. calls somNew on it to create and initialize a new object. As explained above, 
  8779. somNew will use somDefaultInit to initialize the new object. 
  8780.  
  8781. Also, the C usage bindings provide object-construction macros that use 
  8782. somNewNoInit and then invoke non-default initializers. These  macros are named 
  8783. using the form <className>New_<initializerName>. For example, the C usage 
  8784. bindings for "Example2" allow using the following expression to create, 
  8785. initialize, and return a new "Example2" object: 
  8786.  
  8787.  
  8788. Example2New_Example2_withName(env, "AnyName");
  8789.  
  8790. In the C++ bindings, initializers are represented as overloaded C++ 
  8791. constructors. As a result, there is no need to specify the name of the 
  8792. initializer method. For example, using the C++ bindings, the following 
  8793. expressions could be used to create a new "Example2" object: 
  8794.  
  8795.  
  8796. new Example2;                   // will use somDefaultInit
  8797. new Example2();                 // will use somDefaultInit
  8798. new Example2(env,"A.B.Normal"); // will use Example2_withName
  8799. new Example2(env,123);          // will use Example2_withSize
  8800.  
  8801. Observe that if multiple initializers in a class have exactly the same 
  8802. signatures, the C++ usage bindings would be unable to differentiate among the 
  8803. calls, if made using the forms illustrated above. In this case, a client could 
  8804. use somNewNoInit first, and then invoke the specific initializer, as described 
  8805. in the preceding paragraphs. 
  8806.  
  8807.  
  8808. ΓòÉΓòÉΓòÉ 6.5.2. Uninitialization ΓòÉΓòÉΓòÉ
  8809.  
  8810. An object should always be uninitialized before its storage is freed. This is 
  8811. important because it also allows releasing resources and freeing storage not 
  8812. contained within the body of the object.  SOMobjects handles uninitialization 
  8813. in much the same way as for initializers: An uninitializer takes a control 
  8814. argument and is supported with stub procedures in the implementation template 
  8815. file in a manner similar to initializers. 
  8816.  
  8817. Only a single uninitialization method is needed, so SOMObject introduces the 
  8818. method that provides this function: somDestruct. As with the default 
  8819. initializer method, a class designer who requires nothing special in the way of 
  8820. uninitialization need not be concerned about modifying the default somDestruct 
  8821. method procedure. However, your code will execute faster if the .idl file 
  8822. overrides somDestruct so that a non-generic stub-procedure code can be provided 
  8823. for the class. Note that somDestruct was overridden by "Example1" and 
  8824. "Example2" above No specific IDL modifiers other than override are required for 
  8825. this. 
  8826.  
  8827. Like an initializer template, the stub procedure for somDestruct consists of 
  8828. two sections: The first section is used by the programmer for performing any 
  8829. "local" uninitialization that may be required. The second section (which 
  8830. consists of a single EndDestructor macro invocation) invokes somDestruct on 
  8831. ancestors The second section must not be modified or removed by the programmer. 
  8832. It must be the final statement executed in the destructor. 
  8833.  
  8834.  
  8835. ΓòÉΓòÉΓòÉ 6.5.2.1. Using `somDestruct' ΓòÉΓòÉΓòÉ
  8836.  
  8837. It is rarely necessary to invoke the somDestruct method explicitly This is 
  8838. because object uninitialization is normally done just before freeing an 
  8839. object's storage, and the mechanisms provided by SOMobjects for this purpose 
  8840. will automatically invoke somDestruct. For example, if an object were created 
  8841. using somNew or somNewNoInit, or by using a convenience macro provided by the C 
  8842. languag bindings, then the somFree method can be invoked on the object to 
  8843. delete the object. This automatically calls somDestruct before freeing storage. 
  8844.  
  8845. C++ users can simply use the delete operator provided by the C++ bindings. This 
  8846. destructor calls somDestruct before the C++ delete  operator frees the object's 
  8847. storage. 
  8848.  
  8849. On the other hand, if an object is initially created by allocating memory in 
  8850. some special way and subsequently some somRenew methods are used, somFree (or 
  8851. C++ delete) is probably not appropriate. Thus, the somDestruct method should be 
  8852. explicitly called to uninitialize the object before freeing memory. 
  8853.  
  8854.  
  8855. ΓòÉΓòÉΓòÉ 6.5.3. A complete example ΓòÉΓòÉΓòÉ
  8856.  
  8857. The following example illustrates the implementation and use of initializers 
  8858. and destructors from the C++ bindings. The first part shows the IDL for three 
  8859. classes with initializers. For variety, some of the classes use callstyle OIDL 
  8860. and others use callstyle IDL. 
  8861.  
  8862. #include <somobj.idl>
  8863.  
  8864. interface A : SOMObject {
  8865.         readonly attribute long a;
  8866.         implementation {
  8867.                 releaseorder: _get_a;
  8868.                 functionprefix = A;
  8869.                 somDefaultInit: override, init;
  8870.                 somDestruct: override;
  8871.                 somPrintSelf: override;
  8872.         };
  8873. };
  8874.  
  8875.  
  8876. (null)
  8877. interface B : SOMObject {
  8878.         readonly attribute long b;
  8879.         void BwithInitialValue(inout somInitCtrl ctrl,
  8880.                                in long initialValue);
  8881.         implementation {
  8882.                 callstyle = oidl;
  8883.                 releaseorder: _get_b, BwithInitialValue;
  8884.                 functionprefix = B;
  8885.                 BwithInitialValue: init;
  8886.                 somDefaultInit: override, init;
  8887.                 somDestruct: override;
  8888.                 somPrintSelf: override;
  8889.         };
  8890. };
  8891.  
  8892.  
  8893. (null)
  8894. interface C : A, B      {
  8895.         readonly attribute long c;
  8896.         void CwithInitialValue(inout somInitCtrl ctrl,
  8897.                                in long initialValue);
  8898.         void CwithInitialString(inout somInitCtrl ctrl,
  8899.                                 in string initialString);
  8900.         implementation {
  8901.                 releaseorder: _get_c, CwithInitialString,
  8902.                               CwithInitialValue;
  8903.                 functionprefix = C;
  8904.                 CwithInitialString: init;
  8905.                 CwithInitialValue: init;
  8906.                 somDefaultInit: override;
  8907.                 somDestruct: override;
  8908.                 somPrintSelf: override;
  8909.         };
  8910. };
  8911.  
  8912.  
  8913. ΓòÉΓòÉΓòÉ 6.5.3.1. Implementation code ΓòÉΓòÉΓòÉ
  8914.  
  8915. Based on the foregoing class definitions, the next example illustrates several 
  8916. important aspects of initializers. The following code is a completed 
  8917. implementation template and an example client program for the preceding 
  8918. classes. Code added to the original template is given in bold. 
  8919.  
  8920. /*
  8921.  *  This file generated by the SOM Compiler and Emitter Framework.
  8922.  *  Generated using:
  8923.  *      SOM Emitter emitxtm.dll: 2.22
  8924.  */
  8925.  
  8926. #define SOM_Module_ctorfullexample_Source
  8927. #define VARIABLE_MACROS
  8928. #define METHOD_MACROS
  8929. #include <ctorFullExample.xih>
  8930. #include <stdio.h>
  8931.  
  8932. SOM_Scope void SOMLINK AsomDefaultInit(A *somSelf,
  8933.                                        somInitCtrl* ctrl)
  8934. {
  8935.     AData *somThis; /* set by BeginInitializer */
  8936.     somInitCtrl globalCtrl;
  8937.     somBooleanVector myMask;
  8938.     AMethodDebug("A","somDefaultInit");
  8939.  
  8940.     A_BeginInitializer_somDefaultInit;
  8941.     A_Init_SOMObject_somDefaultInit(somSelf, ctrl);
  8942.     /*
  8943.      * local A initialization code added by programmer
  8944.      */
  8945. _a = 1;
  8946. }
  8947.  
  8948. SOM_Scope void SOMLINK AsomDestruct(A *somSelf, octet doFree,
  8949.                                     somDestructCtrl* ctrl)
  8950. {
  8951.     AData *somThis; /* set by BeginDestructor */
  8952.     somDestructCtrl globalCtrl;
  8953.     somBooleanVector myMask;
  8954.     AMethodDebug("A","somDestruct");
  8955.     A_BeginDestructor;
  8956.  
  8957.     /*
  8958.      * local A deinitialization code added by programmer
  8959.      */
  8960.     A_EndDestructor;
  8961. }
  8962.  
  8963. SOM_Scope SOMObject*  SOMLINK AsomPrintSelf(A *somSelf)
  8964. {
  8965.     AData *somThis = AGetData(somSelf);
  8966.     AMethodDebug("A","somPrintSelf");
  8967.     somPrintf("{an instance of %s at location %X with (a=%d)}\n",
  8968.              _somGetClassName(),somSelf,__get_a((Environment*)0));
  8969.     return (SOMObject*)((void*)somSelf);
  8970. }
  8971.  
  8972. SOM_Scope void SOMLINK BBwithInitialValue(B *somSelf,
  8973.                                           somInitCtrl* ctrl,
  8974.                                           long initialValue)
  8975. {
  8976.     BData *somThis; /* set by BeginInitializer */
  8977.     somInitCtrl globalCtrl;
  8978.     somBooleanVector myMask;
  8979.     BMethodDebug("B","BwithInitialValue");
  8980.  
  8981.     B_BeginInitializer_withInitialValue;
  8982.     B_Init_SOMObject_somDefaultInit(somSelf, ctrl);
  8983.  
  8984.     /*
  8985.      * local B initialization code added by programmer
  8986.      */
  8987.  _b = initialValue;
  8988. }
  8989.  
  8990. SOM_Scope void SOMLINK BsomDefaultInit(B *somSelf,
  8991.                                        somInitCtrl* ctrl)
  8992. {
  8993.     BData *somThis; /* set by BeginInitializer */
  8994.     somInitCtrl globalCtrl;
  8995.     somBooleanVector myMask;
  8996.     BMethodDebug("B","somDefaultInit");
  8997.  
  8998.     B_BeginInitializer_somDefaultInit;
  8999.     B_Init_SOMObject_somDefaultInit(somSelf, ctrl);
  9000.  
  9001.     /*
  9002.      * local B initialization code added by programmer
  9003.      */
  9004.  _b = 2;
  9005. }
  9006.  
  9007. SOM_Scope void SOMLINK BsomDestruct(B *somSelf, octet doFree,
  9008.                                     somDestructCtrl* ctrl)
  9009. {
  9010.     BData *somThis; /* set by BeginDestructor */
  9011.     somDestructCtrl globalCtrl;
  9012.     somBooleanVector myMask;
  9013.     BMethodDebug("B","somDestruct");
  9014.     B_BeginDestructor;
  9015.  
  9016.     /*
  9017.      * local B deinitialization code added by programmer
  9018.      */
  9019.  
  9020.     B_EndDestructor;
  9021. }
  9022.  
  9023. SOM_Scope SOMObject*  SOMLINK BsomPrintSelf(B *somSelf)
  9024. {
  9025.     BData *somThis = BGetData(somSelf);
  9026.     BMethodDebug("B","somPrintSelf");
  9027.     printf("{an instance of %s at location %X with (b=%d)}\n",
  9028.            _somGetClassName(),somSelf,__get_b());
  9029.     return (SOMObject*)((void*)somSelf);
  9030. }
  9031.  
  9032. Note: The following initializer for a C object accepts a string as an argument, 
  9033. converts this to an integer, and uses this for ancestor initialization of "B." 
  9034. This illustrates how a default ancestor initializer call is replaced with a 
  9035. non-default ancestor initializer call. 
  9036.  
  9037. SOM_Scope void SOMLINK CCwithInitialString(C *somSelf,
  9038.                                            Environment *ev,
  9039.                                            somInitCtrl* ctrl,
  9040.                                            string initialString)
  9041. {
  9042.     CData *somThis; /* set by BeginInitializer */
  9043.     somInitCtrl globalCtrl;
  9044.     somBooleanVector myMask;
  9045.     CMethodDebug("C","CwithInitialString");
  9046.  
  9047.     C_BeginInitializer_withInitialString;
  9048.     C_Init_A_somDefaultInit(somSelf, ctrl);
  9049.     C_Init_B_BwithInitialValue(somSelf, ctrl,
  9050.                                atoi(initialString)-11);
  9051.  
  9052.     /*
  9053.      * local C initialization code added by programmer
  9054.      */
  9055.     _c = atoi(initialString);
  9056. }
  9057.  
  9058. SOM_Scope void SOMLINK CsomDefaultInit(C *somSelf,
  9059.                                        somInitCtrl* ctrl)
  9060. {
  9061.     CData *somThis; /* set by BeginInitializer */
  9062.     somInitCtrl globalCtrl;
  9063.     somBooleanVector myMask;
  9064.     CMethodDebug("C","somDefaultInit");
  9065.  
  9066.     C_BeginInitializer_somDefaultInit;
  9067.     C_Init_A_somDefaultInit(somSelf, ctrl);
  9068.     C_Init_B_somDefaultInit(somSelf, ctrl);
  9069.  
  9070.     /*
  9071.      * local C initialization code added by programmer
  9072.      */
  9073. _c = 3;
  9074. }
  9075.  
  9076. SOM_Scope void SOMLINK CsomDestruct(C *somSelf, octet doFree,
  9077.                                     somDestructCtrl* ctrl)
  9078. {
  9079.     CData *somThis; /* set by BeginDestructor */
  9080.     somDestructCtrl globalCtrl;
  9081.     somBooleanVector myMask;
  9082.     CMethodDebug("C","somDestruct");
  9083.     C_BeginDestructor;
  9084.  
  9085.     /*
  9086.      * local C deinitialization code added by programmer
  9087.      */
  9088.  
  9089.     C_EndDestructor;
  9090. }
  9091.  
  9092.  
  9093. SOM_Scope SOMObject*  SOMLINK CsomPrintSelf(C *somSelf)
  9094. {
  9095.     CData *somThis = CGetData(somSelf);
  9096.     CMethodDebug("C","somPrintSelf");
  9097.     printf("{an instance of %s at location %X with"
  9098.            " (a=%d, b=%d, c=%d)}\n",
  9099.         _somGetClassName(),somSelf,
  9100.         __get_a((Environment*)0),
  9101.         __get_b(),
  9102.         __get_c((Environment*)0));
  9103.     return (SOMObject*)((void*)somSelf);
  9104. }
  9105.  
  9106. SOM_Scope void SOMLINK CCwithInitialValue(  C *somSelf,
  9107.                                         Environment *ev,
  9108.                                         somInitCtrl* ctrl,
  9109.                                         long initialValue)
  9110. {
  9111.     CData *somThis; /* set by BeginInitializer */
  9112.     somInitCtrl globalCtrl;
  9113.     somBooleanVector myMask;
  9114.     CMethodDebug("C","CwithInitialValue");
  9115.  
  9116.     C_BeginInitializer_withInitialValue;
  9117.     C_Init_A_somDefaultInit(somSelf, ctrl);
  9118.     C_Init_B_BwithInitialValue(somSelf, ctrl, initialValue-11);
  9119.  
  9120.     /*
  9121.      * local C initialization code added by programmer
  9122.      */
  9123.     _c = initialValue;
  9124. }
  9125.  
  9126. Here is a C++ program that creates instances of "A", "B", and "C" using the 
  9127. initializers defined above. 
  9128.  
  9129. main()
  9130. {
  9131.     SOM_TraceLevel = 1;
  9132.  
  9133.     A *a = new A;
  9134.     a->somPrintSelf();
  9135.     delete a;
  9136.     printf("\n");
  9137.  
  9138.     B *b = new B();
  9139.     b->somPrintSelf();
  9140.     delete b;
  9141.     printf("\n");
  9142.  
  9143.     b = new B(22);
  9144.     b->somPrintSelf();
  9145.     delete b;
  9146.     printf("\n");
  9147.  
  9148.     C *c = new C;
  9149.     c->somPrintSelf();
  9150.     delete c;
  9151.     printf("\n");
  9152.  
  9153.     c = new C((Environment*)0, 44);
  9154.     c->somPrintSelf();
  9155.     delete c;
  9156.     printf("\n");
  9157.  
  9158.     c = new C((Environment*)0, "66");
  9159.     c->somPrintSelf();
  9160.     delete c;
  9161. }
  9162.  
  9163. The output from the preceding program is as follows: 
  9164.  
  9165. "ctorFullExample.C": 18:        In A:somDefaultInit
  9166. "ctorFullExample.C": 48:        In A:somPrintSelf
  9167. "./ctorFullExample.xih": 292:     In A:A_get_a
  9168. {an instance of A at location 20063C38 with (a=1)}
  9169. "ctorFullExample.C": 35:        In A:somDestruct
  9170.  
  9171. "ctorFullExample.C": 79:        In B:somDefaultInit
  9172. "ctorFullExample.C": 110: In B:somPrintSelf
  9173. "./ctorFullExample.xih": 655:     In B:B_get_b
  9174. {an instance of B at location 20064578 with (b=2)}
  9175. "ctorFullExample.C": 97:        In B:somDestruct
  9176.  
  9177. "ctorFullExample.C": 62:        In B:BwithInitialValue
  9178. "ctorFullExample.C": 110: In B:somPrintSelf
  9179. "./ctorFullExample.xih": 655:     In B:B_get_b
  9180. {an instance of B at location 20064578 with (b=22)}
  9181. "ctorFullExample.C": 97:        In B:somDestruct
  9182.  
  9183. "ctorFullExample.C": 150: In C:somDefaultInit
  9184. "ctorFullExample.C": 18:        In A:somDefaultInit
  9185. "ctorFullExample.C": 79:        In B:somDefaultInit
  9186. "ctorFullExample.C": 182: In C:somPrintSelf
  9187. "./ctorFullExample.xih": 292:     In A:A_get_a
  9188. "./ctorFullExample.xih": 655:     In B:B_get_b
  9189. "./ctorFullExample.xih": 1104:    In C:C_get_c
  9190. {an instance of C at location 20065448 with (a=1, b=2, c=3)}
  9191. "ctorFullExample.C": 169: In C:somDestruct
  9192. "ctorFullExample.C": 35:        In A:somDestruct
  9193. "ctorFullExample.C": 97:        In B:somDestruct
  9194.  
  9195. "ctorFullExample.C": 196: In C:CwithInitialValue
  9196. "ctorFullExample.C": 18:        In A:somDefaultInit
  9197. "ctorFullExample.C": 62:        In B:BwithInitialValue
  9198. "ctorFullExample.C": 182: In C:somPrintSelf
  9199. "./ctorFullExample.xih": 292:     In A:A_get_a
  9200. "./ctorFullExample.xih": 655:     In B:B_get_b
  9201. "./ctorFullExample.xih": 1104:      In C:C_get_c
  9202. {an instance of C at location 20065448 with (a=1, b=33, c=44)}
  9203. "ctorFullExample.C": 169: In C:somDestruct
  9204. "ctorFullExample.C": 35:        In A:somDestruct
  9205. "ctorFullExample.C": 97:        In B:somDestruct
  9206.  
  9207.  
  9208.  
  9209. "ctorFullExample.C": 132: In C:CwithInitialString
  9210. "ctorFullExample.C": 18:        In A:somDefaultInit
  9211. "ctorFullExample.C": 62:        In B:BwithInitialValue
  9212. "ctorFullExample.C": 182: In C:somPrintSelf
  9213. "./ctorFullExample.xih": 292:     In A:A_get_a
  9214. "./ctorFullExample.xih": 655:     In B:B_get_b
  9215. "./ctorFullExample.xih": 1104:      In C:C_get_c
  9216. {an instance of C at location 20065448 with (a=1, b=55, c=66)}
  9217. "ctorFullExample.C": 169: In C:somDestruct
  9218. "ctorFullExample.C": 35:        In A:somDestruct
  9219. "ctorFullExample.C": 97:        In B:somDestruct
  9220.  
  9221.  
  9222. ΓòÉΓòÉΓòÉ 6.5.4. Customizing the initialization of class objects ΓòÉΓòÉΓòÉ
  9223.  
  9224. As described previously, the somDefaultInit method can be overridden to 
  9225. customize the initialization of objects. Because classes are objects, 
  9226. somDefaultInit is also invoked on classes when they are first created 
  9227. (generally by invoking the somNew method on a metaclass). For a class object, 
  9228. however, somDefaultInit normally just sets the name of the class to "unknown," 
  9229. after which the somInitMIClass method must be used for the major portion of 
  9230. class initialization. Of course, metaclasses can override somDefaultInit to 
  9231. initialize introduced class variables that require no arguments for their 
  9232. initialization. 
  9233.  
  9234. Note: Because somNew does not call somInitMIClass, class objects returned from 
  9235. invocations of somNew on a metaclass are not yet useful class objects. 
  9236.  
  9237. The somInitMIClass method (introduced by SOMClass) is invoked on a new class 
  9238. object using arguments to indicate the class name and the parent classes from 
  9239. which inheritance is desired (among other arguments). This invocation is made 
  9240. by whatever routine is used to initialize the class. (For SOM classes using the 
  9241. C or C++ implementation bindings, this is handled by the somBuildClass 
  9242. procedure, which is called by the implementation bindings automatically.) The 
  9243. somInitMIClass method is often overridden by a metaclass to influence 
  9244. initialization of new classes in some way. Typically, the overriding procedure 
  9245. begins by making parent method calls, and then performs additional actions 
  9246. thereafter. 
  9247.  
  9248. However, without use of the Cooperative Metaclass to guarantee correct 
  9249. operation of SOMobjects in general, none of the methods introduced by SOMClass 
  9250. should be overridden. As a result, customizing the initialization of class 
  9251. objects (other than through overriding somDefaultInit for initialization of 
  9252. class variables) is not recommended in SOMobjects 2.1.  Users whose 
  9253. applications require this should request access to the experimental Cooperative 
  9254. Metaclass used to implement the SOMobjects Metaclass Framework.  But, 
  9255. metaclasses implemented using the experimental Cooperative Metaclass may 
  9256. require reprogramming when SOMobjects introduces an officially supported 
  9257. Cooperative Metaclass. 
  9258.  
  9259.  
  9260. ΓòÉΓòÉΓòÉ 6.6. Creating a SOM Class Library ΓòÉΓòÉΓòÉ
  9261.  
  9262. One of the principal advantages of SOM is that it makes "black box" (or binary) 
  9263. reusability possible. Consequently, SOM classes are frequently packaged and 
  9264. distributed as class libraries. A class library  holds the actual 
  9265. implementation of one or more classes and can be dynamically loaded and 
  9266. unloaded as needed by applications. Importantly, class libraries can also be 
  9267. replaced independently of the applications  that use them and, provided that 
  9268. the class implementor observes simple SOM guidelines for preserving binary 
  9269. compatibility, can evolve and expand over time. 
  9270.  
  9271.  
  9272. ΓòÉΓòÉΓòÉ 6.6.1. General guidelines for class library designers ΓòÉΓòÉΓòÉ
  9273.  
  9274. One of the most important features of SOM is that it allows you to build and 
  9275. distribute class libraries in binary form. Because there is no "fragile base 
  9276. class" problem in SOM, client programs that use your libraries (by subclassing 
  9277. your classes or by invoking the methods in your classes) will not need to be 
  9278. recompiled if you later produce a subsequent version of the library, provided 
  9279. you adhere to some simple restrictions. 
  9280.  
  9281.    1. You should always maintain the syntax and the semantics of your existing 
  9282.       interfaces. This means that you cannot take away any exposed 
  9283.       capabilities, nor add or remove arguments for any of your public methods. 
  9284.  
  9285.    2. Always maintain the releaseorder list, so that it never changes except 
  9286.       for additions to the end. The releaseorder should contain all of your 
  9287.       public methods, the one or two methods that correspond to each public 
  9288.       attribute, and a placeholder for each private method (or private 
  9289.       attribute method). 
  9290.  
  9291.    3. Assign a higher minorversion number for each subsequent release of a 
  9292.       class, so that client programmers can determine whether a new feature is 
  9293.       present or not. Change the majorversion number only when you deliberately 
  9294.       wish to break binary compatibility. (See the topic "Modifier statements" 
  9295.       in Chapter 4, "SOM IDL and the SOM Compiler" for explanations of the 
  9296.       releaseorder, minorversion and majorversion modifiers.) 
  9297.  
  9298.    4. Define attributes that return pointers to structures, or define methods 
  9299.       that take an out  parameter for passing a structure back to the caller. 
  9300.       In Windows NT and Windows 95, Microsoft has provided the --stdcall 
  9301.       convention. However it is not always faithfully implemented across 
  9302.       compilers. So, it is best to avoid struct returns. 
  9303.  
  9304.       Note that you can always avoid this problem in classes of your own 
  9305.       design. However, some of the attributes and methods in the frameworks 
  9306.       that come with the SOMobjects Toolkit do  return structures. Many of 
  9307.       these are dictated by the OMG CORBA standard, and could not be avoided. 
  9308.  
  9309.    5. With each new release of your class library, you have significant degrees 
  9310.       of freedom to change much of the implementation detail. You can add to or 
  9311.       reorganize your instance variables, add new public or private methods, 
  9312.       inject new base classes into your class hierarchies, change metaclasses 
  9313.       to more derived ones, and relocate the implementation of methods upward 
  9314.       in your class hierarchies. Provided you always retain the same 
  9315.       capabilities and semantics that were present in your first release, none 
  9316.       of these changes will break the client programs that use your libraries. 
  9317.  
  9318.  
  9319. ΓòÉΓòÉΓòÉ 6.6.2. Types of class libraries ΓòÉΓòÉΓòÉ
  9320.  
  9321. Since class libraries are not programs, users cannot execute them directly. To 
  9322. enable users to make direct use of your classes, you must also provide one or 
  9323. more programs that create the classes and objects that the user will need. This 
  9324. section describes how to package your classes in a SOM class library and what 
  9325. you must do to make the contents of the library accessible to other programs. 
  9326.  
  9327. On AIX, class libraries are actually produced as AIX shared libraries, whereas 
  9328. on OS/2 or Windows they appear as dynamically-linked libraries (or DLLs). The 
  9329. term "DLL" is sometimes used to refer to either an AIX, an OS/2, or a Windows 
  9330. class library, and (by convention only) the file suffix ".dll" is used for SOM 
  9331. class libraries on all platforms. 
  9332.  
  9333. A program can use a class library containing a given class or classes in one of 
  9334. two ways: 
  9335.  
  9336.    1. If the programmer employs the SOM bindings to instantiate the class and 
  9337.       invoke its methods, the resulting client program contains static 
  9338.       references to the class. The operating system will automatically resolve 
  9339.       those references when the program is loaded, by also loading the 
  9340.       appropriate class library. 
  9341.  
  9342.    2. If the programmer uses only the dynamic SOM mechanisms for finding the 
  9343.       class and invoking its methods (for example, by invoking somFindClass, 
  9344.       somFindMethod, somLookupMethod, somDispatch, somResolveByName,and so 
  9345.       forth), the resulting client program does not contain any static 
  9346.       references to the class library. Thus, SOM will load the class library 
  9347.       dynamically during execution of the program. Note: For SOM to be able to 
  9348.       load the class library, the dllname modifier must be set in the .idl 
  9349.       file. (See the topic "Modifier statements" in Chapter 4, "SOM IDL and the 
  9350.       SOM Compiler.") 
  9351.  
  9352.  Because the provider of a class library cannot predict which of these ways a 
  9353.  class will be used, SOM class libraries must be built such that either usage 
  9354.  is possible. The first case above requires the class library to export the 
  9355.  entry points needed by the SOM bindings, whereas the second case requires the 
  9356.  library to provide an initialization function to create the classes it 
  9357.  contains. The following topics discuss each case. 
  9358.  
  9359.  
  9360. ΓòÉΓòÉΓòÉ 6.6.3. Building export files ΓòÉΓòÉΓòÉ
  9361.  
  9362. The SOM Compiler provides a "def" emitter to produce the necessary exported 
  9363. symbols for each class. For example, to generate the necessary exports for a 
  9364. class "A", issue the sc command with the following -s option. (For a discussion 
  9365. of the sc command and options, see "Running the SOM Compiler" in Chapter 4, 
  9366. "SOM IDL and the SOM Compiler.") 
  9367.  
  9368. This command generates an "a.def" file: 
  9369.  
  9370.    sc -sdef a.idl
  9371.  
  9372. Typically, a class library contains multiple classes. To produce an appropriate 
  9373. export file for each class that the library will contain, you can create a new 
  9374. export file for the library itself by combining the exports from each "def" 
  9375. file into a single file. The following example of a combined export "def" file 
  9376. a class library composed of three classes, "A", "B", and "C". 
  9377.  
  9378.  "def" file:
  9379.  
  9380.    LIBRARY abc INITINSTANCE
  9381.    DESCRIPTION 'abc example class library'
  9382.    PROTMODE
  9383.    DATA MULTIPLE NONSHARED LOADONCALL
  9384.    EXPORTS
  9385.      ACClassData
  9386.      AClassData
  9387.      ANewClass
  9388.      BCClassData
  9389.      BClassData
  9390.      BNewClass
  9391.      CCClassData
  9392.      CClassData
  9393.      CNewClass
  9394.  
  9395. Other symbols in addition to those generated by the "def" emitter can be 
  9396. included if needed, but this is not required by SOM. One feature of SOM is that 
  9397. a class library needs no more than three exports per class (by contrast, many 
  9398. OOP systems require externals for every method as well). One required export is 
  9399. the name of a procedure to create the class (<className>NewClass), and the 
  9400. others are two external data structures that are referenced by the SOM 
  9401. bindings. 
  9402.  
  9403.  
  9404. ΓòÉΓòÉΓòÉ 6.6.4. Specifying the initialization function ΓòÉΓòÉΓòÉ
  9405.  
  9406. An initialization function for the class library must be provided to support 
  9407. dynamic loading of the library by the SOM Class Manager. The SOM Class Manager 
  9408. expects that, whenever it loads a class library, the initialization function 
  9409. will create and register class objects for all of the classes contained in the 
  9410. library. 
  9411.  
  9412. These classes are then managed as a group (called an affinity group). One class 
  9413. in the affinity group has a privileged position-namely, the class that was 
  9414. specifically requested when the library was loaded. If that class (that is, the 
  9415. class that caused loading to occur) is subsequently unregistered, the SOM Class 
  9416. Manager will automatically unregister all of the other classes in the affinity 
  9417. group as well, and will unload the class library. Similarly, if the SOM Class 
  9418. Manager is explicitly asked to unload the class library, it will also 
  9419. automatically unregister and free all of the classes in the affinity group. 
  9420.  
  9421. It is the responsibility of the class-library creator to supply the 
  9422. initialization function. The interface to the initialization function is given 
  9423. by the following C/C++ prototype: 
  9424.  
  9425.    #ifdef __IBMC__
  9426.      #pragma linkage (SOMInitModule, system)
  9427.    #endif
  9428.  
  9429.    SOMEXTERN void  SOMLINK SOMInitModule ( long majorVersion,
  9430.                                            long minorVersion,
  9431.                                            string className);
  9432.  
  9433. The parameters provided to this function are the className and the major/minor 
  9434. version numbers of the class that was requested when the library was loaded 
  9435. (that is, the class that caused loading). The initialization function is free 
  9436. to use or to disregard this information; nevertheless, if it fails to create a 
  9437. class object with the required name, the SOM Class Manager considers the load 
  9438. to have failed. As a rule of thumb, however, if the initialization function 
  9439. invokes a <className>NewClass procedure for each class in the class library, 
  9440. this condition will always be met. Consequently, the parameters supplied to the 
  9441. initialization function are not needed in most cases. 
  9442.  
  9443. Here is a typical class-library initialization function, written in C, for a 
  9444. library with three classes ("A", "B", and "C"): 
  9445.  
  9446.    #include "a.h"
  9447.    #include "b.h"
  9448.    #include "c.h"
  9449.    #ifdef __IBMC__
  9450.      #pragma linkage (SOMInitModule, system)
  9451.    #endif
  9452.  
  9453.    SOMEXTERN void  SOMLINK SOMInitModule (long majorVersion,
  9454.                              long minorVersion, string className)
  9455.    {
  9456.        SOM_IgnoreWarning (majorVersion);  /* This function makes */
  9457.        SOM_IgnoreWarning (minorVersion);  /* no use of the passed */
  9458.        SOM_IgnoreWarning (className);     /* arguments.   */
  9459.        ANewClass (A_MajorVersion, A_MinorVersion);
  9460.        BNewClass (B_MajorVersion, B_MinorVersion);
  9461.        CNewClass (C_MajorVersion, C_MinorVersion);
  9462.    }
  9463.  
  9464. The source code for the initialization function can be added to one of the 
  9465. implementation files for the classes in the library, or you can put it in a 
  9466. separate file and compile it independently. 
  9467.  
  9468.  
  9469. ΓòÉΓòÉΓòÉ 6.6.5. Creating the import library ΓòÉΓòÉΓòÉ
  9470.  
  9471. Finally, for each of your class libraries, you should create an import library 
  9472. that can be used by client programs (or by other class libraries that use your 
  9473. classes) to resolve the references to your classes. 
  9474.  
  9475. Here is an example illustrating all of the steps required to create a class 
  9476. library ("abc.dll") that contains the three classes "A", "B", and "C". 
  9477.  
  9478.    1. Compile all of the implementation files for the classes that will be 
  9479.       included in the library. Include the initialization function also. 
  9480.  
  9481.       Written in C: 
  9482.  
  9483.                icc -I. -I%SOMBASE%\include -Ge- -c a.c
  9484.                icc -I. -I%SOMBASE%\include -Ge- -c b.c
  9485.                icc -I. -I%SOMBASE%\include -Ge- -c c.c
  9486.                icc -I. -I%SOMBASE%\include -Ge- -c initfunc.c
  9487.  
  9488.       Note:  The "-Ge" option is used only with the IBM compiler.  It indicates 
  9489.              that the object files will go into a DLL. 
  9490.  
  9491.       Written in C++: 
  9492.  
  9493.                icc -I. -I%SOMBASE%\include -Ge- -c a.cpp
  9494.                icc -I. -I%SOMBASE%\include -Ge- -c b.cpp
  9495.                icc -I. -I%SOMBASE%\include -Ge- -c c.cpp
  9496.                icc -I. -I%SOMBASE%\include -Ge- -c initfunc.cpp
  9497.  
  9498.       Note:  The "-Ge" option is used only with the IBM compiler.  It indicates 
  9499.              that the object files will go into a DLL. 
  9500.  
  9501.    2. Produce an export file for each class. 
  9502.  
  9503.                sc -sdef a.idl b.idl c.idl
  9504.  
  9505.    3. Manually combine the exported symbols into a single file. 
  9506.  
  9507.       Create a file "abc.def" from "a.def", "b.def", and  c.def". Include the 
  9508.       initialization function (SOMInitModule) in the export list, so that all 
  9509.       classes will be initialized automatically, unless your initialization 
  9510.       function does not need arguments and you explicitly invoke it yourself 
  9511.       from an DLL initialization    routine. 
  9512.  
  9513.    4. Create an import library ╤ì/export.objΓêÖ that corresponds to the class 
  9514.       library, so that programs and other class libraries can use (import) your 
  9515.       classes. 
  9516.  
  9517.               ilib /geni abc.def
  9518.  
  9519.       The filename ("abc.def") specifies the exported symbols to include in the 
  9520.       import library. An import library ("abc.lib") will be created. Another 
  9521.       file ("abc.exp") will also be created. This is the "export.obj" which 
  9522.       will be used in the link step. 
  9523.  
  9524.    5. Using the object files and the export file, produce a binary class 
  9525.       library. 
  9526.  
  9527.                set LIB=%SOMBASE%\lib;%LIB%
  9528.                  ilink a.obj b.obj c.obj initfunc.obj /OUT:abc.dll somtk.lib\ abc.exp
  9529.  
  9530.       If your classes make use of classes in other class libraries, include the 
  9531.       names of their import libraries immediately after "somtk" (before the 
  9532.       next comma). 
  9533.  
  9534.  
  9535. ΓòÉΓòÉΓòÉ 6.7. Customizing Memory Management ΓòÉΓòÉΓòÉ
  9536.  
  9537. SOM is designed to be policy free and highly adaptable. Most of the SOM 
  9538. behavior can be customized by subclassing the built-in classes and overriding 
  9539. their methods, or by replacing selected functions in the SOM run-time library 
  9540. with application code. This chapter contains more advanced topics describing 
  9541. how to customize the following aspects of SOM behavior: memory management, 
  9542. dynamic class loading and unloading, character output, error handling, and 
  9543. method resolution. Information on customizing Distributed SOM is provided in 
  9544. Chapter 6. 
  9545.  
  9546. The memory management functions used by the SOM run-time environment are a 
  9547. subset of those supplied in the ANSI C standard library. They have the same 
  9548. calling interface and return the equivalent types of results as their ANSI C 
  9549. counterparts, but include some supplemental error checking. Errors detected in 
  9550. these functions result in the invocation of the error-handling function to 
  9551. which SOMError points. 
  9552.  
  9553. The correspondence between the SOM memory-management function variables and 
  9554. their ANSI standard library equivalents is given in the table below. 
  9555.  
  9556. Memory-Management Functions 
  9557.  
  9558. ΓöîΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÉ
  9559. Γöé SOM FUNCTION   Γöé ANSI STANDARD C Γöé RETURN TYPE  Γöé ARGUMENT TYPES   Γöé
  9560. Γöé VARIABLE     Γöé LIBRARY FUNC-  Γöé        Γöé           Γöé
  9561. Γöé         Γöé TION       Γöé        Γöé           Γöé
  9562. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  9563. Γöé SOMCalloc    Γöé calloc( )    Γöé somToken   Γöé size_t, size_t   Γöé
  9564. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  9565. Γöé SOMFree     Γöé free( )     Γöé void     Γöé somToken      Γöé
  9566. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  9567. Γöé SOMMalloc    Γöé malloc( )    Γöé somToken   Γöé size_t       Γöé
  9568. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  9569. Γöé SOMRealloc    Γöé realloc( )    Γöé somToken   Γöé somToken, size_t  Γöé
  9570. ΓööΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÿ
  9571.  
  9572. An application program can replace SOM's memory management functions with its 
  9573. own memory management functions to change the way SOM allocates memory (for 
  9574. example, to perform all memory allocations as suballocations in a shared memory 
  9575. heap). This replacement is possible because SOMCalloc, SOMMalloc, SOMRealloc, 
  9576. and SOMFree are actually global variables that point to SOM's default memory 
  9577. management functions, rather than being the names of the functions themselves. 
  9578. Thus, an application program can replace SOM's default memory management 
  9579. functions by assigning the entry-point address of the user-defined memory 
  9580. management function to the appropriate global variable. For example, to replace 
  9581. the default free procedure with the user-defined function MyFree (which must 
  9582. have the same signature as the ANSI C free function), an application program 
  9583. would require the following code: 
  9584.  
  9585. #include <som.h>
  9586. /* Define a replacement routine: */
  9587.  
  9588. #ifdef __OS2__                  /* not for SOM 3.0 */
  9589. #pragma linkage(myFree, system) /* not for SOM 3.0 */
  9590. #endif                          /* not for SOM 3.0 */
  9591.  
  9592. void SOMLINK myFree (somToken memPtr)
  9593. {
  9594.      (Customized code goes here)
  9595. }
  9596. ...
  9597. SOMFree = myFree;
  9598.  
  9599. Note:  In general, all of these routines should be replaced as a group. For 
  9600.        instance, if an application supplies a customized version of SOMMalloc, 
  9601.        it should also supply correponding SOMCalloc, SOMFree, and SOMRealloc 
  9602.        functions that conform to this same style of memory management. 
  9603.  
  9604.  
  9605. ΓòÉΓòÉΓòÉ 6.8. Customizing Class Loading and Unloading ΓòÉΓòÉΓòÉ
  9606.  
  9607. SOM uses three routines that manage the loading and unloading of class 
  9608. libraries (referred to here as DLLs). These routines are called by the 
  9609. SOMClassMgrObject  as it dynamically loads and registers classes. If 
  9610. appropriate, the rules that govern the loading and unloading of DLLs can be 
  9611. modified, by replacing these functions with alternative implementations. 
  9612.  
  9613.  
  9614. ΓòÉΓòÉΓòÉ 6.8.1. Customizing class initialization ΓòÉΓòÉΓòÉ
  9615.  
  9616. The SOMClassInitFuncName function has the following signature: 
  9617.  
  9618. string  (*SOMClassInitFuncName) ( ); 
  9619.  
  9620. This function returns the name of the function that will initialize (create 
  9621. class objects for) all of the classes that are packaged together in a single 
  9622. class library. (This function name applies to all class libraries loaded by the 
  9623. SOMClassMgrObject.) The SOM-supplied version of SOMClassInitFuncName returns 
  9624. the string " SOMInitModule".  The interface to the library initialization 
  9625. function is described under the topic "Creating a SOM Class Library" earlier in 
  9626. this chapter. 
  9627.  
  9628.  
  9629. ΓòÉΓòÉΓòÉ 6.8.2. Customizing DLL loading ΓòÉΓòÉΓòÉ
  9630.  
  9631. To dynamically load a SOM class, the SOMClassMgrObject  calls the function 
  9632. pointed to by the global variable SOMLoadModule to load the DLL containing the 
  9633. class. The reason for making public the SOMLoadModule function (and the 
  9634. following SOMDeleteModule function) is to reveal the boundary where SOM touches 
  9635. the operating system. Explicit invocation of these functions is never required. 
  9636. However, they are provided to allow class implementors to insert their own code 
  9637. between the operating system and SOM, if desired. The  SOMLoadModule function 
  9638. has the following signature: 
  9639.  
  9640.  long  (*SOMLoadModule)   ( string className, 
  9641.  
  9642.                                                       string fileName,
  9643.  
  9644.                                                      string functionName,
  9645.  
  9646.                                                      long majorVersion,
  9647.  
  9648.                                                      long minorVersion,
  9649.  
  9650.                                                      somToken *modHandle);
  9651.  
  9652.  This function is responsible for loading the DLL containing the SOM class 
  9653.  className and returning either the value zero (for success) or a nonzero 
  9654.  system-specific error code. The output argument modHandle is used to return a 
  9655.  token that can subsequently be used by the DLL-un loading routine (described 
  9656.  below) to unload the DLL. The default DLL-loading routine returns the DLL's 
  9657.  module handle in this argument. The remaining arguments are used as follows: 
  9658.  
  9659.  Argument                 Usage 
  9660.  
  9661.  fileName                 The file name of the DLL to be loaded, which can be 
  9662.                           either a simple name or a full path name. 
  9663.  
  9664.  functionName             The name of the routine to be called after the DLL is 
  9665.                           successfully loaded by the SOMClassMgrObject. This 
  9666.                           routine is responsible for creating the class objects 
  9667.                           for the class(es) contained in the DLL. Typically, 
  9668.                           this argument has the value "SOMInitModule", which is 
  9669.                           obtained from the function SOMClassInitFuncName 
  9670.                           described above. If no SOMInitModule entry exists in 
  9671.                           the DLL, the default DLL-loading routine looks in the 
  9672.                           DLL for a procedure with the name <className>NewClass 
  9673.                           instead. If neither entry point can be found, the 
  9674.                           default DLL-loading routine fails. 
  9675.  
  9676.  majorVersion             The major version number to be passed to the class 
  9677.                           initialization function in the DLL (specified by the 
  9678.                           functionName argument). 
  9679.  
  9680.  minorVersion             The minor version number to be passed to the class 
  9681.                           initialization function in the DLL (specified by the 
  9682.                           FunctionName argument). 
  9683.  
  9684.  An application program can replace the default DLL-loading routine by 
  9685.  assigning the entry point address of the new DLL-loading function (such as 
  9686.  MyLoadModule) to the global variable SOMLoadModule, as follows: 
  9687.  
  9688.   #include <som.h>
  9689.   /* Define a replacement routine: */
  9690.   long myLoadModule (string className, string fileName,
  9691.                      string functionName, long majorVersion,
  9692.                      long minorVersion, somToken *modHandle)
  9693.   {
  9694.        (Customized code goes here)
  9695.   }
  9696.   ...
  9697.   SOMLoadModule = MyLoadModule;
  9698.  
  9699.  
  9700. ΓòÉΓòÉΓòÉ 6.8.3. Customizing DLL unloading ΓòÉΓòÉΓòÉ
  9701.  
  9702. To unload a SOM class, the SOMClassMgrObject calls the function pointed to by 
  9703. the global variable SOMDeleteModule. The SOMDeleteModule function has the 
  9704. following signature: 
  9705.  
  9706. long  (*SOMDeleteModule)  (in somToken modHandle); 
  9707.  
  9708. This function is responsible for unloading the DLL designated by the modHandle 
  9709. parameter and returning either zero (for success) or a nonzero system-specific 
  9710. error code. The parameter modHandle contains the value returned by the DLL 
  9711. loading routine (described above) when the DLL was loaded. 
  9712.  
  9713. An application program can replace the default DLL-unloading routine by 
  9714. assigning the entry point address of the new DLL-unloading function (such as, 
  9715. MyDeleteModule) to the global variable SOMDeleteModule, as follows: 
  9716.  
  9717. #include <som.h>
  9718. /* Define a replacement routine: */
  9719. long myDeleteModule (somToken modHandle)
  9720. {
  9721.      (Customized code goes here)
  9722. }
  9723. ...
  9724. SOMDeleteModule = MyDeleteModule;
  9725.  
  9726.  
  9727. ΓòÉΓòÉΓòÉ 6.9. Customizing Character Output ΓòÉΓòÉΓòÉ
  9728.  
  9729. The SOM character-output function is invoked by all of the SOM error-handling 
  9730. and debugging macros whenever a character must be generated (see "Debugging" 
  9731. and "Exceptions and error handling" in Using SOM Classes in Client Programs, 
  9732. "Using SOM Classes in Client Programs"). The default character-output routine, 
  9733. pointed to by the global variable SOMOutCharRoutine, simply writes the 
  9734. character to "stdout", then returns 1 if successful, or 0 otherwise. 
  9735.  
  9736. For convenience, SOMOutCharRoutine is supplemented by the somSetOutChar 
  9737. function.  The somSetOutChar function enables each task to have a customized 
  9738. character output routine, thus it is often preferred for changing the output 
  9739. routine called by somPrintf (because SOMOutChrRoutine would remain in effect 
  9740. for subsequent tasks).  On Windows, the somSetOutChar function is required 
  9741. (rather than SOMOutCharRoutine); it is optional on other operating systems. 
  9742.  
  9743. An application programmer might wish to supply a customized replacement routine 
  9744. to: 
  9745.  
  9746.      Direct the output to stderr, 
  9747.  
  9748.      Record the output in a log file, 
  9749.  
  9750.      Collect characters and handle them in larger chunks, 
  9751.  
  9752.      Send the output to a window to display it, 
  9753.  
  9754.      Place the output in a clipboard, or 
  9755.  
  9756.      Some combination of these. 
  9757.  
  9758.  With SOMOutCharRoutine, an application program would use code similar to the 
  9759.  following to install the replacement routine: 
  9760.  
  9761.   #include <som.h>
  9762.   #pragma linkage(myCharacterOutputRoutine, system)
  9763.   /* Define a replacement routine: */
  9764.   int SOMLINK myCharacterOutputRoutine (char c)
  9765.   {
  9766.        (Customized code goes here)
  9767.   }
  9768.  
  9769.   /* After the next stmt all output */
  9770.   /* will be sent to the new routine   */
  9771.   SOMOutCharRoutine = myCharacterOutputRoutine;
  9772.  
  9773.  With somSetOutChar, an application program would use code similar to the 
  9774.  following to install the replacement routine: 
  9775.  
  9776.   #include <som.h>
  9777.   static int irOutChar(char c);
  9778.  
  9779.   static int irOutChar(char c)
  9780.   {
  9781.       (Customized code goes here)
  9782.   }
  9783.  
  9784.   main (...)
  9785.   {
  9786.       ...
  9787.   somSetOutChar((somTD_SOMOutCharRoutine *) irOutChar);
  9788.   }
  9789.  
  9790.  
  9791. ΓòÉΓòÉΓòÉ 6.10. Customizing Error Handling ΓòÉΓòÉΓòÉ
  9792.  
  9793. When an error occurs within any of the SOM-supplied methods or functions, an 
  9794. error-handling procedure is invoked. The default error-handling procedure 
  9795. supplied by SOM, pointed to by the global variable SOMError, has the following 
  9796. signature: 
  9797.  
  9798. void  (*SOMError) (int errorCode ,  string fileName,  int lineNum ); 
  9799.  
  9800. The default error-handling procedure inspects the  errorCode  argument and 
  9801. takes appropriate action, depending on the last decimal digit of errorCode (see 
  9802. "Exceptions and error handling" in Using SOM Classes in Client Programs for a 
  9803. discussion of error classifications). In the default error handler, fatal 
  9804. errors terminate the current process. The remaining two arguments (fileName and 
  9805. lineNum), which indicate the name of the file and the line number within the 
  9806. file where the error occurred, are used to produce an error message. 
  9807.  
  9808. An application programmer might wish to replace the default error handler with 
  9809. a customized error-handling routine to: 
  9810.  
  9811.      Record errors in a way appropriate to the particular application, 
  9812.  
  9813.      Inform the user through the application's user interface, 
  9814.  
  9815.      Attempt application-level recovery by restarting at a known point, or 
  9816.  
  9817.      Shut down the application. 
  9818.  
  9819.  An application program would use code similar to the following to install the 
  9820.  replacement routine: 
  9821.  
  9822.   #include <som.h>
  9823.   /* Define a replacement routine: */
  9824.   void myErrorHandler (int errorCode, string fileName, int lineNum)
  9825.   {
  9826.        (Customized code goes here)
  9827.   }
  9828.   ...
  9829.   /* After the next stmt all errors */
  9830.   /* will be handled by the new routine   */
  9831.   SOMError = myErrorHandler;
  9832.  
  9833.  When any error condition originates within the classes supplied with SOM, SOM 
  9834.  is left in an internally consistent state. If appropriate, an application 
  9835.  program can trap errors with a customized error-handling procedure and then 
  9836.  resume with other processing. Application programmers should be aware, 
  9837.  however, that all methods within the SOM run-time library behave atomically. 
  9838.  That is, they either succeed or fail; but if they fail, partial effects are 
  9839.  undone wherever possible. This is done so that all SOM methods remain usable 
  9840.  and can be re-executed following an error. 
  9841.  
  9842.  
  9843. ΓòÉΓòÉΓòÉ 7. Distributed SOM (DSOM) ΓòÉΓòÉΓòÉ
  9844.  
  9845. Note:  The SOMobject Base Toolkit provides the capability for implementing 
  9846.        Workstation Distributed System Object Module (DSOM) (distribution among 
  9847.        processes on a single machine). 
  9848.  
  9849. Implementing an application that is distributed across a network of machines 
  9850. requires Workgroup DSOM, which is not available. 
  9851.  
  9852.  The following subjects are discussed in this section: 
  9853.  
  9854.      A Simple DSOM Example 
  9855.      Basic Client Programming 
  9856.      Basic Server Programming 
  9857.      Implementing Classes 
  9858.      Configuring DSOM Applications 
  9859.      Running DSOM Applications 
  9860.      DSOM as a CORBA-compliant Object Request Broker 
  9861.      Advanced Topics 
  9862.      Error Reporting and Troubleshooting 
  9863.      Limitations 
  9864.  
  9865.  
  9866. ΓòÉΓòÉΓòÉ 7.1. What is Distributed SOM? ΓòÉΓòÉΓòÉ
  9867.  
  9868. Whereas the power of SOM technology comes from the fact that SOM insulates the 
  9869. client of an object from the object's implementation, the power of DSOM lies in 
  9870. the fact that DSOM insulates the client of an object from the object's 
  9871. location. 
  9872.  
  9873. Distributed SOM (or DSOM) provides a framework that allows application programs 
  9874. to access objects across address spaces. That is, application programs can 
  9875. access objects in other processes. 
  9876.  
  9877. This version of DSOM currently supports distribution among processes on the 
  9878. same machine (referred to as Workstation DSOM). 
  9879.  
  9880. DSOM runs on the AIX (Release 3.2.5 and above), OS/2 (Release 2.0 and above), 
  9881. Windows 95, and Windows NT (Version 3.51) operating systems. A Workstation DSOM 
  9882. application can run on a machine in either environment using core capabilities 
  9883. of the SOMobjects system. Future releases of DSOM may support large, 
  9884. enterprise-wide networks. 
  9885.  
  9886. This version of DSOM can be viewed as a System Object Model extension that 
  9887. allows a program to invoke methods on SOM objects in other processes. Other 
  9888. versions of SOM, such as the AIX and OS/2 versions, support Workgroup DSOM. 
  9889. They can be viewed as a SOM extension also. In addition they can be viewed as 
  9890. an Object Request Broker (ORB); that is, a standardized "transport" for 
  9891. distributed object interaction. In this respect, DSOM complies with the Common 
  9892. Object Request Broker Architecture (CORBA) specification, published by the 
  9893. Object Management Group (OMG) and x/Open. 
  9894.  
  9895. This chapter describes DSOM from both perspectives. 
  9896.  
  9897. Note:  Portions of this discussion of DSOM pertain to Workgroup DSOM only and 
  9898.        are not supported by this Windows version of the product. References to 
  9899.        topics such as ORB, CORBA, and selection of servers do not apply to this 
  9900.        version. These discussions are presented here to provide a more complete 
  9901.        understanding of DSOM in general. 
  9902.  
  9903.  
  9904. ΓòÉΓòÉΓòÉ 7.2. DSOM features ΓòÉΓòÉΓòÉ
  9905.  
  9906. Here is a quick summary of some of DSOM's more important features: 
  9907.  
  9908.      Uses the standard SOM Compiler, Interface Repository, language bindings, 
  9909.       and class libraries.  Thus, DSOM provides a growth path for 
  9910.       non-distributed SOM applications. 
  9911.  
  9912.      Allows an application program to access local objects. 
  9913.  
  9914.      Uses existing interprocess communication (IPC) facilities for Workstation 
  9915.       communication. 
  9916.  
  9917.      Provides support for writing multi-threaded servers and event-driven 
  9918.       programs. 
  9919.  
  9920.      Provides a default object server program, which can be easily used to 
  9921.       create SOM objects and make those objects accessible to one or more 
  9922.       client programs. If the default server program is used, SOM class 
  9923.       libraries are loaded upon demand, so no server programming or compiling 
  9924.       is necessary. 
  9925.  
  9926.      Complies with the CORBA 1.1 specification, which is important for 
  9927.       application portability. 
  9928.  
  9929.  
  9930. ΓòÉΓòÉΓòÉ 7.3. When to use DSOM ΓòÉΓòÉΓòÉ
  9931.  
  9932. DSOM should be used for those applications that require sharing of objects 
  9933. among multiple programs. The object actually exists in only one process (this 
  9934. process is known as the object's server); the other processes (known as 
  9935. clients) access the object through remote method invocations, made transparent 
  9936. by DSOM. 
  9937.  
  9938. DSOM should also be used for applications that require objects to be isolated 
  9939. from the main program. This is usually done in cases where reliability is a 
  9940. concern, either to protect the object from failures in other parts of the 
  9941. application, or to protect the application from an object. 
  9942.  
  9943.  
  9944. ΓòÉΓòÉΓòÉ 7.4. Chapter Outline ΓòÉΓòÉΓòÉ
  9945.  
  9946. Briefly, this section covers the following subjects: 
  9947.  
  9948.      Tutorial example 
  9949.      Programming DSOM applications 
  9950.      Configuring DSOM applications 
  9951.      Running DSOM applications 
  9952.      DSOM and CORBA 
  9953.      Advanced topics 
  9954.      Error reporting and troubleshooting 
  9955.  
  9956.  
  9957. ΓòÉΓòÉΓòÉ 7.5. Tutorial example ΓòÉΓòÉΓòÉ
  9958.  
  9959. First, a complete example shows how an existing SOM class implementation (a 
  9960. "stack") can be used with DSOM to create a distributed "Stack" application. 
  9961. Using the "Stack" example as a backdrop, the basic DSOM interfaces are 
  9962. introduced. 
  9963.  
  9964.  
  9965. ΓòÉΓòÉΓòÉ 7.6. Programming DSOM applications ΓòÉΓòÉΓòÉ
  9966.  
  9967. All DSOM applications involve three kinds of programming: 
  9968.  
  9969.      Client programming:  writing code that uses objects; 
  9970.  
  9971.      Server programming:  writing code that implements and manages objects. 
  9972.  
  9973.      Implementing classes:  writing code that implements objects. 
  9974.  
  9975.  Three sections ("Basic Client Programming", "Basic Server Programming", and 
  9976.  Implementing Classes") describe how to create DSOM applications from these 
  9977.  three points of view. In turn, the structure and services of the relevant DSOM 
  9978.  run-time environment are explained. 
  9979.  
  9980.  Note:  The three sections are presented in the order above to aid in their 
  9981.  explanation. However, the actual programming tasks are likely to be performed 
  9982.  in the opposite order. 
  9983.  
  9984.  Additional examples are provided in these sections to illustrate DSOM 
  9985.  services. 
  9986.  
  9987.  
  9988. ΓòÉΓòÉΓòÉ 7.7. Configuring DSOM applications ΓòÉΓòÉΓòÉ
  9989.  
  9990. The section "Configuring DSOM Applications" explains what is necessary to set 
  9991. up a DSOM application, once the application has been built. 
  9992.  
  9993.  
  9994. ΓòÉΓòÉΓòÉ 7.8. Running DSOM applications ΓòÉΓòÉΓòÉ
  9995.  
  9996. The section "Running DSOM Applications" explains what is necessary to run a 
  9997. DSOM application, once it has been built and configured. 
  9998.  
  9999.  
  10000. ΓòÉΓòÉΓòÉ 7.9. DSOM and CORBA ΓòÉΓòÉΓòÉ
  10001.  
  10002. Those readers interested in using DSOM as a CORBA-compliant ORB should read the 
  10003. section entitled "DSOM as a CORBA compliant Object Broker." That section 
  10004. answers the question: How are CORBA concepts implemented in DSOM? 
  10005.  
  10006.  
  10007. ΓòÉΓòÉΓòÉ 7.10. Advanced topics ΓòÉΓòÉΓòÉ
  10008.  
  10009. The section on "Advanced Topics" covers the following: 
  10010.  
  10011.    1. "Peer versus client/server processes" demonstrates how peer-to-peer 
  10012.       object interactions are supported in DSOM. 
  10013.  
  10014.    2. "Dynamic Invocation Interface" details DSOM support for the CORBA dynamic 
  10015.       invocation interface to dynamically build and invoke methods on remote 
  10016.       objects. 
  10017.  
  10018.    3. "Creating user-supplied proxy classes" describes how to override proxy 
  10019.       generation by the DSOM run time and, instead, install a proxy object 
  10020.       supplied by the user. 
  10021.  
  10022.    4. "Customizing the default base proxy class"discusses how the 
  10023.       SOMDClientProxy class can be subclassed to define a customized base class 
  10024.       that DSOM will use during dynamic proxy-class generation. 
  10025.  
  10026.  
  10027. ΓòÉΓòÉΓòÉ 7.11. Error reporting and troubleshooting ΓòÉΓòÉΓòÉ
  10028.  
  10029. The section on "Error Reporting and Troubleshooting" discusses facilities to 
  10030. aid in problem diagnosis. 
  10031.  
  10032.  
  10033. ΓòÉΓòÉΓòÉ 7.12. A Simple DSOM Example ΓòÉΓòÉΓòÉ
  10034.  
  10035. A sample "Stack" application is presented in this section as a tutorial 
  10036. introduction to DSOM. It demonstrates that, for simple examples like a "Stack", 
  10037. after very little work, the class can be used to implement distributed objects 
  10038. that are accessed remotely. The example first presents the "Stack" application 
  10039. components and the steps that the implementer must perform before the 
  10040. application can be run, and then describes the run time activity that results 
  10041. from executing the application. This run-time scenario introduces several of 
  10042. the key architectural components of the DSOM run-time environment. 
  10043.  
  10044. The source code for this example is provided with the DSOM samples in the 
  10045. SOMobjects Developer Toolkit. 
  10046.  
  10047.  
  10048. ΓòÉΓòÉΓòÉ 7.12.1. The "Stack" interface ΓòÉΓòÉΓòÉ
  10049.  
  10050. The example starts with the assumption that the class implementer has 
  10051. successfully built a SOM class library DLL, called "stack.dll", in the manner 
  10052. described in Section 5.6, "Creating a SOM Class Library," of Chapter 5, 
  10053. "Implementing Classes in SOM." The DLL implements the following IDL interface. 
  10054.  
  10055. #include <somobj.idl>
  10056.  
  10057. interface Stack: SOMObject
  10058. {
  10059.     const long stackSize = 10;
  10060.     exception STACK_OVERFLOW{};
  10061.     exception STACK_UNDERFLOW{};
  10062.     boolean full();
  10063.     boolean empty();
  10064.     long top() raises(STACK_UNDERFLOW);
  10065.     long pop() raises(STACK_UNDERFLOW);
  10066.     void push(in long element) raises(STACK_OVERFLOW);
  10067.  
  10068.     #ifdef __SOMIDL__
  10069.     implementation
  10070.     {
  10071.       releaseorder: full, empty, top, pop, push;
  10072.       somDefaultInit: override;
  10073.       long stackTop;                  // top of stack index
  10074.       long stackValues[stackSize];    // stack elements
  10075.       dllname = "stack.dll";
  10076.     };
  10077.     #endif
  10078. };
  10079.  
  10080. This DLL could have been built without the knowledge that it would ever be 
  10081. accessed remotely (that is, built following the procedures in Chapter 5). Note, 
  10082. however, that some DLLs may require changes in the way their classes pass 
  10083. arguments and manage memory, in order to be used by remote clients (see the 
  10084. topic "Implementation Constraints" in section 6.5, "Implementing Classes"). 
  10085.  
  10086.  
  10087. ΓòÉΓòÉΓòÉ 7.12.2. The "Stack" class implementation ΓòÉΓòÉΓòÉ
  10088.  
  10089. #define Stack_Class_Source
  10090. #include <stack.ih>
  10091.  
  10092. SOM_Scope boolean  SOMLINK full(Stack somSelf, Environment *ev)
  10093. {
  10094.     StackData *somThis = StackGetData(somSelf);
  10095.     StackMethodDebug("Stack","full");
  10096.  
  10097.     /* Return TRUE if stack is full. */
  10098.     return (_stackTop == stackSize);
  10099. }
  10100.  
  10101. SOM_Scope boolean  SOMLINK empty(Stack somSelf, Environment *ev)
  10102. {
  10103.     StackData *somThis = StackGetData(somSelf);
  10104.     StackMethodDebug("Stack","empty");
  10105.  
  10106.     /* Return TRUE if stack is empty.*/
  10107.     return (_stackTop == 0);
  10108. }
  10109.  
  10110. SOM_Scope long  SOMLINK top(Stack somSelf, Environment *ev)
  10111. {
  10112.     StackData *somThis = StackGetData(somSelf);
  10113.     StackMethodDebug("Stack","top");
  10114.  
  10115.     if (_stackTop > 0)
  10116.     {
  10117.        /* Return top element in stack without removing it from
  10118.         * the stack.
  10119.         */
  10120.        return (_stackValues[_stackTop-1]);
  10121.     }
  10122.     else
  10123.     {
  10124.        somSetException(ev, USER_EXCEPTION,
  10125.                        ex_STACK_UNDERFLOW, NULL);
  10126.        return (-1L);
  10127.     }
  10128. }
  10129.  
  10130. SOM_Scope long  SOMLINK pop(Stack somSelf, Environment *ev)
  10131. {
  10132.     StackData *somThis = StackGetData(somSelf);
  10133.     StackMethodDebug("Stack","pop");
  10134.  
  10135.     if (_stackTop > 0)
  10136.     {
  10137.        /* Return top element in stack and remove it from the
  10138.         * stack.
  10139.         */
  10140.        _stackTop--;
  10141.        return (_stackValues[_stackTop]);
  10142.     }
  10143.     else
  10144.     {
  10145.        somSetException(ev, USER_EXCEPTION,
  10146.                        ex_STACK_UNDERFLOW, NULL);
  10147.        return (-1L);
  10148.     }
  10149. }
  10150.  
  10151. SOM_Scope void  SOMLINK push(Stack somSelf,
  10152.                              Environment *ev, long el)
  10153. {
  10154.     StackData *somThis = StackGetData(somSelf);
  10155.     StackMethodDebug("Stack","push");
  10156.  
  10157.     if (_stackTop < stackSize)
  10158.     {
  10159.       /* Add element to top of the stack. */
  10160.       _stackValues[_stackTop] = el;
  10161.       _stackTop++;
  10162.     }
  10163.     else
  10164.     {
  10165.        somSetException(ev, USER_EXCEPTION,
  10166.                        ex_STACK_OVERFLOW, NULL);
  10167.     }
  10168. }
  10169.  
  10170. SOM_Scope void  SOMLINK somDefaultInit(Stack somSelf,
  10171.                                        somInitCtrl* ctrl)
  10172. {
  10173.     StackData *somThis;
  10174.     somInitCtrl globalCtrl;
  10175.     somBooleanVector myMask;
  10176.     StackMethodDebug("Stack","somDefaultInit");
  10177.     Stack_BeginInitializer_somDefaultInit;
  10178.  
  10179.     Stack_Init_SOMObject_somDefaultInit(somSelf, ctrl);
  10180.  
  10181.     /* stackTop is index into stackValues for next pushed
  10182.      * stack element.
  10183.      * stackValues[0..(stackSize-1)] holds stack elements.
  10184.      */
  10185.     _stackTop = 0;
  10186. }
  10187.  
  10188.  
  10189. ΓòÉΓòÉΓòÉ 7.12.3. Client program using a local stack ΓòÉΓòÉΓòÉ
  10190.  
  10191. A simple client program written to use a local "Stack" object is displayed 
  10192. below. This C program is shown so that the differences between a local and 
  10193. remote client program can be highlighted. 
  10194.  
  10195. #include <stack.h>
  10196.  
  10197. boolean OperationOK(Environment *ev);
  10198.  
  10199. int main(int argc, char *argv[])
  10200. {
  10201.   Environment ev;
  10202.   Stack stk;
  10203.   long num = 100;
  10204.  
  10205.   SOM_InitEnvironment(&ev);
  10206.  
  10207.   /* The StackNewClass invocation is optional and unnecessary
  10208.    * in the client program when the class object is created in
  10209.    * the SOMInitModule function that is invoked during DLL
  10210.    * initialization.
  10211.    */
  10212.   StackNewClass(Stack_MajorVersion, Stack_MinorVersion);
  10213.   stk = StackNew();
  10214.  
  10215.   /* Verify successful object creation */
  10216.   if ( stk != NULL )
  10217.   {
  10218.      while ( !_full(stk, &ev) )
  10219.      {
  10220.         _push(stk, &ev, num);
  10221.         somPrintf("Top: %d\n", _top(stk, &ev));
  10222.         num += 100;
  10223.      }
  10224.  
  10225.      /* Test stack overflow exception */
  10226.      _push(stk, &ev, num);
  10227.      OperationOK(&ev);
  10228.  
  10229.      while ( !_empty(stk, &ev) )
  10230.      {
  10231.         somPrintf("Pop: %d\n", _pop(stk, &ev));
  10232.      }
  10233.  
  10234.      /* Test stack underflow exception */
  10235.      somPrintf("Top Underflow: %d\n", _top(stk, &ev));
  10236.      OperationOK(&ev);
  10237.      somPrintf("Pop Underflow: %d\n", _pop(stk, &ev));
  10238.      OperationOK(&ev);
  10239.  
  10240.      _push(stk, &ev, -10000);
  10241.      somPrintf("Top: %d\n", _top(stk, &ev));
  10242.      somPrintf("Pop: %d\n", _top(stk, &ev));
  10243.  
  10244.      _somFree(stk);
  10245.   }
  10246.  
  10247.   SOM_UninitEnvironment(&ev);
  10248.  
  10249.   return(0);
  10250. }
  10251.  
  10252. boolean OperationOK(Environment *ev)
  10253. {
  10254.    char *exID;
  10255.  
  10256.    switch (ev->_major)
  10257.    {
  10258.      case SYSTEM_EXCEPTION:
  10259.        exID = somExceptionId(ev);
  10260.        somPrintf("System exception: %s\n", exID);
  10261.        somdExceptionFree(ev);
  10262.        return (FALSE);
  10263.  
  10264.      case USER_EXCEPTION:
  10265.        exID = somExceptionId(ev);
  10266.        somPrintf("User exception: %s\n", exID);
  10267.        somdExceptionFree(ev);
  10268.        return (FALSE);
  10269.  
  10270.      case NO_EXCEPTION:
  10271.        return (TRUE);
  10272.  
  10273.      default:
  10274.        somPrintf("Invalid exception type in Environment.\n");
  10275.        somdExceptionFree(ev);
  10276.        return (FALSE);
  10277.    }
  10278. }
  10279.  
  10280.  
  10281. ΓòÉΓòÉΓòÉ 7.12.4. Client program using a remote stack ΓòÉΓòÉΓòÉ
  10282.  
  10283. The preceding program has been rewritten below showing how DSOM can be used to 
  10284. create and access a "Stack" object somewhere in the system. The exact location 
  10285. of the object does not matter to the application; it just wants a "Stack" 
  10286. object. Note that the stack operations of the two programs are identical. The 
  10287. main differences lie in stack creation and destruction, as highlighted below. 
  10288. (Also see "Memory management" later for more information on allocating and 
  10289. freeing memory.) 
  10290.  
  10291. #include <somd.h>
  10292. #include <stack.h>
  10293.  
  10294. int main(int argc, char *argv])
  10295. {
  10296.   Environment ev;
  10297.   Stack stk;
  10298.   long num = 100;
  10299.  
  10300.   SOM_InitEnvironment(&ev);
  10301.   SOMD_Init(&ev);
  10302.  
  10303. size='auto'.
  10304.   /* The StackNewClass invocation is optional and unnecessary
  10305.    * in the client program when the class object is created in
  10306.    * the SOMInitModule function that is invoked during DLL
  10307.    * initialization.
  10308.    */
  10309.   StackNewClass (Stack_MajorVersion, Stack_MinorVersion);
  10310.   stk = _somdNewObject(SOMD_ObjectMgr, &ev, "Stack", "");
  10311.  
  10312.   /* Verify successful object creation */
  10313.   if ( OperationOK(&ev) )
  10314.   {
  10315.      while ( !_full(stk, &ev) )
  10316.      {
  10317.         _push(stk, &ev, num);
  10318.         somPrintf("Top: %d\n", _top(stk, &ev));
  10319.         num += 100;
  10320.      }
  10321.  
  10322.      /* Test stack overflow exception */
  10323.      _push(stk, &ev, num);
  10324.      OperationOK(&ev);
  10325.  
  10326.      while ( !_empty(stk, &ev) )
  10327.      {
  10328.         somPrintf("Pop: %d\n", _pop(stk, &ev));
  10329.      }
  10330.  
  10331.      /* Test stack underflow exception */
  10332.      somPrintf("Top Underflow: %d\n", _top(stk, &ev));
  10333.      OperationOK(&ev);
  10334.      somPrintf("Pop Underflow: %d\n", _pop(stk, &ev));
  10335.      OperationOK(&ev);
  10336.  
  10337.      _push(stk, &ev, -10000);
  10338.      somPrintf("Top: %d\n", _top(stk, &ev));
  10339.      somPrintf("Pop: %d\n", _top(stk, &ev));
  10340.  
  10341.      _somdDestroyObject(SOMD_ObjectMgr, &ev, stk);
  10342.  
  10343.      if ( OperationOK(&ev) )
  10344.      {
  10345.         somPrintf("Stack test successfully completed.\n");
  10346.      }
  10347.   }
  10348.   SOMD_Uninit(&ev);
  10349.   SOM_UninitEnvironment(&ev);
  10350.  
  10351.   return(0);
  10352. }
  10353.  
  10354. size='auto'.
  10355. boolean OperationOK(Environment *ev)
  10356. {
  10357.    char *exID;
  10358.  
  10359.    switch (ev->_major)
  10360.    {
  10361.      case SYSTEM_EXCEPTION:
  10362.        exID = somExceptionId(ev);
  10363.        somPrintf("System exception: %s\n", exID);
  10364.        somdExceptionFree(ev);
  10365.        return (FALSE);
  10366.  
  10367.      case USER_EXCEPTION:
  10368.        exID = somExceptionId(ev);
  10369.        somPrintf("User exception: %s\n", exID);
  10370.        somdExceptionFree(ev);
  10371.        return (FALSE);
  10372.  
  10373.      case NO_EXCEPTION:
  10374.        return (TRUE);
  10375.  
  10376.      default:
  10377.        somPrintf("Invalid exception type in Environment.\n");
  10378.        somdExceptionFree(ev);
  10379.        return (FALSE);
  10380.    }
  10381. }
  10382.  
  10383. Let's step through the differences. 
  10384.  
  10385. First, every DSOM program must include the file <somd.h> (when using C ++, 
  10386. <somd.xh>). This file defines constants, global variables, and run-time 
  10387. interfaces used by DSOM. Usually, this file is sufficient to establish all 
  10388. necessary DSOM definitions. 
  10389.  
  10390. Next, DSOM requires its own initialization call. 
  10391.  
  10392.         SOMD_Init(&ev);
  10393.  
  10394. The call to SOMD_Init initializes the DSOM run-time environment SOMD_Init must 
  10395. be called before any DSOM run-time calls are made. A side effect of calling 
  10396. SOMD_Init is that a run-time object, called the DSOM Object Manager, is 
  10397. created, and a pointer to it is stored in the global variable, SOMD_ObjectMgr, 
  10398. for programming convenience. The DSOM Object Manager provides basic run-time 
  10399. support for clients to find, create, destroy, and identify objects. The Object 
  10400. Manager is discussed in detail in the section entitled "Basic Client 
  10401. Programming." 
  10402.  
  10403. Next, the local stack creation statement, 
  10404.  
  10405.         stk = StackNew();
  10406. was replaced by 
  10407.  
  10408.  
  10409.         stk = _somdNewObject(SOMD_ObjectMgr, &ev, "Stack", "");
  10410.  
  10411. The call to somdNewObject asks the DSOM Object Manager (SOMD_ObjectMgr) to 
  10412. create a "Stack" object, wherever it can find an implementation of "Stack". 
  10413. (There are other methods with which one can request specific servers.) If no 
  10414. object could be created, NULL is returned, and an exception is raised. 
  10415. Otherwise, the object returned is a "Stack" proxy. 
  10416.  
  10417. A proxy is an object that is a local representative for a remote target object. 
  10418. A proxy inherits the target object's interface, so it responds to the same 
  10419. methods. Operations invoked on the proxy are not executed locally, but are 
  10420. forwarded to the "real" target object for execution. The client program always 
  10421. has a proxy for each remote target object on which it operates. 
  10422.  
  10423. From this point on, the client program treats the "Stack" proxy exactly as it 
  10424. would treat a local "Stack". The "Stack" proxy takes responsibility for 
  10425. forwarding requests to, and yielding results from, the remote "Stack". For 
  10426. example, 
  10427.  
  10428.         _push(stk,&ev,num);
  10429.  
  10430. causes a message representing the method call to be sent to the server process 
  10431. containing the remote object. The DSOM run-time in the server process decodes 
  10432. the message and invokes the method on the target object. The result (in this 
  10433. case, just an indication of completion) is then returned to the client process 
  10434. in a message. The DSOM run time in the client process decodes the result 
  10435. message and returns any result data to the caller. 
  10436.  
  10437. At the end of the original client program, the local "Stack" was destroyed by 
  10438. the statement, 
  10439.  
  10440.         _somFree(stk);
  10441.  
  10442. whereas, in the client program above, the "Stack" proxy and the remote "Stack" 
  10443. are destroyed by the statement, 
  10444.  
  10445.         _somdDestroyObject(SOMD_ObjectMgr, &ev, stk);
  10446.  
  10447. If the client only wants to release its use of the remote object (freeing the 
  10448. proxy) without destroying the remote object, it can call the somdReleaseObject 
  10449. method instead of somdDestroyObject. 
  10450.  
  10451. Finally, the client must shut down DSOM, so that any operating system resources 
  10452. acquired by DSOM for communications or process management can be returned: 
  10453.  
  10454.         SOMD_Uninit(&ev);
  10455. This call must be made at the end of every DSOM program. 
  10456.  
  10457.  
  10458. ΓòÉΓòÉΓòÉ 7.12.4.1. Using specific servers ΓòÉΓòÉΓòÉ
  10459.  
  10460. In DSOM, the process that manages a target object is called the object's 
  10461. server. Servers are implemented as programs that use SOM classes.  Server 
  10462. implementations are registered with DSOM in an Implementation Repository. The 
  10463. Implementation Repository is a database queried by clients in order to find 
  10464. desired servers, and queried by DSOM in order to activate those servers upon 
  10465. demand. 
  10466.  
  10467. The example above placed no constraints on the DSOM Object Manager as to where 
  10468. the remote "Stack" object should be created. The somdNewObject call creates a 
  10469. remote object of a specified class in an arbitrary server that implements that 
  10470. class. However, the DSOM Object Manager provides methods for finding specific 
  10471. servers. 
  10472.  
  10473. For example, the client program above can be modified slightly to find a 
  10474. specific server named "StackServer", which has already been registered in 
  10475. DSOM's Implementation Repository.  (Note that the programmer knew or discovered 
  10476. that the "StackServer" server implementation supports the "Stack" class.)  The 
  10477. highlighted lines below show the changes that were made: 
  10478.  
  10479. #include <somd.h>
  10480. #include <stack.h>
  10481.  
  10482. int main(int argc, char *argv[]) {
  10483.         Stack stk;
  10484.         Environment e;
  10485.         SOMDServer server;
  10486.  
  10487.         SOM_InitEnvironment(&e);
  10488.         SOMD_Init(&e);
  10489.  
  10490.         server =
  10491.           _somdFindServerByName(SOMD_ObjectMgr, &e, "StackServer");
  10492.         stk = _somdCreateObj(server, &e, "Stack", "");
  10493.  
  10494.         _push(stk,&e,100);
  10495.         _push(stk,&e,200);
  10496.         _pop(stk,&e);
  10497.         if (!_empty(stk,&e)) somPrintf("Top: %d\n", _top(stk,&e));
  10498.  
  10499.         _somdDeleteObj(server, &e, stk);
  10500.         _somdReleaseObject(SOMD_ObjectMgr, &e, stk);
  10501.         _somdReleaseObject(SOMD_ObjectMgr, &e, server);
  10502.         SOMD_Uninit(&e);
  10503.         SOM_UninitEnvironment(&e);
  10504.  
  10505.         return(0);
  10506. }
  10507.  
  10508. This version of the program replaces the somdNewObject operation with calls to 
  10509. somdFindServerByName and somdCreateObj. The somdFindServerByName method 
  10510. consults the Implementation Repository to find the DSOM server implementation 
  10511. whose name is "StackServer", and creates a server proxy, which provides a 
  10512. connection to that server. Every DSOM server process has a server object that 
  10513. defines methods to assist in the creation and management of objects in that 
  10514. server. Server objects must be instances of SOMDServer or one of its 
  10515. subclasses. The somdFindServerByName returns a proxy to the SOMDServer object 
  10516. in the named server. 
  10517.  
  10518. Once the client has the server proxy, it can create and destroy objects in that 
  10519. server. The somdCreateObj call creates an object of the class "Stack" in the 
  10520. server named "StackServer". 
  10521.  
  10522. To free the remote "Stack" object, the example shows a somdDeleteObj request on 
  10523. the stack object's server. Next, somdReleaseObject requests are made on the 
  10524. DSOM Object Manager, to free the stack proxy and the server proxy in the 
  10525. client. (Note that these three calls are equivalent to the somdDestroyObject 
  10526. call in the previous example.) 
  10527.  
  10528.  
  10529. ΓòÉΓòÉΓòÉ 7.12.5. A note on finding existing objects ΓòÉΓòÉΓòÉ
  10530.  
  10531. The two examples above show how clients can create a remote, transient object 
  10532. for their exclusive use. Clients may want to find and use objects that already 
  10533. exist. In that case, the calls to somdNewObject or somdCreateObj would be 
  10534. replaced with other "lookup" calls on some directory object that would take an 
  10535. object name or identifier and return a proxy to the remote object. 
  10536.  
  10537. The basic mechanisms that DSOM provides for naming and locating objects will be 
  10538. discussed in section  "Basic Client Programming." 
  10539.  
  10540.  
  10541. ΓòÉΓòÉΓòÉ 7.12.6. "Stack" server implementation ΓòÉΓòÉΓòÉ
  10542.  
  10543. A server consists of three parts. First, a "main" program, when run, provides 
  10544. an address space for the objects it manages, and one or more process "threads" 
  10545. that can execute method calls. (Windows 3.x and AIX currently do not have 
  10546. multi-thread support, while Windows 95, Windows NT, OS/2, and AIX 4.1 do.) 
  10547. Second, a server object, derived from the SOMDServer class, provides methods 
  10548. used to manage objects in the server process. Third, one or more class 
  10549. libraries provide object implementations. Usually these libraries are 
  10550. constructed as dynamically linked libraries (DLLs), so they can be loaded and 
  10551. linked by a server program dynamically. 
  10552.  
  10553. In this simple example, we can use the default DSOM server program, which is 
  10554. already compiled and linked. The default server behaves as a simple server, in 
  10555. that it simply receives and executes requests continuously. The default server 
  10556. creates its server object from the class, SOMDServer. The default server will 
  10557. load any class libraries it needs upon demand. 
  10558.  
  10559. The "Stack" class library, "stack.dll", can be used without modification in the 
  10560. distributed application. This is possible because the "Stack" class is "well 
  10561. formed"; in other words, there are no methods that implicitly assume the client 
  10562. and the object are in the same address space. 
  10563.  
  10564. Thus, by using the default server and the existing class library, a simple 
  10565. "Stack" server can be provided without any additional programming! 
  10566.  
  10567. An application may require more functionality in the server program or the 
  10568. server object than the default implementations provide. A discussion on how to 
  10569. implement server programs and server objects is found later in this chapter, in 
  10570. section 6.4, "Basic Server Programming". 
  10571.  
  10572.  
  10573. ΓòÉΓòÉΓòÉ 7.12.7. Compiling the application ΓòÉΓòÉΓòÉ
  10574.  
  10575. DSOM programs and class libraries are compiled and linked like any other SOM 
  10576. program or library. The header file "somd.h" (or for C++, "somd.xh") should be 
  10577. included in any source program that uses DSOM services. DSOM run-time calls can 
  10578. be resolved by linking with the SOMobjects Toolkit library: "somtk.lib" (The 
  10579. DSOM DLL(s)  - "somd.dll", will be loaded at run time.) For more information, 
  10580. see "Compiling and linking" in Chapter 3, "Using SOM classes in Client 
  10581. Programs," and the same topic in Chapter 5, "Implementing Classes in SOM." 
  10582.  
  10583.  
  10584. ΓòÉΓòÉΓòÉ 7.12.8. Installing the implementation ΓòÉΓòÉΓòÉ
  10585.  
  10586. Before the application can be run, certain environment variables must be set 
  10587. and the stack class and server implementations must be registered in the SOM 
  10588. Interface Repository and DSOM Implementation Repository. 
  10589.  
  10590.  
  10591. ΓòÉΓòÉΓòÉ 7.12.8.1. Setting environment variables ΓòÉΓòÉΓòÉ
  10592.  
  10593. Several environment variables are used by SOM and DSOM. These variables need to 
  10594. be set before registering the DSOM application in the Interface and 
  10595. Implementation Repositories. 
  10596.  
  10597. For this example, the following environment variables could be set as shown. A 
  10598. full description of the environment variables and how to set them is given in 
  10599. section 6.6, "Configuring DSOM." 
  10600.  
  10601.  
  10602. set USER=pat
  10603. set HOSTNAME=localhost
  10604. set SOMDDIR=c:\somddir
  10605. rem *** The following variables are usually set somenv.bat
  10606. rem ***
  10607. assuming "c:\som"
  10608. rem *** is the value of %SOMBASE% supplied by the user.
  10609. set SOMIR=c:\som\etc\som.ir:som.ir
  10610. set PATH=.;c:\som\lib;<previous PATH>
  10611.  
  10612. USER identifies the user of a DSOM client application. DSOM sends the USER ID 
  10613. with every remote method call, in case the remote object wishes to perform any 
  10614. access control checking. This is discussed later in the section "Basic Server 
  10615. Programming." 
  10616.  
  10617. HOSTNAME is always set to "localhost" for Workstation SOM. 
  10618.  
  10619. SOMIR gives a list of files that together constitute the Interface Repository. 
  10620. The IR is used by DSOM to guide the construction and interpretation of request 
  10621. messages. For DSOM, it is preferable to use full pathnames in the list of IR 
  10622. files, since the IR will be shared by several programs that may not all reside 
  10623. in the same directory. 
  10624.  
  10625. SOMDDIR gives the name of a directory used to store DSOM configuration files, 
  10626. including the Implementation Repository. 
  10627.  
  10628. PATH gives a list of directories where EXEs and DLLs can be found. 
  10629.  
  10630.  
  10631. ΓòÉΓòÉΓòÉ 7.12.8.2. Registering the class in the Interface Repository ΓòÉΓòÉΓòÉ
  10632.  
  10633. Before an object can be accessed remotely by DSOM, it is necessary to register 
  10634. the class's interface and implementation in the Interface Repository (IR). DSOM 
  10635. uses the interface information when transforming local method calls on proxies 
  10636. into request messages transmitted to remote objects. 
  10637.  
  10638. DSOM servers also consult the IR to find the name of the DLL for a dynamically 
  10639. loaded class. The DLL name for the "Stack" class must be specified using the 
  10640. dllname="stack.dll" modifier in the implementation statement of the "Stack" 
  10641. IDL. The Interface Repository is described in detail in Chapter 7, "The 
  10642. Interface Repository Framework." 
  10643.  
  10644. The IDL specification of "Stack" is compiled into the Interface Repository 
  10645. using the following command: 
  10646.  
  10647.         sc -u -sir stack.idl
  10648.  
  10649. When a class has not been compiled into the Interface Repository, DSOM will 
  10650. generate a run-time error when an attempt is made to invoke a method from that 
  10651. class. The error indicates that the method's descriptor was not found in the 
  10652. IR. 
  10653.  
  10654.  
  10655. ΓòÉΓòÉΓòÉ 7.12.8.3. Registering the server in the Implementation Repository ΓòÉΓòÉΓòÉ
  10656.  
  10657. It is necessary to register a description of a server's implementation in the 
  10658. Implementation Repository. DSOM uses this information to assist clients in 
  10659. finding servers, and in activating server processes upon demand. 
  10660.  
  10661. For this example, where the default server is used, we need only to identify 
  10662. the server's name, and the class that the server implements. This is 
  10663. accomplished using the regimpl utility discussed in section 6.6, "Configuring 
  10664. DSOM Applications". The following commands define a default server, named 
  10665. "StackServer", which supports the Stack class: 
  10666.  
  10667.         regimpl -A -i StackServer
  10668.         regimpl -a -i StackServer -c Stack
  10669.  
  10670.  
  10671. ΓòÉΓòÉΓòÉ 7.12.9. Running the application ΓòÉΓòÉΓòÉ
  10672.  
  10673. This section discusses: 
  10674.  
  10675.      Starting the DSOM daemon 
  10676.      Running the client 
  10677.  
  10678.  Starting the DSOM daemon 
  10679.  
  10680.  Before running a DSOM application, the DSOM daemon, somdd, must be started. 
  10681.  
  10682.      The daemon can be started manually from the command line, or it could be 
  10683.       started automatically from a start-up script run at boot time. It may be 
  10684.       run in the background with the commands start somdd (The somdd program 
  10685.       requires no parameters. An optional -q parameter can be used to set 
  10686.       "quiet" mode, to suppress messages.) 
  10687.  
  10688.       The somdd daemon is responsible for establishing a "binding" (that is, a 
  10689.       connection) between a client process and a server.  It will activate the 
  10690.       desired server automatically, if necessary. 
  10691.  
  10692.  Running the client 
  10693.  
  10694.  Once the DSOM daemon is running, the application may be started. This is 
  10695.  accomplished by running the client program. If the StackServer is not running, 
  10696.  it will be started automatically by the DSOM daemon when the client attempts 
  10697.  to invoke a method on one of its objects. After the client program ends, the 
  10698.  server will continue to run, accepting connections from new clients. To 
  10699.  terminate the server, give its console window focus and press ctrl-c. 
  10700.  
  10701.  
  10702. ΓòÉΓòÉΓòÉ 7.12.10. "Stack" example run-time scenario ΓòÉΓòÉΓòÉ
  10703.  
  10704. The following scenario steps through the actions taken by the DSOM run time in 
  10705. response to each line of code in the second "Stack" client program presented 
  10706. above. The illustration following the scenario shows the processes, and the 
  10707. objects within them, that participate in these actions. 
  10708.  
  10709.      Initialize an environment for error passing: 
  10710.  
  10711.             SOM_InitEnvironment(&e);
  10712.  
  10713.      Initialize DSOM: 
  10714.  
  10715.             SOMD_Init(&e);
  10716.  
  10717.  This causes the creation of the DSOM Object Manager (with SOMDObjectMgr 
  10718.  interface). The global variable SOMD_ObjectMgr points to this object. 
  10719.  
  10720.      Initialize "Stack" class object: 
  10721.  
  10722.             StackNewClass(Stack_MajorVersion, Stack_MinorVersion);
  10723.  
  10724.      Find the "StackServer" implementation and assign its proxy to the 
  10725.       variable server: 
  10726.  
  10727.             server = _somdFindServerByName(SOMD_ObjectMgr, &e, "StackServer");
  10728.  
  10729.  This causes the creation of the server proxy object in the client process. 
  10730.  Proxy objects are shown as shaded circles. Note that the "real" server object 
  10731.  in the server process is not created at this time. In fact, the server process 
  10732.  has not yet been started. 
  10733.  
  10734.      Ask the server object to create a "Stack" and assign "Stack" proxy to 
  10735.       variable stack. 
  10736.  
  10737.             stk = _somdCreateObj(server, &e, "Stack", "");
  10738.  
  10739.  This causes somdd, the DSOM daemon (which is already running) to activate the 
  10740.  stack server process (by starting the "generic" server program). The stack 
  10741.  server process, upon activation, creates the "real" SOMDServer object in the 
  10742.  server process. The SOMDServer object works with the DSOM run time to create a 
  10743.  local "Stack" object and return a "Stack" proxy to the client. (The details of 
  10744.  this procedure are deferred until section 6.4, "Basic Server Programming".) 
  10745.  
  10746.      Ask the "Stack" proxy to push 100 onto the remote stack: 
  10747.  
  10748.             _push(stk,&e,100);
  10749.  
  10750.  This causes a message representing the method call to be marshalled and sent 
  10751.  to the server process. In the server process, DSOM demarshals the message and, 
  10752.  with the help of the SOMDServer, locates the target "Stack" object upon which 
  10753.  it invokes the method ("push"). The result (which is void in this case) is 
  10754.  then passed back to the client process in a message. 
  10755.  
  10756.      Invoke more "Stack" operations on the remote stack, via the proxy: 
  10757.  
  10758.             _push(stk,&e,200);
  10759.  
  10760.             _pop(stk,&e);
  10761.  
  10762.             if (!_empty(stk,&e)) t = _top(stk,&e);
  10763.  
  10764.      Explicitly destroy both the remote stack, the stack proxy, and the server 
  10765.       proxy: 
  10766.  
  10767.             _somdDeleteObj(server, &e, stk);
  10768.  
  10769.             _somdReleaseObject(SOMD_ObjectMgr, &e, stk);
  10770.  
  10771.             _somdReleaseObject(SOMD_ObjectMgr, &e, server);
  10772.  
  10773.      Free the error-passing environment: 
  10774.  
  10775.             SOM_UninitEnvironment(&e);
  10776.  
  10777.  This scenario has introduced the key processes in a DSOM application: client, 
  10778.  server, and somdd. Also introduced are the key objects that comprise the DSOM 
  10779.  run-time environment: the SOMD_ObjectMgr in the client process and the 
  10780.  SOMD_ServerObject in the server process. 
  10781.  
  10782.  
  10783. ΓòÉΓòÉΓòÉ 7.12.11. Summary ΓòÉΓòÉΓòÉ
  10784.  
  10785. This example has introduced the key concepts of building, installing, and 
  10786. running a DSOM application. It has also introduced some of the key components 
  10787. that comprise the DSOM application run-time environment. 
  10788.  
  10789. The following sections, "Basic Client Programming," "Basic Server Programming," 
  10790. and "Implementing Classes," provide more detail on how to use, manage, and 
  10791. implement remote objects, respectively. 
  10792.  
  10793.  
  10794. ΓòÉΓòÉΓòÉ 7.13. Basic Client Programming ΓòÉΓòÉΓòÉ
  10795.  
  10796. For the most part, client programming in DSOM is exactly the same as client 
  10797. programming in SOM, since DSOM transparently hides the fact that an object is 
  10798. remote when the client accesses the object. 
  10799.  
  10800. However, a client application writer also needs to know how to create, locate, 
  10801. use, save, and destroy remote objects. (This is not done using the usual SOM 
  10802. bindings.) The DSOM run-time environment provides these services to client 
  10803. programs primarily through the DSOM Object Manager. These run-time services 
  10804. will be detailed in this section. Examples of how an application developer uses 
  10805. these services are provided throughout the section. 
  10806.  
  10807.  
  10808. ΓòÉΓòÉΓòÉ 7.13.1. DSOM Object Manager ΓòÉΓòÉΓòÉ
  10809.  
  10810. DSOM defines a DSOM Object Manager, which provides services needed by clients 
  10811. to create, find and use objects in the DSOM run-time environment. 
  10812.  
  10813. The DSOM Object Manager is derived from an abstract, generic "object manager" 
  10814. class, called ObjectMgr. This abstract ObjectMgr class defines a basic set of 
  10815. methods that support object creation, location (with implicit activation), and 
  10816. destruction. 
  10817.  
  10818. As an abstract class, ObjectMgr defines only an interface; there is no 
  10819. implementation associated with ObjectMgr. Consequently, an application should 
  10820. not create instances of the ObjectMgr class. 
  10821.  
  10822.  An abstract Object Manager class was defined under the expectation that 
  10823. applications will often need simultaneous access to objects implemented and 
  10824. controlled by a variety of object systems. Such object systems may include 
  10825. other ORBs (in addition to DSOM), object-oriented databases, and so forth. It 
  10826. is likely that each object system will provide the same sort of basic services 
  10827. for object creation, location, and activation, but each using a different 
  10828. interface. 
  10829.  
  10830. Thus, the ObjectMgr abstract class defines a simple and "universal" interface 
  10831. that can be mapped to any object system. The application would only have to 
  10832. understand a single, common ObjectMgr interface. Under this scheme, specific 
  10833. object managers are defined by subclassing the ObjectMgr class and overriding 
  10834. the ObjectMgr methods to map them into the object system-specific programming 
  10835. interfaces. 
  10836.  
  10837. DSOM's Object Manager, SOMDObjectMgr, is defined as a specific class of 
  10838. ObjectMgr. It defines methods for: 
  10839.  
  10840.      Finding servers that implement particular kinds of objects 
  10841.  
  10842.      Creating objects in servers 
  10843.  
  10844.      Obtaining object identifiers (string IDs) 
  10845.  
  10846.      Finding objects, given their identifiers 
  10847.  
  10848.      Releasing and destroying objects 
  10849.  
  10850.  These functions will be discussed in the remainder of this section. 
  10851.  
  10852.  Note:  The OMG has standardized an "object lifecycle" service, which includes 
  10853.         support for creating and destroying distributed objects.  The DSOM 
  10854.         Object Manager may be augmented in the future with an OMG-compliant 
  10855.         lifecycle service. 
  10856.  
  10857.  
  10858. ΓòÉΓòÉΓòÉ 7.13.2. Initializing a client program ΓòÉΓòÉΓòÉ
  10859.  
  10860. A client application must declare and initialize the DSOM run time before 
  10861. attempting to create or access a remote object. The SOMD_Init procedure 
  10862. initializes all of the DSOM run time, including the  SOMDObjectMgr object. The 
  10863. global variable, SOMD_ObjectMgr is initialized to point to the local DSOM 
  10864. Object Manager. 
  10865.  
  10866. A client application must also initialize all application classes used by the 
  10867. program. For each class, the corresponding <className>NewClass call should be 
  10868. made. 
  10869.  
  10870. Note:  In non-distributed SOM programs, the <className>New macro (and the new 
  10871.        operator provided for each class by the SOM C++ bindings) implicitly 
  10872.        calls the procedure <className>NewClass when creating a new object. This 
  10873.        is not currently possible in DSOM because, when creating remote objects, 
  10874.        DSOM uses a generic method that is not class-specific. 
  10875.  
  10876.  This was shown in the "Stack" example in section 6.2. In a similar example of 
  10877.  an application that uses "Car" and "Driver" objects, the initialization code 
  10878.  might look like this: 
  10879.  
  10880.   #include <somd.h>    /* needed by all clients */
  10881.   #include <Car.h>     /* needed to access remote Car */
  10882.   #include <Driver.h>  /* needed to access remote Driver */
  10883.  
  10884.   main()
  10885.   {
  10886.       Environment ev; /* ev used for error passing */
  10887.       SOM_InitEnvironment(&ev);
  10888.  
  10889.       /* Do DSOM initialization */
  10890.       SOMD_Init(&ev);
  10891.  
  10892.       /* Initialize application classes */
  10893.       CarNewClass(Car_MajorVersion, Car_MinorVersion);
  10894.       DriverNewClass(Driver_MajorVersion, Driver_MinorVersion);
  10895.       ...
  10896.   }
  10897.  
  10898.  As shown, client programs should include the "somd.h" file (or, for C++ 
  10899.  programs, the "somd.xh" file) in order to define the DSOM runtime interfaces. 
  10900.  
  10901.  Note also that, since Environments are used for passing error results between 
  10902.  a method and its caller, an Environment variable (ev) must be declared and 
  10903.  initialized for this purpose. 
  10904.  
  10905.  The calls to "CarNewClass" and "DriverNewClass" are required if the client 
  10906.  will be creating or accessing Cars and Drivers. The procedures "CarNewClass" 
  10907.  and "DriverNewClass" create class objects for the classes "Car" and "Driver". 
  10908.  When a DSOM Object Manager method like somdNewObject is invoked to create a 
  10909.  "Car", it expects the "Car" class object to exist. If the class does not yet 
  10910.  exist, the "ClassNotFound" exception will be returned. 
  10911.  
  10912.  
  10913. ΓòÉΓòÉΓòÉ 7.13.3. Exiting a client program ΓòÉΓòÉΓòÉ
  10914.  
  10915. At the end of a client program, the SOMD_Uninit procedure must be called to 
  10916. free DSOM run-time objects, and to release system resources such as semaphores, 
  10917. shared memory segments, and so on. SOMD_Uninit should be called even if the 
  10918. client program terminates unsuccessfully; otherwise, system resources will not 
  10919. be released. 
  10920.  
  10921. For example, the exit code in the client program might look like this: 
  10922.  
  10923.     ...
  10924.     SOMD_Uninit(&e);
  10925.     SOM_UninitEnvironment(&e);
  10926. }
  10927.  
  10928. Note also the SOM_UninitEnvironment call, which frees any memory associated 
  10929. with the specified Environment structure. 
  10930.  
  10931.  
  10932. ΓòÉΓòÉΓòÉ 7.13.4. Creating remote objects ΓòÉΓòÉΓòÉ
  10933.  
  10934. Distributed objects can be created in several different ways in DSOM. 
  10935.  
  10936.      The client can create an object on any server that implements that class 
  10937.       of object. 
  10938.  
  10939.      The client can find a specific server upon which to create an object. 
  10940.  
  10941.      A server can create an object and register a reference to the object in 
  10942.       some well-known directory. (An object reference contains information that 
  10943.       reliably identifies a particular object.) 
  10944.  
  10945.  The first two cases are discussed immediately below. The last case is 
  10946.  discussed near the end of this section. 
  10947.  
  10948.  
  10949. ΓòÉΓòÉΓòÉ 7.13.4.1. Creating an object in an arbitrary server ΓòÉΓòÉΓòÉ
  10950.  
  10951. Following is an example of how to create a new remote object in the case where 
  10952. the client does not care in which server the object is created. In this 
  10953. situation, the client defers these decisions to the DSOM Object Manager 
  10954. (SOMD_ObjectMgr) by using the somdNewObject method call, which has this IDL 
  10955. definition: 
  10956.  
  10957.  
  10958.   // (from file om.idl)
  10959.  
  10960.  
  10961.   SOMObject somdNewObject(in Identifier objclass, in string hints);
  10962.  
  10963.   // Returns a new object of the named class.  This is a "basic"
  10964.   // creation method, where the decisions about where and how to
  10965.   // create the object are mostly left up to the Object Manager.
  10966.   // However, the Object Manager may optionally define creation
  10967.   // "hints" which the client may specify in this call.
  10968.  
  10969. Here is the example of how a remote "Car" would be created using somdNewObject: 
  10970.  
  10971. #include <somd.h>
  10972. #include <Car.h>
  10973.  
  10974. main()
  10975. {
  10976.     Environment ev;
  10977.     Car car;
  10978.  
  10979.     SOM_InitEnvironment(&ev);
  10980.     SOMD_Init(&ev);
  10981.  
  10982.     /* create the class object */
  10983.     CarNewClass(Car_MajorVersion, Car_MinorVersion);
  10984.  
  10985.     /* create a Car object on some server, let the
  10986.        Object Manager choose which one */
  10987.     car = _somdNewObject(SOMD_ObjectMgr, &ev, "Car", "");
  10988.     ...
  10989. }
  10990.  
  10991. The main argument to the somdNewObject method call is a string specifying the 
  10992. name of the class of the desired object. The last argument is a string that may 
  10993. contain "hints" for the Object Manager when choosing a server. In this example, 
  10994. the client is providing no hints. (Currently, the DSOM Object Manager simply 
  10995. passes the hints to the server object in a somdCreateObj call.) 
  10996.  
  10997.  
  10998. ΓòÉΓòÉΓòÉ 7.13.4.2. Proxy objects ΓòÉΓòÉΓòÉ
  10999.  
  11000. As far as the client program is concerned, when a remote object is created, a 
  11001. pointer to the object is returned. However, what is actually returned is a 
  11002. pointer to a proxy object, which is a local representative for the remote 
  11003. target object. 
  11004.  
  11005. Proxies are responsible for ensuring that operations invoked on it get 
  11006. forwarded to the "real" target object that it represents. The DSOM run time 
  11007. creates proxy objects automatically, wherever an object is returned as a result 
  11008. of some remote operation. The client program will always have a proxy for each 
  11009. remote target object on which it operates. Proxies are described further in the 
  11010. sections entitled "DSOM as a CORBA-compliant Object Request Broker" and 
  11011. "Advanced Topics". 
  11012.  
  11013. In the example above, a pointer to a "Car" proxy is returned and put in the 
  11014. variable "car". Any subsequent methods invoked on "car" will be forwarded and 
  11015. executed on the corresponding remote "Car" object. 
  11016.  
  11017. Proxy objects inherit behavior from the SOMDClientProxy class. 
  11018.  
  11019.  
  11020. ΓòÉΓòÉΓòÉ 7.13.4.3. Servers and server objects ΓòÉΓòÉΓòÉ
  11021.  
  11022. In DSOM, the process that manages a target object is called the object's 
  11023. server. Servers are implemented as programs that use SOM classes. The example 
  11024. above placed no constraints on the DSOM Object Manager as to which server 
  11025. should create the remote "Car" object. However, if the client desires more 
  11026. control over distribution of objects, the DSOM Object Manager provides methods 
  11027. for finding specific servers. 
  11028.  
  11029. Server implementations are registered with DSOM in an Implementation 
  11030. Repository. Server implementations are described by a unique ID, a unique 
  11031. (user-friendly) name, the program name that implements the server, the classes 
  11032. that are implemented by the server, the machine on which the server is located, 
  11033. whether the server is multi-threaded, and so forth. (See section 6.6 for more 
  11034. information on registering server implementations.) A client can ask the DSOM 
  11035. Object Manager to find a particular server: 
  11036.  
  11037.      By name 
  11038.  
  11039.      By ID 
  11040.  
  11041.      By a class it supports 
  11042.  
  11043.  When a client asks for a "server", it is given (a proxy to) a server object 
  11044.  that provides interfaces for managing the objects in the server. There is one 
  11045.  server object per server process. All server objects are instances of the 
  11046.  SOMDServer class, or its subclasses. The default method provided by SOMDServer 
  11047.  for creating objects is: 
  11048.  
  11049.     // (from file somdserv.idl)
  11050.  
  11051.     SOMObject somdCreateObj(in Identifier objclass, in string hints);
  11052.  
  11053.     // Creates an object of the specified class.  This method
  11054.     // may optionally define creation "hints" which the client
  11055.     // may specify in this call.  (Hints are ignored by default.)
  11056.  
  11057.  Section 6.4 explains how to create application-specific server objects, 
  11058.  derived from SOMDServer, which override SOMDServer methods and introduce their 
  11059.  own methods for object management. 
  11060.  
  11061.  
  11062. ΓòÉΓòÉΓòÉ 7.13.4.4. Creating an object in a specific server ΓòÉΓòÉΓòÉ
  11063.  
  11064. The following example demonstrates how a client application creates a new 
  11065. object in a remote server chosen by the client. The DSOM Object Manager method 
  11066. somdFindServerByName is used to find and create a proxy to the server object 
  11067. for the server implementation named "myCarServer". The method somdCreateObj is 
  11068. then invoked on the server object to create the remote "Car". A proxy to the 
  11069. remote "Car" is returned. (The "Stack" client presented in the previous section 
  11070. used the same methods to create a remote "Stack".) 
  11071.  
  11072.  /* find a specific Car server */
  11073.     server =
  11074.       _somdFindServerByName(SOMD_ObjectMgr, &ev, "myCarServer");
  11075.  
  11076.  /* create a remote Car object on that server */
  11077.     car = _somdCreateObj(server, &ev, "Car", "");
  11078.     ...
  11079. }
  11080.  
  11081. Note:  If the specified server does not provide any implementation of the 
  11082.        desired class, a NULL pointer will be returned and a "ClassNotFound" 
  11083.        exception will be raised. 
  11084.  
  11085.  Three other methods can be invoked on the DSOM Object Manager to find server 
  11086.  implementations: somdFindServer, somdFindServersByClass, and 
  11087.  somdFindAnyServerByClass. The IDL declarations of these methods follow: 
  11088.  
  11089.  
  11090.   SOMDServer somdFindServer(in ImplId serverid);
  11091.  
  11092.   sequence<SOMDServer> somdFindServersByClass(in Identifier objclass);
  11093.  
  11094.   SOMDServer somdFindAnyServerByClass(in Identifier objclass);
  11095.  
  11096.  The somdFindServer method is similar to the somdFindServerByName method, 
  11097.  except that the server's implementation ID (of type ImplId) is used to 
  11098.  identify the server instead of the server's user-friendly name (or "alias"). 
  11099.  The implementation ID is a unique string generated by the Implementation 
  11100.  Repository during server registration. (See section 6.6 for more details.) 
  11101.  
  11102.  The somdFindServersByClass method, given a class name, returns a sequence of 
  11103.  all servers that support the given class. The client program may then choose 
  11104.  which server to use, based on the server's name, program, or other 
  11105.  implementation attributes (e.g., the server is multi-threaded). (See the topic 
  11106.  below, "Inquiring about a remote object's implementation.") 
  11107.  
  11108.  Finally, the somdFindAnyServerByClass method simply selects any one of the 
  11109.  server implementations registered in the Implementation Repository that 
  11110.  supports the given class, and returns a server proxy for that server. 
  11111.  
  11112.  Once the server proxy is obtained, methods like somdCreateObj, shown in the 
  11113.  example above, can be invoked upon it to create new objects. 
  11114.  
  11115.  
  11116. ΓòÉΓòÉΓòÉ 7.13.4.5. Inquiring about a remote object's implementation ΓòÉΓòÉΓòÉ
  11117.  
  11118. A client may wish to inquire about the (server) implementation of a remote 
  11119. object. All objects in a server, including the "server object", share the same 
  11120. implementation definition. This is common when using the somdFindServersByClass 
  11121. call, where a sequence of server proxies is returned, and some choice must be 
  11122. made about which to use. 
  11123.  
  11124. When a proxy is obtained by a client, the client can inquire about the 
  11125. underlying server implementation by obtaining its corresponding 
  11126. ImplementationDef. An ImplementationDef object  contains a set of attributes 
  11127. that describe a server implementation. To get the ImplementationDef associated 
  11128. with a remote object, the get_implementation method (implemented on SOMDObject 
  11129. and inherited by SOMDClientProxy) can be called. 
  11130.  
  11131. For example, if a program has a proxy for a remote server object, it can get 
  11132. the ImplementationDef for the server with method calls similar to the 
  11133. following: 
  11134.  
  11135.  
  11136.     ImplementationDef implDef;
  11137.     SOMDServer server;
  11138.  
  11139.     ...
  11140.     implDef = _get_implementation(server, &ev);
  11141.  
  11142. Once the ImplementationDef has been obtained, the application can access its 
  11143. attributes using the _get_impl_xxx methods. 
  11144.  
  11145. The ImplementationDef class is discussed further in section 6.6, "Configuring 
  11146. DSOM." 
  11147.  
  11148.  
  11149. ΓòÉΓòÉΓòÉ 7.13.5. Destroying remote objects ΓòÉΓòÉΓòÉ
  11150.  
  11151. There are several ways of destroying objects or their proxies in DSOM, just as 
  11152. there are several ways to create objects. Remote objects can be asked to 
  11153. destroy themselves, or, the SOMDObjectMgr and the SOMDServer can participate in 
  11154. the deletion. 
  11155.  
  11156.  
  11157. ΓòÉΓòÉΓòÉ 7.13.5.1. Destroying objects via a proxy ΓòÉΓòÉΓòÉ
  11158.  
  11159. DSOM provides means for deleting remote objects via their proxies. For example, 
  11160. if somFree is invoked on a proxy, the somFree call gets forwarded directly to 
  11161. the target object, just like any other target method call. For example, 
  11162.  
  11163.  
  11164. _somFree(car);
  11165.  
  11166. frees the remote car.  Note that, by default, invoking somFree on the proxy 
  11167. does not free the proxy, only the remote object.  However, the following call 
  11168. can be issued as part of a client-program initialization, so that invoking 
  11169. somFree on a proxy frees both the remote object and the proxy: 
  11170.  
  11171.    __set_somd21somFree(SOMD_ObjectMgr, ev, TRUE);
  11172.  
  11173. All subsequent invocations of somFree on a proxy object will result in both the 
  11174. remote object and the proxy being freed. 
  11175.  
  11176. To be explicit about whether the proxy or the remote object is being deleted, 
  11177. the methods somdTargetFree and somdProxyFree, defined on proxies, can be used: 
  11178.  
  11179. _somdTargetFree(car, &ev);
  11180. frees the remote "Car" (but not the proxy) and 
  11181.  
  11182. _somdProxyFree(car, &ev);
  11183.  
  11184. frees the proxy (but not the remote "Car"). 
  11185.  
  11186. Note:  CORBA specifies a third method for deleting object references. (Proxies 
  11187.        are a specialized type of object reference.) The method 
  11188.  
  11189.  
  11190.                       _release(car, &ev);
  11191.  
  11192.  
  11193.                deletes the proxy (but not the target object).
  11194.  
  11195.  
  11196. ΓòÉΓòÉΓòÉ 7.13.5.2. Destroying objects via the DSOM Object Manager ΓòÉΓòÉΓòÉ
  11197.  
  11198. Having created a remote object with somdNewObject or somdCreateObj, the remote 
  11199. object and its local proxy may be destroyed by invoking the method 
  11200. somdDestroyObject on the DSOM Object Manager using the proxy as an argument. 
  11201. For example, 
  11202.  
  11203.  
  11204. /* create the car */
  11205. car = _somdNewObject(SOMD_ObjectMgr, &ev, "Car", "");
  11206. ...
  11207. /* destroy the car (and its proxy) */
  11208. _somdDestroyObject(SOMD_ObjectMgr, &ev, car);
  11209.  
  11210. If the client does not want to destroy the remote object, but is finished 
  11211. working with it, the somdReleaseObject method should be used instead, e.g., 
  11212.  
  11213. _somdReleaseObject(SOMD_ObjectMgr, &ev, car);
  11214.  
  11215. This deletes the local proxy, but not the remote object. 
  11216.  
  11217. Both somdDestroyObject and somdReleaseObject are defined on the ObjectMgr, so 
  11218. that the Object Manager is aware of the client's actions, in case it wants to 
  11219. do any bookkeeping. 
  11220.  
  11221. The object passed to either the somdDestroyObject method or the 
  11222. somdReleaseObject method can be either a local SOM object or a DSOM proxy 
  11223. object.  When a local SOM object is passed, somdDestroyObject has the same 
  11224. behavior as somFree. If a local SOM object is passed to somdReleaseObject, 
  11225. however, this has no effect. 
  11226.  
  11227.  
  11228. ΓòÉΓòÉΓòÉ 7.13.5.3. Destroying objects via a server object ΓòÉΓòÉΓòÉ
  11229.  
  11230. The somdDestroyObject method described above sends a request to delete a remote 
  11231. object to the object's server. It does so to ensure that the server has an 
  11232. opportunity to participate in, if not perform, the deletion. The method defined 
  11233. on the SOMDServer class for destroying objects is somdDeleteObj. If the client 
  11234. has a proxy for the server object, it can also invoke somdDeleteObj directly, 
  11235. instead of calling somdDestroyObject. 
  11236.  
  11237. Destroying objects via the server object, rather than asking the object itself 
  11238. (as in somFree or somdTargetFree), allows the server object do any clean-up 
  11239. that is needed. For simple applications, this may not be necessary, but for 
  11240. applications that provide their own application-tailored server objects, it may 
  11241. be critical. 
  11242.  
  11243.  
  11244. ΓòÉΓòÉΓòÉ 7.13.6. Creating remote objects using user-defined metaclasses ΓòÉΓòÉΓòÉ
  11245.  
  11246. An application may wish to define its own constructor methods for a particular 
  11247. class, via a user-supplied metaclass. In this case, the somdNewObject method 
  11248. should not be used, since it simply calls the default constructor method, 
  11249. somNew, defined by SOMClass. 
  11250.  
  11251. Instead, the application can obtain a proxy to the actual class object in the 
  11252. server process. It can do so via the somdGetClassObj method, invoked on the 
  11253. SOMDServer proxy returned by one of the somdFindServerXxx methods. The 
  11254. application-defined constructor method can then be invoked on the proxy for the 
  11255. remote class object. 
  11256.  
  11257. Note:  The same issues apply to destructor methods. If the application defines 
  11258.        its own destructor methods, they can be called via the class object 
  11259.        returned by somdGetClassObj, as opposed to calling somdDestroyObject. 
  11260.  
  11261.  The following example creates a new object in a remote server using an 
  11262.  application-defined constructor method, "makeCar", which is assumed to have 
  11263.  been defined in the metaclass of "Car", named "MetaCar". 
  11264.  
  11265.   #include <somd.h>
  11266.   #include <Car.h>
  11267.   main( )
  11268.   {
  11269.       Environment ev;
  11270.       SOMDServer server;
  11271.       Car car;
  11272.       MetaCar carClass;
  11273.  
  11274.       SOM_InitEnvironment(&ev);
  11275.       SOMD_Init(&ev);
  11276.  
  11277.       /* find a Car server */
  11278.       server = _somdFindAnyServerByClass(SOMD_ObjectMgr, &ev, "Car");
  11279.  
  11280.       /* get the class object for Car */
  11281.       carClass = (MetaCar) _somdGetClassObj(server, &ev, "Car");
  11282.  
  11283.       /* create the car object */
  11284.       car = _makeCar(carClass, &ev, "Red", "Toyota", "2-door");
  11285.  
  11286.       ...
  11287.   }
  11288.  
  11289.  
  11290. ΓòÉΓòÉΓòÉ 7.13.7. Saving and restoring references to objects ΓòÉΓòÉΓòÉ
  11291.  
  11292. A proxy is a kind of "object reference". An object reference contains 
  11293. information that is used to identify a target object. 
  11294.  
  11295. To enable clients to save references to remote objects (in a file system, for 
  11296. example) or exchange references to remote objects (with other application 
  11297. processes), DSOM must be able to externalize proxies. To "externalize a proxy" 
  11298. means to create a string ID for a proxy that can be used by any process to 
  11299. identify the remote target object. DSOM must also support the translation of 
  11300. string IDs back into proxies. 
  11301.  
  11302. The DSOM Object Manager defines two methods for converting between proxies and 
  11303. their string IDs: somdGetIdFromObject and somdGetObjectFromId. 
  11304.  
  11305. Here is an example client program that creates a remote "Car" object. It 
  11306. generates a string ID corresponding to the proxy, and saves the string ID to a 
  11307. file for later use. 
  11308.  
  11309. #include <stdio.h>
  11310. #include <somd.h>
  11311. #include <Car.h>
  11312. main( )
  11313. {
  11314.     Environment ev;
  11315.     Car car;
  11316.     string somdObjectId;
  11317.     FILE* file;
  11318.  
  11319.     SOM_InitEnvironment(&ev);
  11320.     SOMD_Init(&ev);
  11321.  
  11322.     /* create a remote Car object */
  11323.     car = _somdNewObject(SOMD_ObjectMgr, &ev, "Car", "");
  11324.  
  11325.     /* save the reference to the object */
  11326.     somdObjectId = _somdGetIdFromObject(SOMD_ObjectMgr, &ev, car);
  11327.     file = fopen("/u/joe/mycar", "w");
  11328.     fprintf(file, "%s", somdObjectId);
  11329. ...
  11330.  
  11331. Next is an example client program that retrieves the string ID and regenerates 
  11332. a valid proxy for the original remote "Car" object (assuming the remote "Car" 
  11333. object can still be found in the server). 
  11334.  
  11335. ...
  11336.     Environment ev;
  11337.     Car car;
  11338.     char buffer[256];
  11339.     string somdObjectId;
  11340.     FILE* file;
  11341.  
  11342. ...
  11343.     /* restore proxy from its string form */
  11344.     file = fopen("/u/joe/mycar", "r");
  11345.     somdObjectId = (string) buffer;
  11346.     fscanf(file, "%s", somdObjectId);
  11347.     car = _somdGetObjectFromId(SOMD_ObjectMgr, &ev, somdObjectId);
  11348. ...
  11349.  
  11350. Once the proxy has been regenerated, methods can be invoked on the proxy and 
  11351. they will be forwarded to the remote target object, as always. 
  11352.  
  11353. Note:  The somdGetIdFromObject and somdGetObjectFromId methods directly 
  11354.        correspond to the CORBA methods ORB_object_to_string and 
  11355.        ORB_string_to_object, defined on the ORB class. 
  11356.  
  11357.  
  11358. ΓòÉΓòÉΓòÉ 7.13.7.1. Finding existing objects ΓòÉΓòÉΓòÉ
  11359.  
  11360. The SOMDObjectMgr and SOMDServer classes support the methods described above, 
  11361. which allow clients to create objects in servers. However, it is also likely 
  11362. that clients will want to find and use objects that have already been created, 
  11363. usually by the servers that implement them. For example, a print service will 
  11364. create printer objects, and must then export them to clients. In that case, the 
  11365. calls to somdNewObject or somdCreateObj would be replaced with other "lookup" 
  11366. calls on some directory (server) object which would take an object name or 
  11367. identifier and return a proxy to a corresponding remote object. Likewise, the 
  11368. server that owns the object would register the exported object in the 
  11369. directory. 
  11370.  
  11371. It is important to understand that DSOM does not provide a directory service 
  11372. such as the one described. But such a directory object could be implemented by 
  11373. the application, where a table or collection object maps object names to 
  11374. proxies. The string IDs for the proxies in the directory object could be saved 
  11375. using a file. A directory server implemented using DSOM could be used to share 
  11376. the directory among processes. 
  11377.  
  11378. Upon a lookup call, the directory server could find the corresponding proxy (or 
  11379. its string ID) in the directory, and return it to the caller. 
  11380.  
  11381.  
  11382. ΓòÉΓòÉΓòÉ 7.13.8. Finding server objects ΓòÉΓòÉΓòÉ
  11383.  
  11384. The DSOM Object Manager can be used to find server object proxies using the 
  11385. somdFindServerXxx methods. However, it is important to point out that an 
  11386. application can also augment those services, by managing server proxies itself. 
  11387. Server proxies can be maintained in an application-specific directory, stored 
  11388. in a file, or passed from process to process, just as any other proxies. 
  11389.  
  11390.  
  11391. ΓòÉΓòÉΓòÉ 7.13.9. Invoking methods on remote objects ΓòÉΓòÉΓòÉ
  11392.  
  11393. As described earlier, DSOM proxies are local representatives of remote objects, 
  11394. and as such, they can be treated like the target objects themselves. Method 
  11395. calls are invoked in exactly the same manner as if the object is local. This is 
  11396. true both for method calls using the static bindings (as most of our examples 
  11397. have shown), as well as for dynamic dispatching calls, where SOM facilities 
  11398. (such as the somDispatch method) are used to construct method calls at run 
  11399. time. 
  11400.  
  11401. CORBA 1.1 also defines a dynamic invocation interface that is implemented by 
  11402. DSOM. It is described later in section 6.9, "Advanced Topics". 
  11403.  
  11404. The DSOM run time is responsible for transporting any input method argument 
  11405. values supplied by the caller (defined by legal IDL types) to the target object 
  11406. in a remote call. Likewise, the DSOM run time transports the return value and 
  11407. any output argument values back to the caller following the method call. 
  11408.  
  11409. Note:  DSOM uses the Interface Repository (IR) to discover the "signature" of a 
  11410.        method (that is, the method's prototype). It is important that the 
  11411.        contents of the IR match the method bindings used by the application 
  11412.        program (i.e. the same IDL file is used to update the IR and to generate 
  11413.        bindings). 
  11414.  
  11415.  DSOM can make remote invocations only of methods whose parameter types are 
  11416.  among the following IDL types:  basic types (short, long, unsigned short, 
  11417.  unsigned long, float, double, char, boolean, octet), enum, struct, union, 
  11418.  sequence, string, array, any, and object. The members of a struct, union, 
  11419.  sequence, or array and the value of an any, must also be from the above list 
  11420.  of supported DSOM types. 
  11421.  
  11422.  In addition to the preceding types, DSOM also supports method parameters of 
  11423.  type pointer to one of the above types (for example, long*) Pointers to 
  11424.  pointers are not supported, however, and pointers embedded within one of the 
  11425.  above types (for example, a pointer within a struct) are not supported The 
  11426.  "void *" type is also not supported. Currently, DSOM has the limitation that 
  11427.  NULL pointer values cannot be returned as inout or out method arguments 
  11428.  although it is expected that this limitation will be addressed in a future 
  11429.  release. 
  11430.  
  11431.  Types declared as SOMFOREIGN types are not currently supported by DSOM. 
  11432.  Because the SOM somId is declared as a SOMFOREIGN type, this implies that any 
  11433.  method having a parameter of type somId cannot be invoked remotely using DSOM. 
  11434.  This restriction includes the  SOM methods: somRespondsTo, somSupportsMethod, 
  11435.  somGetMethodDescriptor, somGetMethodIndex, and somGetNthMethodInfo. 
  11436.  
  11437.  When a method parameter is an object type (that is, an instance of SOMObject 
  11438.  or some class derived from SOMObject), a client program making a remote 
  11439.  invocation of that method must pass an object reference for that parameter, 
  11440.  rather than passing a local SOMObject, unless the client program is also DSOM 
  11441.  server program, in which case DSOM will automatically convert the local object 
  11442.  into an object reference. 
  11443.  
  11444.  Methods having the procedure SOM IDL modifier cannot be invoked remotely using 
  11445.  DSOM.  This is because these "methods" are called directly, rather than via 
  11446.  the normal method resolution mechanisms on which DSOM relies. 
  11447.  
  11448.  
  11449. ΓòÉΓòÉΓòÉ 7.13.9.1. Determining memory allocation and ownership ΓòÉΓòÉΓòÉ
  11450.  
  11451. When a method is invoked that returns a result of type string, sequence, or 
  11452. array, DSOM will allocate memory in the client's address space for the result. 
  11453. Ownership of this memory becomes the responsibility of the client program. When 
  11454. the client program has finished using it, the client should free the memory 
  11455. using the ORBfree function, rather than using free or SOMFree (This is because 
  11456. the memory has been allocated by DSOM using special memory management 
  11457. techniques; therefore, the client should ask DSOM to also free the memory.) 
  11458.  
  11459. When invoking a method using DSOM, the client program is  responsible for 
  11460. providing storage for all in arguments and for all inout/out arguments, with 
  11461. the following exceptions: DSOM will allocate storage for a string or for the 
  11462. _buffer field of a sequence when used as an out argument, and will allocate 
  11463. storage for the_value field of an any when used as an inout or out argument. 
  11464. This storage becomes the responsibility of the client program and should later 
  11465. be freed using ORBfree. For a string or sequence used as an inout argument, the 
  11466. out result is constrained to be no larger than the size of the in argument 
  11467. allocated by the client. 
  11468.  
  11469.  
  11470. ΓòÉΓòÉΓòÉ 7.13.10. Passing object references in method calls ΓòÉΓòÉΓòÉ
  11471.  
  11472. When pointers to objects are returned as method output values (as in the 
  11473. previous examples), DSOM automatically converts the object pointers (in the 
  11474. server) to object proxies in the client. 
  11475.  
  11476. Likewise, when a client passes object (proxy) pointers as input arguments to a 
  11477. method, DSOM automatically converts the proxy argument in the client to an 
  11478. appropriate object reference in the server. 
  11479.  
  11480. Note:  If the proxy is for an object that is in the same server as the target 
  11481.        object, DSOM gives the object reference to the server object for 
  11482.        resolution to a SOM object pointer. Otherwise, DSOM leaves the proxy 
  11483.        alone, since the proxy must refer to an object in some process other 
  11484.        than the target's server. 
  11485.  
  11486.  
  11487. ΓòÉΓòÉΓòÉ 7.13.11. Memory management ΓòÉΓòÉΓòÉ
  11488.  
  11489. DSOM programs must manage four different kinds of memory resources: objects, 
  11490. object references, Environment structures, and blocks of memory. There are 
  11491. different techniques for allocating and releasing each kind of resource. 
  11492.  
  11493. Objects and object references 
  11494.  
  11495. Creating and destroying remote objects was discussed previously in this section 
  11496. (see "Creating remote objects" and "Destroying remote objects"). Creating and 
  11497. destroying local objects is described in section 3.2, "Using SOM Classes - the 
  11498. Basics," in Chapter 3, "Using SOM Classes in Client Programs."  Object 
  11499. references are typically created automatically by DSOM as needed by the client 
  11500. program. They are also released in the client program by using either the 
  11501. release method or the somdProxyFree method. (The two methods are equivalent.) 
  11502.  
  11503. Environment structures 
  11504.  
  11505. When a client invokes a method and the method returns an exception in the 
  11506. Environment structure, it is the client's responsibility to free the exception. 
  11507. This is done by calling either exception_free or somdExceptionFree on the 
  11508. Envirnmen structure in which the exception was returned. (The two functions are 
  11509. equivalent.) A similar function, somExceptionFree, is available for SOM 
  11510. programmers however DSOM programmers can use somdExceptionFree to free all 
  11511. exceptions (regardless of whether they were returned from a local or remote 
  11512. method call). 
  11513.  
  11514. Blocks of memory 
  11515.  
  11516. For allocating and releasing blocks of memory within a client program, SOM 
  11517. provides the SOMMalloc and SOMFree functions (analogous to the C "mallo" and 
  11518. "free" functions). The "Memory Management" section of Chapter 3 describes these 
  11519. functions. To release memory allocated by DSOM in response to a remote method 
  11520. call, however, DSOM client programs should use the ORBfree function 
  11521.  
  11522. For example, when a method is invoked that returns a result of type string, 
  11523. sequence, or array, DSOM will allocate memory for the result in the client's 
  11524. address space. Ownership of this memory becomes the responsibility of the 
  11525. client program. When finished using this memory, the client program should free 
  11526. it using the ORBfree function, rather than free or SOMFree. This is because the 
  11527. memory has been allocated by DSOM using special memory-management techniques; 
  11528. therefore, the client should ask DSOM to also free the memory. If the storage 
  11529. is freed using SOMFree rather than ORBfree, then memory leaks will result. 
  11530.  
  11531. The differences between the SOMFree and ORBfree functions are twofold: 
  11532.  
  11533.    1. First, SOMFree should only be used to free memory not allocated by 
  11534.       DSO(for example, memory the client program allocated itself using 
  11535.       SOMMalloc), while ORBfree should be used to free memory allocated by DSOM 
  11536.       in response to a remote method call. 
  11537.  
  11538.    2. Second, SOMFee only frees a single block of memory (in the same way that 
  11539.       the C "free" function does), while ORBfree will free an entire data 
  11540.       structure, including any allocated blocks of memory within in. For 
  11541.       example, if a remote method call returns a sequence of structs, and each 
  11542.       struct contains a string, ORBfree will free, with a single call, not only 
  11543.       the sequence's "_buffer" member, but also each struct and all the strings 
  11544.       within the structs. Freeing a similar data structure using SOMFree would 
  11545.       require multiple calls (one for each call to SOMMalloc used to build the 
  11546.       data structure). 
  11547.  
  11548.  Some programmers may wish to use a single function to free blocks of memory, 
  11549.  regardless of whether they were allocated locally or by DSOM in response to a 
  11550.  remote method call. For these programmers, DSOM provides a function, 
  11551.  SOMD_NoORBfree, which can be called just after calling SOMD_Init in the client 
  11552.  program. (It requires no arguments and returns no value.) This function 
  11553.  specifies that the client program will free all memory blocks using SOMFree, 
  11554.  rather than ORBfree. In response to this call, DSOM will not keep track of the 
  11555.  memory it allocates for the client. Instead, it assumes that the client 
  11556.  program will be responsible for walking all data structures returned from 
  11557.  remote method calls, while calling SOMFree for each block of memory within. 
  11558.  
  11559.  
  11560. ΓòÉΓòÉΓòÉ 7.13.11.1. Memory management for method parameters ΓòÉΓòÉΓòÉ
  11561.  
  11562. For each method, five SOM IDL modifiers are available to specify the method's 
  11563. memory-management policy  (that is, whether the caller or the object owns the 
  11564. parameters' memory after the method is invoked). These modifiers are 
  11565. memory_management, caller_owns_result, caller_owns_parameters, 
  11566. object_owns_result, and object_owns_parameters. For a complete description of 
  11567. these modifiers and their meanings, see the section entitled "Implementation 
  11568. Statements" in Chapter 4, "SOM IDL and the SOM Compiler." 
  11569.  
  11570. Note that the memory-management policy for a particular parameter applies to 
  11571. the parameter and all the memory embedded within it (for example, if a struct 
  11572. is owned by the caller, then so are all the struct's members). Also note that 
  11573. the "object-owned" memory-management policy, specified by the 
  11574. object_owns_result and object_owns_parameters modifiers, is not  supported by 
  11575. DSM for metods invoked using the Dynamic Invocation Interface (DII). (This is 
  11576. because the "object-owned" policy is not CORBA-compliant, and because it 
  11577. precludes reusing Request objects to invoke a method multiple times.) 
  11578.  
  11579.  
  11580. ΓòÉΓòÉΓòÉ 7.13.11.2. The CORBA policy for parameter memory management ΓòÉΓòÉΓòÉ
  11581.  
  11582. When a class contains the SOM IDL modifier memory_management = corba, this 
  11583. signifies that all methods introduced by the class follow the CORBA 
  11584. specification for parameter memory management, except where a particular method 
  11585. has an explicit modifier (object_owns_result or object_owns_parameters) that 
  11586. indicates otherwise. The remainder of this section describes the CORBA 
  11587. specification for parameter memory management. 
  11588.  
  11589. Caller frees parameters and return results 
  11590.  
  11591. The CORBA memory-management policy specifies that the caller of a method is 
  11592. responsible for freeing all parameters and the return result after the method 
  11593. call is complete. This applies regardless of whether the parameter was 
  11594. allocated by the caller or the object (or, in the case of a remote method call, 
  11595. by DSOM). In other words, the CORBA policy asserts that parameters are 
  11596. uniformly "caller-owned". 
  11597.  
  11598. Allocation responsibilities 
  11599.  
  11600. Whether the parameter or return result should be allocated by the caller or by 
  11601. the object depends on the type  of the parameter and its mode  ("in", "inout", 
  11602. "out", or "return").  In general, the caller is responsible for allocating 
  11603. storage for most parameters and return results. More specifically, CORBA 
  11604. requires that storage for all "in" arguments, for all "inout" or "out" 
  11605. arguments, and for all "return" results must be provided by the client program, 
  11606. with certain exceptions as itemized below. 
  11607.  
  11608. The object is responsible for allocating storage as follows: 
  11609.  
  11610.      for strings when used as "out" arguments or as "return" results 
  11611.  
  11612.      for the "_buffer" field of sequences when used as "out" arguments or as 
  11613.       "return" results, 
  11614.  
  11615.      for the "_value" field of anys when used as "inout" or "out" arguments or 
  11616.       as "return" results, 
  11617.  
  11618.      for pointer types when used as "inout" or "out" arguments or as "return" 
  11619.       results, 
  11620.  
  11621.      for arrays when used as "return" results, and 
  11622.  
  11623.      for objects when used as "inout" or "out" arguments or as "return" 
  11624.       results. 
  11625.  
  11626.  Note:  For "inout" strings and sequences, the "out" result is constrained to 
  11627.         be no larger than the size of the "in" argument allocated by the 
  11628.         client. 
  11629.  
  11630.  Ownership of memory allocated in the above cases becomes the responsibility of 
  11631.  the client program. For remote method calls, when a remote object allocates 
  11632.  memory for a parameter or "return" value, DSOM subsequently allocates memory 
  11633.  in the client's address space for the parameter or result. For a 
  11634.  parameter/result that is an object (rather than a block of memory) DSOM 
  11635.  automatically creates an object reference (a proxy object) in the client's 
  11636.  address space. In each case, the memory or the proxy object becomes the 
  11637.  responsibility of the client program and should later be freed by the client, 
  11638.  using ORBfree for blocks of memory or release for proxy objects. 
  11639.  
  11640.  
  11641. ΓòÉΓòÉΓòÉ 7.13.11.3. The 'somdReleaseResources' method and object-owned parameters ΓòÉΓòÉΓòÉ
  11642.  
  11643. As stated earlier, the CORBA policy asserts that method parameters and return 
  11644. results are uniformly caller-owned. This means the method caller has the 
  11645. responsibility for freeing memory after invoking a method, regardless of 
  11646. whether the memory was allocated by the caller or the object. 
  11647.  
  11648. A class implementor can designate certain method parameters and results as 
  11649. object-owned, however, by using the object_owns_result and 
  11650. object_owns_parameters SOM IDL modifiers. These modifiers signify that the 
  11651. object, rather than the caller, is responsible for freeing the memory 
  11652. associated with the parameter/result. For "in" parameters, the object can free 
  11653. the memory any time after receiving it; for "inout" and "out" parameters, and 
  11654. for return results, the object will free the memory sometime before the object 
  11655. is destroyed. (See the section entitled "Implementation statements" in Chapter 
  11656. 4, "SOM IDL and the SOM Compiler," for more information on these modifiers.) 
  11657.  
  11658. When a DSOM client program makes a remote method invocation, via a proxy, and 
  11659. the method being invoked has an object-owned parameter or return result, then 
  11660. the client-side memory associated with the parameter/result will be owned by 
  11661. the caller's proxy, and the server-side memory will be owned by the remote 
  11662. object. The memory owned by the caller's proxy will be freed when the proxy is 
  11663. released by the client program. (The time at which the server-side memory will 
  11664. be freed depends on the implementation of the remote object.) 
  11665.  
  11666. A DSOM client can also instruct a proxy object to free all memory that it owns 
  11667. on behalf of the client without releasing the proxy (assuming that the client 
  11668. program is finished using the object-owned memory), by invoking the 
  11669. somdReleaseResource method on the proxy object. Calling somdReleaseResources 
  11670. can prevent unused memory from accumulating in a proxy. 
  11671.  
  11672. For example, consider a client program repeatedly invoking a remote method 
  11673. "get_string", which returns a string that is designated (in SOM IDL) as 
  11674. "object-owned". The proxy on which the method is invoked will store the memory 
  11675. associated with all the returned strings, even if the strings are not unique, 
  11676. until the proxy is released. If the client program only uses the last result 
  11677. returned from "get_string", then unused memory accumulates in the proxy. The 
  11678. client program can prevent this by invoking somdReleaseResources on the proxy 
  11679. object periodicall (for example, each time it finishes using the result of the 
  11680. last "get_string" call). 
  11681.  
  11682.  
  11683. ΓòÉΓòÉΓòÉ 7.13.12. Writing clients that are also servers ΓòÉΓòÉΓòÉ
  11684.  
  11685. In many applications, processes may need to play both client and server roles. 
  11686. That is, objects in the process may make requests of remote objects on other 
  11687. servers, but may also implement and export objects, requiring that it be able 
  11688. to respond to incoming requests. Details of how to write programs in this 
  11689. peer-to-peer style are explained in section 6.9, "Advanced Topics". 
  11690.  
  11691.  
  11692. ΓòÉΓòÉΓòÉ 7.13.13. Compiling and linking clients ΓòÉΓòÉΓòÉ
  11693.  
  11694. All client programs must include the header file "somd.h" (or for C++, 
  11695. "somd.xh") in addition to any "<className>.h" (or "<className>.xh") header 
  11696. files they require from application classes. All DSOM client programs must link 
  11697. to the SOMobjects Toolkit library: "somtk.lib" For more information, see the 
  11698. topic "Compiling and linking" in Chapter 3, "Using SOM Classes in Client 
  11699. Programs." 
  11700.  
  11701.  
  11702. ΓòÉΓòÉΓòÉ 7.14. Basic Server Programming ΓòÉΓòÉΓòÉ
  11703.  
  11704. Server programs execute and manage object implementations. That is, they are 
  11705. responsible for: 
  11706.  
  11707.      Notifying the DSOM daemon that they are ready to begin processing 
  11708.       requests, 
  11709.  
  11710.      Accepting client requests, 
  11711.  
  11712.      Loading class library DLLs when required, 
  11713.  
  11714.      Creating/locating/destroying local objects, 
  11715.  
  11716.      Demarshalling client requests into method invocations on their local 
  11717.       objects, 
  11718.  
  11719.      Marshalling method invocation results into responses to clients, and 
  11720.  
  11721.      Sending responses back to clients. 
  11722.  
  11723.  As mentioned previously, DSOM provides a simple, "generic" server program that 
  11724.  performs all of these tasks. All the server programmer needs to provide are 
  11725.  the application class library(ies) DLL that the implementer wants to 
  11726.  distribute. Optionally, the programmer can also supply an application#specific 
  11727.  server class, derived from SOMDServer. (The SOMDServer class can be used by 
  11728.  default.) The server program does the rest automatically. 
  11729.  
  11730.  The "generic" server program is called somdsvr and can be found in 
  11731.  %SOMBASE%\bin\somdsvr.exe 
  11732.  
  11733.  Some applications may require additional flexibility or functionality than 
  11734.  what is provided by the generic server program. In that case, 
  11735.  application-specific server programs can be developed. This section discusses 
  11736.  the steps involved in writing such a server program. 
  11737.  
  11738.  To create a server program, a server writer needs to know what services the 
  11739.  DSOM run-time environment will provide and how to use those services to 
  11740.  perform the duties (listed above) of a server. The DSOM run-time environment 
  11741.  provides several key objects that can be used to perform server tasks. These 
  11742.  objects and the services they provide will be discussed in this section. 
  11743.  Examples showing how to use the run-time objects to write a server are also 
  11744.  shown. 
  11745.  
  11746.  
  11747. ΓòÉΓòÉΓòÉ 7.14.1. Server run-time objects ΓòÉΓòÉΓòÉ
  11748.  
  11749. There are three DSOM run-time objects that are important in a server: 
  11750.  
  11751.      The server's implementation definition (ImplementationDef), 
  11752.  
  11753.      The SOM Object Adapter (SOMOA), and 
  11754.  
  11755.      The application-specific server object (an instance of either SOMDServer 
  11756.       or a class derived from SOMDServer). 
  11757.  
  11758.  
  11759. ΓòÉΓòÉΓòÉ 7.14.1.1. Server implementation definition ΓòÉΓòÉΓòÉ
  11760.  
  11761. A server's implementation definition must be registered in the Implementation 
  11762. Repository before a server can be used. When a client attempts to invoke a 
  11763. method on a remote object, DSOM consults the Implementation Repository to find 
  11764. the location of the target object's server. 
  11765.  
  11766. An implementation definition is represented by an object of class 
  11767. ImplementationDef, whose attributes describe a server's ID, user-assigned 
  11768. alias, host name, program pathname, the class of its server object, whether or 
  11769. not it is multi-threaded, and so forth. Implementation IDs uniquely identify 
  11770. servers within the Implementation Repository, and are used as keys into the 
  11771. Implementation Repository when retrieving the ImplementationDef for a 
  11772. particular server. 
  11773.  
  11774. It is possible to change the implementation characteristics of a server. The 
  11775. implementation ID identifies a logical server, and the ImplementationDef 
  11776. describes the current implementation of that logical server. 
  11777.  
  11778. See the topic "Registering Servers and Classes" in section 6.6 for details on 
  11779. server registration. Two registration methods are described: "manual," (via the 
  11780. regimpl, the wregimpl, or the pregimpl utility) and "programmatic," 
  11781. ImplRepository methods. 
  11782.  
  11783. When a server is initialized, it must retrieve a copy of its ImplementationDef, 
  11784. and keep it in a global variable (SOMD_ImplDefObject). This variable is used by 
  11785. the DSOM run time. (Client-only programs may leave the SOMD_ImplDefObject 
  11786. variable set to NULL.) 
  11787.  
  11788.  
  11789. ΓòÉΓòÉΓòÉ 7.14.1.2. SOM Object Adapter (SOMOA) ΓòÉΓòÉΓòÉ
  11790.  
  11791. The SOM Object Adapter (SOMOA) is the main interface between the server 
  11792. application and the DSOM run time. The SOMOA is responsible for most of the 
  11793. server duties listed at the beginning of this section. In particular, the SOMOA 
  11794. object handles all communications an interpretation of inbound requests and 
  11795. outbound results. When clients send requests to a server, the requests are 
  11796. received and processed by the SOMOA. 
  11797.  
  11798. The SOMOA works together with the server object to create and resolve DSOM 
  11799. references to local objects, and dispatch methods on objects. 
  11800.  
  11801. There is one SOMOA object per server process. (The SOMOA class is implemented 
  11802. as a single instance class.) 
  11803.  
  11804.  
  11805. ΓòÉΓòÉΓòÉ 7.14.1.3. Server object ΓòÉΓòÉΓòÉ
  11806.  
  11807. Each server process contains a single server object, which has the following 
  11808. responsibilities for managing objects in the server: 
  11809.  
  11810.      Provides an interface to client applications for basic object creation 
  11811.       and destruction services, as well as any other application-specific 
  11812.       object-management services that may be required by clients. For example, 
  11813.       a print server may have a method that returns a list of all printers 
  11814.       managed by that server. Clients may call this method to find out what 
  11815.       printers are available. 
  11816.  
  11817.      Provides an interface to the SOM Object Adapter for support in the 
  11818.       creation and management of DSOM object references (which are used 
  11819.       identify an object in the server), and for dispatching requests. 
  11820.  
  11821.      The server class, SOMDServer, defines the base interface that must be 
  11822.       supported by any server object. In addition, SOMDServer provides a 
  11823.       default implementation that is suited to managing transient SOM objects 
  11824.       in a server. This section will show how an application might override the 
  11825.       basic SOMDServer methods and introduce new methods in order to tailor the 
  11826.       server object functionality to a particular application. 
  11827.  
  11828.  
  11829. ΓòÉΓòÉΓòÉ 7.14.2. Server activation ΓòÉΓòÉΓòÉ
  11830.  
  11831. Server programs may be activated either 
  11832.  
  11833.      Automatically by the DSOM daemon, somdd, or 
  11834.  
  11835.      Manually via command line invocation, or under application control. 
  11836.  
  11837.  When a server is activated automatically by somdd, it will be passed a single 
  11838.  argument (in argv[1]) that is the implementation ID assigned to the server 
  11839.  implementation when it was registered into the Implementation Repository 
  11840.  (discussed above and in section 6.6, "Configuring DSOM Applications"). This is 
  11841.  useful when the server program cannot know until activation which "logical" 
  11842.  server it is implementing. (This is true for the generic server provided with 
  11843.  DSOM.) The implementation ID is used by the server to retrieve its 
  11844.  ImplementationDef from the Implementation Repository. 
  11845.  
  11846.  A server that is not activated by somdd may obtain its ImplementationDef from 
  11847.  the Implementation Repository in any manner that is convenient: by ID, by 
  11848.  alias, and so forth. Moreover, a server may choose to "register itself" 
  11849.  dynamically, as part of its initialization. To do so, the server would use the 
  11850.  programmatic interface to the Implementation Repository. 
  11851.  
  11852.  For example, suppose that the server program "myserver" was designed so that 
  11853.  it could be activated either automatically or manually. This requires that it 
  11854.  be written to expect the implementation ID as its first argument, and to use 
  11855.  that argument to retrieve its ImplementationDef from the Implementation 
  11856.  Repository. If an application defines a server in the Implementation 
  11857.  Repository whose implementation ID is 
  11858.  
  11859.   2bcdc4f2-0f62f780-7f-00-10005aa8afdc
  11860.  then "myserver" could be run as that server by invoking the following command: 
  11861.  
  11862.   myserver 2bcdc4f2-0f62f780-7f-00-10005aa8afdc
  11863.  
  11864.  
  11865. ΓòÉΓòÉΓòÉ 7.14.3. Initializing a server program ΓòÉΓòÉΓòÉ
  11866.  
  11867. The following subjects are discussed in this section: 
  11868.  
  11869.      Initializing the DSOM run-time environment 
  11870.      Initializing the server's ImplementationDef 
  11871.      Initializing the SOM Object Adapter 
  11872.      When initialization fails 
  11873.  
  11874.  
  11875. ΓòÉΓòÉΓòÉ 7.14.3.1. Initializing the DSOM run-time environment ΓòÉΓòÉΓòÉ
  11876.  
  11877. The first thing the server program should do is to initialize the DSOM run time 
  11878. by calling the SOMD_Init function. This causes the various DSOM run-time 
  11879. objects to be created and initialized, including the Implementation Repository 
  11880. (accessible via the global variable SOMD_ImplRepObject), which is used in the 
  11881. next initialization step. 
  11882.  
  11883.  
  11884. ΓòÉΓòÉΓòÉ 7.14.3.2. Initializing the server's ImplementationDef ΓòÉΓòÉΓòÉ
  11885.  
  11886. Next, the server program is responsible for initializing its implementationDef, 
  11887. referred to by the global variable SOMD_ImplDefObject. It is initialized to 
  11888. NULL by SOMD_Init. (For client programs it should be left as NULL.) If the 
  11889. server implementation was registered with the Implementation Repository before 
  11890. the server program was activated (as will be the case for all servers that are 
  11891. activated automatically by somdd), then the ImplementationDef can be retrieved 
  11892. from the Implementation Repository. Otherwise, the server program can register 
  11893. its implementation with the Implementation Repository dynamically (as shown in 
  11894. section 6.6, "Configuring DSOM applications"). 
  11895.  
  11896. The server can retrieve its ImplementationDef from the Implementation 
  11897. Repository by invoking the find_impldef method on SOMD_ImplRepObject.  It 
  11898. supplies, as a key, the implementation ID of the desired ImplementationDef. 
  11899.  
  11900. The following code shows how a server program might initialize the DSOM 
  11901. run-time environment and retrieve its ImplementationDef from the Implementation 
  11902. Repository. 
  11903.  
  11904. #include <somd.h> /* needed by all servers */
  11905. main(int argc, char **argv)
  11906. {
  11907.    Environment ev;
  11908.    SOM_InitEnvironment(&ev);
  11909.  
  11910. /* Initialize the DSOM run-time environment */
  11911.    SOMD_Init(&ev);
  11912.  
  11913. /* Retrieve its ImplementationDef from the Implementation
  11914.    Repository by passing its implementation ID as a key */
  11915.    SOMD_ImplDefObject =
  11916.       _find_impldef(SOMD_ImplRepObject, &ev, argv[1]);
  11917. ...
  11918. }
  11919.  
  11920.  
  11921. ΓòÉΓòÉΓòÉ 7.14.3.3. Initializing the SOM Object Adapter ΓòÉΓòÉΓòÉ
  11922.  
  11923. The next step the server must take before it is ready to accept and process 
  11924. requests from clients is to create a SOMOA object and initialize the global 
  11925. variable SOMD_SOMOAObject to point to it. This is accomplished by the 
  11926. assignment: 
  11927.  
  11928. SOMD_SOMOAObject = SOMOANew();
  11929.  
  11930. Note:  The SOMOA object is not created automatically by SOMD_Init because it is 
  11931.        only required by server processes. 
  11932.  
  11933.  After the global variables have been initialized, the server can do any 
  11934.  application-specific initialization required before processing requests from 
  11935.  clients. Finally, when the server is ready to process requests, it must call 
  11936.  the impl_is_ready method on the SOMOA: 
  11937.  
  11938.   _impl_is_ready(SOMD_SOMOAObject, &ev, SOMD_ImplDefObject);
  11939.  
  11940.  The SOMOA will then set up a communications port for incoming messages, which 
  11941.  it registers with the DSOM daemon. Once the DSOM daemon has been notified of 
  11942.  the server's port, it assists client applications in "binding" (i.e., 
  11943.  establishing a connection) to that server. 
  11944.  
  11945.  The impl_is_ready method also causes the server object, whose class is defined 
  11946.  in the server's ImplementationDef, to be created. The server object can be 
  11947.  referenced through the global variable, SOMD_ServerObject. 
  11948.  
  11949.  
  11950. ΓòÉΓòÉΓòÉ 7.14.3.4. When initialization fails ΓòÉΓòÉΓòÉ
  11951.  
  11952. It is possible that a server will encounter some error when initializing 
  11953. itself. Servers must attempt to notify DSOM that their activation failed, using 
  11954. the activate_impl_failed method. This method is called as follows: 
  11955.  
  11956. /* tell the daemon (via SOMOA) that activation failed */
  11957. _activate_impl_failed(SOMD_SOMOAObject,&ev, SOMD_ImplDefObject, rc);
  11958. Server writers should be aware, however, that until the server's 
  11959. SOMD_ImpldefObject has been initialized, it is not possible to call the 
  11960. _activate_impl_failed method on the DSOM daemon. 
  11961.  
  11962. Note:  A server program should not call activate_impl_failed once it has called 
  11963.        impl_is_ready. 
  11964.  
  11965.  
  11966. ΓòÉΓòÉΓòÉ 7.14.4. Processing requests ΓòÉΓòÉΓòÉ
  11967.  
  11968. The SOMOA is the object in the DSOM run-time environment that receives client 
  11969. requests and transforms them into method calls on local server objects. In 
  11970. order for SOMOA to listen for a request, the server program must invoke one of 
  11971. two methods on SOMD_SOMOAObject. If the server program wishes to turn control 
  11972. over to SOMD_SOMOAObject completely (that is, effectively have SOMD_SOMOAObject 
  11973. go into an infinite request-processing loop), then it invokes the 
  11974. execute_request_loop method on SOMD_SOMOAObject as follows: 
  11975.  
  11976. rc = _execute_request_loop(SOMD_SOMOAObject, &ev, SOMD_WAIT);
  11977.  
  11978. Note:  This is the way the DSOM provided "generic" server program interacts 
  11979.        with SOMD_SOMOAObject. 
  11980.  
  11981.  The execute_request_loop method takes an input parameter of type Flags. The 
  11982.  value of this parameter should be either SOMD_WAIT or SOMD_NO_WAIT. If 
  11983.  SOMD_WAIT is passed as argument, execute_request_loop will return only when an 
  11984.  error occurs. If SOMD_NO_WAIT is passed, it will return when there are no more 
  11985.  outstanding messages to be processed. SOMD_NO_WAIT is usually used when the 
  11986.  server is being used with the event manager. See "Peer vs. client-server 
  11987.  processes" in section 6.9, "Advanced Topics," for more details. 
  11988.  
  11989.  If the server wishes to incorporate additional processing between request 
  11990.  executions, it can invoke the execute_next_request method to receive and 
  11991.  execute requests one at a time: 
  11992.  
  11993.   for(;;) {
  11994.      rc = _execute_next_request(SOMD_SOMOAObject, &ev, SOMD_NO_WAIT);
  11995.      /* perform app-specific code between messages here, e.g., */
  11996.         if (!rc) numMessagesProcessed++;
  11997.   }
  11998.  
  11999.  Just like execute_request_loop, execute_next_request has a Flags argument that 
  12000.  can take one of two values: SOMD_WAIT or SOMD_NO_WAIT. If execute_next_request 
  12001.  is invoked with the SOMD_NO_WAIT flag and no message is available, the method 
  12002.  returns immediately with a return code of SOMDERROR_NoMessages. If a request 
  12003.  is present, it will execute it. Thus, it is possible to "poll" for incoming 
  12004.  requests using the SOMD_NO_WAIT flag. 
  12005.  
  12006.  
  12007. ΓòÉΓòÉΓòÉ 7.14.5. Exiting a server program ΓòÉΓòÉΓòÉ
  12008.  
  12009. When a server program exits, it should notify the DSOM run time that it is no 
  12010. longer accepting requests. This should be done whether the program exits 
  12011. normally, or as the result of an error. If this is not done, somdd will 
  12012. continue to think that the server program is active, allowing clients to 
  12013. attempt to connect to it, as well as preventing a new copy of that server from 
  12014. being activated. 
  12015.  
  12016. To notify DSOM when the server program is exiting, the deactivate_impl method 
  12017. defined on SOMOA should be called. For example, 
  12018.  
  12019.  /* tell DSOM (via SOMOA) that server is now terminating */
  12020.     _deactivate_impl(SOMD_SOMOAObject, &ev, SOMD_ImplDefObject);
  12021.  
  12022. Note:  For robustness, it would be worthwhile to add appropriate "exit 
  12023.        handlers" or "signal handlers" to your application servers that call the 
  12024.        deactivate_impl method upon abnormal program termination. This ensures 
  12025.        the the DSOM daemon is made aware of the server's termination, so that 
  12026.        client connections are no longer allowed. 
  12027.  
  12028.  Finally, at the end of a server program, the SOMD_Uninit procedure must be 
  12029.  called to free DSOM run-time objects, and to release semaphores, shared memory 
  12030.  segments, and any other system resources. 
  12031.  
  12032.  For example, the exit code in the server program might look like this: 
  12033.  
  12034.       ...
  12035.       SOMD_Uninit(&e);
  12036.       SOM_UninitEnvironment(&e);
  12037.   }
  12038.  
  12039.  Observe also the SOM_UninitEnvironment call, which frees any memory associated 
  12040.  with the specified Environment structure. 
  12041.  
  12042.  When a Windows DSOM server application receives a WM_QUIT message while 
  12043.  processing incoming requests, the execute_request_loop method will return 
  12044.  SOMDERROR_WMQUIT.  When the server receives SOMDERROR_WMQUIT, it should 
  12045.  perform its usual clean up and termination procedures. 
  12046.  
  12047.  
  12048. ΓòÉΓòÉΓòÉ 7.14.6. Managing objects in the server ΓòÉΓòÉΓòÉ
  12049.  
  12050. The following subjects are discussed in this section: 
  12051.  
  12052.      Object references, ReferenceData, and the ReferenceData table 
  12053.      Simple SOM object references 
  12054.      SOMDServer (default server-object class) 
  12055.      Creation and destruction of SOM objects 
  12056.      Mapping objects to object references 
  12057.      Hints on the use of create vs. create_constant 
  12058.      Mapping object references to objects 
  12059.      Dispatching a method 
  12060.  
  12061.  
  12062. ΓòÉΓòÉΓòÉ 7.14.6.1. Object references, ReferenceData, and the ReferenceData table ΓòÉΓòÉΓòÉ
  12063.  
  12064. One of SOMOA's responsibilities is to support the creation of object references 
  12065. (SOMDObjects). Recall from the "Stack" example discussion (in Section 6.2) that 
  12066. an object reference  is an exportable "handle" to an object and that proxies 
  12067. are examples of object references. The SOMOA interface supports three 
  12068. operations for creating object references: create, create_constant, and 
  12069. create_SOM_ref. 
  12070.  
  12071. The create and create_constant methods allow a serve to associate 
  12072. application-specific data about an object with an object reference for that 
  12073. object. This data, called reference data, is represented in a sequence of up to 
  12074. 1024 bytes of information about the object. This sequence, defined by the type 
  12075. ReferenceData, may contain the object's location, state, or any other 
  12076. characteristics meaningful to the application. Usually, ReferenceData is used 
  12077. by a server process to locate or activate an object in the server. 
  12078. ReferenceData, and hence the methods create and create_constant are usually 
  12079. only used in connection with persistent objects (objects whose lifetimes exceed 
  12080. that of the process that created them). 
  12081.  
  12082. The create method differs from the create_constant method in the following way: 
  12083. ReferenceData associated with an object reference constructed by 
  12084. create_constant is immutable whereas the the ReferenceData associated with an 
  12085. object reference created by create can be changed (via the change_id method). 
  12086. References created with create_constant return true when the method is_constant 
  12087. is invoked on them. 
  12088.  
  12089. The create method stores the ReferenceData in a ReferenceData table associated 
  12090. with the server, while create_constant maintains the ReferenceData as a 
  12091. constant part of the object reference. The ReferenceData associated with an 
  12092. object reference (whether it was constructed using create or create_constant 
  12093. can be retrieved via the SOMOA method get_id. 
  12094.  
  12095. The IDL SOMOA interface declarations of create, create_constant, get_id, and 
  12096. change_id, and the SOMDObject interface declaration of is_constant are 
  12097. presented below. 
  12098.  
  12099. /* From the SOMOA interface */
  12100.  
  12101.    sequence <octet,1024> Referencedata;
  12102.    SOMDObject create(in ReferenceData id, in InterfaceDef intf,
  12103.                      in ImplementationDef impl);
  12104.  
  12105.    SOMDObject create_constant(in ReferenceData id,
  12106.                               in InterfaceDef intf,
  12107.                               in ImplementationDef impl);
  12108.  
  12109.    ReferenceData get_id(in SOMDObject objref);
  12110.  
  12111.    void change_id(in SOMDObject objref, in ReferenceData id);
  12112.  
  12113. /* From the SOMDObject interface */
  12114.  
  12115.    boolean is_constant();
  12116.  
  12117. An example of how ReferenceData can be used by an application follows the 
  12118. description of SOMDServer objects in the next section 
  12119.  
  12120.  
  12121. ΓòÉΓòÉΓòÉ 7.14.6.2. Simple SOM object references ΓòÉΓòÉΓòÉ
  12122.  
  12123. In order to efficiently support the generation and interpretation of references 
  12124. to SOM objects, the SOMOA defines another method called create_SOM_ref. 
  12125.  
  12126. The create_SOM_ref method creates a simple DSOM reference (SOMDObject) for a 
  12127. local SOM object. The reference is "special" in that, unlike create and 
  12128. create_constant there is no user-supplied ReferenceData associated with the 
  12129. object and because the reference is only valid while the SOM object exists in 
  12130. memory. The SOMObject to which it refers can be retrieved via the 
  12131. get_SOM_object method. The is_SOM_ref method can be used to tell if the 
  12132. reference was created using create_SOM_ref or not. The IDL declarations for 
  12133. create_SOM_ref, get_SOM_object, and is_SOM_ref are displayed below: 
  12134.  
  12135. /* from SOMOA's interface */
  12136.  
  12137.    SOMDObject create_SOM_ref(in SOMObject somobj,
  12138.                              in ImplementationDef impl);
  12139.  
  12140.    SOMObject get_SOM_object(in SOMDObject somref);
  12141.  
  12142. /* from SOMDObject's interface */
  12143.  
  12144.    boolean is_SOM_ref();
  12145.  
  12146.  
  12147. ΓòÉΓòÉΓòÉ 7.14.6.3. SOMDServer (default server-object class) ΓòÉΓòÉΓòÉ
  12148.  
  12149. Every server has a server object that implements three kinds of activities: 
  12150.  
  12151.      Creation and destruction of SOM objects 
  12152.  
  12153.      Mapping between SOMObjects and SOMDObjects, and 
  12154.  
  12155.      Dispatching methods on SOM objects 
  12156.  
  12157.  Additional, application-specific server methods (for initialization, server 
  12158.  control, etc.) can be defined in a subclass of the SOMDServer class. The class 
  12159.  of the server object to be used with a server is contained in the server's 
  12160.  ImplementationDef. 
  12161.  
  12162.  Following are the IDL declarations of the SOMDServer operations: 
  12163.  
  12164.   // methods called by a client
  12165.  
  12166.      SOMObject somdCreateObj(in Identifier objclass, in string hints)
  12167.  
  12168.      void somdDeleteObj(in SOMObject somobj);
  12169.  
  12170.      SOMClass somdGetClassObj(in Identifier objclass);
  12171.  
  12172.   // methods called by SOMOA
  12173.  
  12174.      SOMDObject somdRefFromSOMObj(in SOMObject somobj);
  12175.  
  12176.      SOMObject somdSOMObjFromRef(in SOMDObject objref);
  12177.  
  12178.      void somdDispatchMethod(in SOMObject somobj,
  12179.                              out somToken retValue,
  12180.                              in somId methodId,
  12181.                              in va_list ap);
  12182.  
  12183.  
  12184. ΓòÉΓòÉΓòÉ 7.14.6.4. Creation and destruction of SOM objects ΓòÉΓòÉΓòÉ
  12185.  
  12186. The SOMDServer class defines methods for the basic creation of SOM objects in 
  12187. the server process (somdCreateObj), and for finding the SOM class object for a 
  12188. specified class (somdGetClassObj). With somdGetClassObj, a client can get a 
  12189. proxy to a class object on the server, so that methods introduced in the 
  12190. class's metaclass (for example, class-specific constructors, etc.) may be 
  12191. invoked directly on the class object. Examples of client use of these two 
  12192. methods were presented earlier in Sections 6.2 and 6.3. 
  12193.  
  12194. With somdDeleteObj, the client can involve the server object in object 
  12195. destruction. (The methods somdTargetFree and somFree are defined on the object 
  12196. themselves and do not involve the server object.) Involving the server object 
  12197. in object creation and destruction can be important for applications that need 
  12198. more control over how objects are created and destroyed, or if the application 
  12199. needs to keep track of an object's creation and destruction. 
  12200.  
  12201.  
  12202. ΓòÉΓòÉΓòÉ 7.14.6.5. Mapping objects to object references ΓòÉΓòÉΓòÉ
  12203.  
  12204. SOMDServer also defines methods that implement mappings between SOMObjects and 
  12205. SOMDObjects (object references) and a method for dispatching method calls on 
  12206. SOM objects. These methods are used by the SOM Object Adapter (SOMOA) when 
  12207. converting remote requests into method calls and results into responses. 
  12208.  
  12209. Recall from the topic "Proxy objects" in Section 6.3, "Basic Client 
  12210. Programming", that servers return proxies to remote objects as method results, 
  12211. not the remote objects themselves. Recall also that class libraries need not be 
  12212. designed to be distributed (that is, the code that implements the classes need 
  12213. not be aware of the existence of proxy objects at all). Thus, it is up to the 
  12214. DSOM run-time environment to ensure that proxies, rather than remote objects, 
  12215. are returned to clients. The SOMD_SOMOAObject and SOMD_ServerObject work 
  12216. together to perform this service. Whenever a result from a remote method call 
  12217. includes a SOMObject, the SOMD_SOMOAObject invokes the somdRefFromSOMObj method 
  12218. on SOMD_ServerObject, asking it to create a SOMDObject from the SOMObject. 
  12219.  
  12220. The default implementation (i.e., SOMDServer's implementation) for 
  12221. somdRefFromSOMObj uses the create_SOM_ref method to return a "simple" reference 
  12222. for the SOMObject. Application-specific server objects (instances of a subclass 
  12223. of SOMDServer) may elect to use create or create_constant to construct the 
  12224. object reference if the application requires Reference Data to be stored. 
  12225.  
  12226.  
  12227. ΓòÉΓòÉΓòÉ 7.14.6.6. Hints on the use of create vs. create_constant ΓòÉΓòÉΓòÉ
  12228.  
  12229. Enough context now exists so that the following question may be answered: "If 
  12230. object references constructed with create support changeable ReferenceData, but 
  12231. object references constructed with create_constant do not, why would I ever 
  12232. want to use create_constant?" 
  12233.  
  12234. Invocations of create add entries to a table called the ReferenceData Table. 
  12235. The ReferenceData Table is persistent; that is, ReferenceData saved in it 
  12236. persists between server activations. Two calls to create with the same 
  12237. arguments do not return the same SOMDObject (per CORBA 1.1 specifications) That 
  12238. is, if create is called twice with the same arguments, two entries in the 
  12239. ReferenceData Table will be created. If a server using create wishes to avoid 
  12240. cluttering up the ReferenceData Table with multiple references to the same 
  12241. object, it must maintain a table of its own to keep track of the references it 
  12242. has created to avoid calling create twice with the same arguments. 
  12243.  
  12244. The create_constant method stores the ReferenceData as part of the SOMDObject's 
  12245. state; that is, it does not add entries to the ReferenceData Table. The 
  12246. create_constant method, then, might be used by a server that does not want to 
  12247. maintain a table of references nor pay the penalty of cluttering up the 
  12248. ReferenceData Table with multiple entries. 
  12249.  
  12250.  
  12251. ΓòÉΓòÉΓòÉ 7.14.6.7. Mapping object references to objects ΓòÉΓòÉΓòÉ
  12252.  
  12253. The somdSOMObjFromRef method maps SOMDObjects to SOMObjects. This method is 
  12254. invoked by  SOMOA on the server object, for each object reference found as a 
  12255. parameter in a request. 
  12256.  
  12257. The default implementation for somdSOMObjFromRef returns the address of the 
  12258. SOMObject for which the specified object reference was create (using the 
  12259. somdRefFromSOMObj method). If the object reference was not created by the same 
  12260. server process, then an exception (BadObjref) is raised. The default 
  12261. implementation does not, however, verify that the original object (for which 
  12262. the object reference was created) still exists. If the original object has been 
  12263. deleted (for example, by another client program), then the address returned 
  12264. will not represent a valid object, and any methods invoked on that object 
  12265. pointer will result in server failure. Note: The default implementation of 
  12266. somdSOMObjFromRef does not check that the original object address is still 
  12267. valid because the check is very expensive and seriously degrades server 
  12268. performance. 
  12269.  
  12270. To have a server verify that all results from somdSOMObjFromRef represent valid 
  12271. objects, server programmers can subclass SOMDServer and override the 
  12272. somdSOMObjFromRef method to perform a validity check on the result (using the 
  12273. somIsObj function). For example, a subclass "MySOMDServer" of SOMDServer could 
  12274. implement the somdSOMObjFromRef method as follows: 
  12275.  
  12276. SOM_Scope SOMObject SOMLINK somdSOMObjFromRef(MySOMDServer somSelf,
  12277.                                               Environment * ev,
  12278.                                               SOMDObject objref)
  12279. {
  12280.     SOMObject obj;
  12281.     StExcep_INV_OBJREF *ex;
  12282.  
  12283.     /* MySOMDServerData *somThis = MySOMDServerGetData(somSelf); */
  12284.     MySOMDServerMethodDebug(*MySOMDServer*, *somdSOMObjFromRef");
  12285.  
  12286.     obj = MySOMDServer_parent_SOMDServer_somdSOMObjFromRef(somSelf,
  12287.                                                     ev, objref);
  12288.     if (somIsObj(obj))
  12289.         return (obj);
  12290.     else {
  12291.         ex = (StExcep_INV_OBJREF *)
  12292.               SOMMalloc(sizeof(StExcep_INV_OBJREF));
  12293.         ex->minor = SOMDERROR_BadObjref;
  12294.         ex->completed = NO;
  12295.         somSetException(ev, USER_EXCEPTION,
  12296.                         ex_StExcep_INV_OBJREF, ex);
  12297.         return (NULL);
  12298.     }
  12299. }
  12300.  
  12301.  
  12302. ΓòÉΓòÉΓòÉ 7.14.6.8. Dispatching a method ΓòÉΓòÉΓòÉ
  12303.  
  12304. After SOMOA (with the help of the local server object) has resolved all the 
  12305. SOMDObjects present in a request, it is ready to invoke the specified method on 
  12306. the target. Rather than invoking somDispatch directly  on the target, it calls 
  12307. the somdDispatchMethod method on the server object. The parameters to 
  12308. somdDispatchMethod are the same as the parameters for SOMObject::somDispatch 
  12309. (see the SOM Programming Reference for a complete description). 
  12310.  
  12311. The default implementation for somdDispatchMethod in SOMServer simply invokes 
  12312. SOMObject::somDispatch on the specified target object with the supplied 
  12313. arguments. The reason for this indirection through the server object is to give 
  12314. the server object a chance to intercept method calls coming into the server 
  12315. process, if desired. 
  12316.  
  12317.  
  12318. ΓòÉΓòÉΓòÉ 7.14.7. Identifying the source of a request ΓòÉΓòÉΓòÉ
  12319.  
  12320. CORBA 1.1 specifies that a Basic Object Adapter should provide a facility for 
  12321. identifying the principal (or user) on whose behalf a request is being 
  12322. performed. The get_principal method, defined by BOA and impleented by SOMOA 
  12323. returns a Principal object, which identifies the caller of a particular method. 
  12324. From this information, an application can perform access control checking. 
  12325.  
  12326. In CORBA 1.1, the interface to Principal is not defined, and is left up to the 
  12327. ORB implementation. In the current release of DSOM, a Principal object is 
  12328. defined to have two attributes: 
  12329.  
  12330.  userName (string)   Identifies the name of the user who invoked a request. 
  12331.  
  12332.  hostName (string)   Identifies the name of the host from which the request 
  12333.                      originated. 
  12334.  
  12335.  Currently, the value of the UserName attribute is obtained from the USER 
  12336.  environment variable in the calling process. Likewise, the hostName attribute 
  12337.  is obtained from the HOSTNAME environment variable. This facility is intended 
  12338.  to provide basic information about the source of a request, and currently, is 
  12339.  not based on any specific authentication (i.e., "login") scheme. More rigorous 
  12340.  authentication and security mechanisms will be considered for future DSOM 
  12341.  implementations. 
  12342.  
  12343.  The IDL prototype for the get_principal method, defined on BOA (SOMOA) is as 
  12344.  follows: 
  12345.  
  12346.   Principal  get_principal (in SOMDObject obj,
  12347.                              in Environment *req_ev);
  12348.  
  12349.  This call will typically be made either by the target object or by the server 
  12350.  object, when a method call is received. The get_principal method uses the 
  12351.  Environment structure associated with the request, and an object reference for 
  12352.  the target object, to produce a Principal object that define the request 
  12353.  initiator. 
  12354.  
  12355.  Note:  CORBA 1.1 defines a "tk_Principal" TypeCode which is used to identify 
  12356.         the type of Principal object arguments in requests, in case special 
  12357.         handling is needed when building the request. Currently, DSOM does not 
  12358.         provide any special handling of objects of type "tk_Principal"; they 
  12359.         are treated like any other object. 
  12360.  
  12361.  
  12362. ΓòÉΓòÉΓòÉ 7.14.8. Compiling and linking servers ΓòÉΓòÉΓòÉ
  12363.  
  12364. The server program must include the "somd.h" header file. Server programs must 
  12365. link to the SOMobjects Toolkit library: "somtk.lib" 
  12366.  
  12367. For more information, see the topic "Compiling and linking" in Chapter 5, 
  12368. "Implementing Classes in SOM." 
  12369.  
  12370.  
  12371. ΓòÉΓòÉΓòÉ 7.15. Implementing Classes ΓòÉΓòÉΓòÉ
  12372.  
  12373. DSOM has been designed to work with a wide range of object implementations, 
  12374. including SOM class libraries as well as non-SOM object implementations. This 
  12375. section describes the necessary steps in using SOM classes or non-SOM object 
  12376. implementations with DSOM. 
  12377.  
  12378.  
  12379. ΓòÉΓòÉΓòÉ 7.15.1. Using SOM class libraries ΓòÉΓòÉΓòÉ
  12380.  
  12381. It is quite easy to use SOM classes in multi-process DSOM-based applications as 
  12382. exemplified by the sample DSOM application presented in section 6.2, "A Simple 
  12383. DSOM Example". In fact, in many cases, existing SOM class libraries may be used 
  12384. in DSOM applications without requiring any special coding or recoding for 
  12385. distribution. This is possible through the use of DSOM's generic server 
  12386. program, which uses SOM and the SOM Object Adapter (SOMOA) to load SOM class 
  12387. libraries on demand, whenever an object of a particular class is created or 
  12388. activated. 
  12389.  
  12390. The topic "Registering servers and classes" in section 6.6 "Configuring DSOM 
  12391. Applications" discusses how to register a server implementation consisting of a 
  12392. DSOM generic server process and one or more SOM class libraries. 
  12393.  
  12394.  
  12395. ΓòÉΓòÉΓòÉ 7.15.1.1. Role of DSOM generic server program ΓòÉΓòÉΓòÉ
  12396.  
  12397. The generic server program provides basic server functionality: it continuously 
  12398. receives and executes requests (via an invocation of the SOMOA's 
  12399. execute_request_loop method), until the server is stopped. Some requests result 
  12400. in the creation of SOM objects; the generic server program will find and load 
  12401. the DLL for the object's class automatically, if it has not already been 
  12402. loaded. 
  12403.  
  12404. When generic server program functionality is not sufficient for the particular 
  12405. application, application-specific server programs can be developed. For 
  12406. example, some applications may want to interact with a user or I/O device 
  12407. between requests. The previous section, entitled "Basic Server Programming," 
  12408. discussed the steps involved in writing a server program. 
  12409.  
  12410.  
  12411. ΓòÉΓòÉΓòÉ 7.15.1.2. Role of SOM Object Adapter ΓòÉΓòÉΓòÉ
  12412.  
  12413. The SOM Object Adapter is DSOM's standard object adapter. It provides basic 
  12414. support for receiving and dispatching requests on objects. As an added feature, 
  12415. the SOMOA and the server process's server object collaborate t automate the 
  12416. task of converting SOM object pointers into DSOM object references, and vice 
  12417. versa. That is, whenever an object pointer is passed as an argument to a 
  12418. method, the SOMOA and the server object convert the pointer to a DSOM bject 
  12419. reference (since a pointer to an object is meaningless outside the object's 
  12420. address space). 
  12421.  
  12422.  
  12423. ΓòÉΓòÉΓòÉ 7.15.1.3. Role of SOMDServer ΓòÉΓòÉΓòÉ
  12424.  
  12425. The server process's server object (whose default class is SOMDServer) is 
  12426. responsible for creating/destroying objects on the server via somdCreateObj, 
  12427. somdGetClassObj, and somdDeleteObj, for mapping between object references 
  12428. (SOMDObjects) and SOMObjects via somdRefFromSOMObj and somdSOMObjFromRef, and 
  12429. for dispatching remote requests to server process objects via 
  12430. somdDispatchMethod. These last three methods are invoked on the server object 
  12431. by the SOMOA when objects are to be returned to clients, when incoming requests 
  12432. contain object references, and when the method is ready to be dispatched, 
  12433. respectively. By partitioning out these mapping and dispatching functions into 
  12434. the server object, the application can more easily customize them, without 
  12435. having to build object adapter subclasses. 
  12436.  
  12437. SOMDServer can be subclassed by applications that want to manage object 
  12438. location, object activation, and method dispatching. An example of such an 
  12439. application (which provides a server class implementation for persistent SOM 
  12440. objects) is shown in section 6.4, "Basic Server Programming." 
  12441.  
  12442. These features of SOMOA and SOMDServer make it possible to take existing OM 
  12443. classes, which have been written for a single-address space environment, and 
  12444. use them unchanged in a DSOM application. More information on the SOMOA and 
  12445. server objects can be found in the "Basic Server Programming" section. 
  12446.  
  12447.  
  12448. ΓòÉΓòÉΓòÉ 7.15.1.4. Implementation constraints ΓòÉΓòÉΓòÉ
  12449.  
  12450. The generic server program (somdsvr), the SOMOA, and the SOMDServer make it 
  12451. easy to use SOM classes with DSOM. However, if there are any parts of the class 
  12452. implementation that were written expecting a single-process environment, the 
  12453. class may have to be modified to behave properly in a client/server 
  12454. environment. Some common implementation practices to avoid are listed below 
  12455.  
  12456.      Printing to standard output. Any text printed by a method will appear at 
  12457.       the server, as opposed to the client. In fact, the server may not be 
  12458.       attached to a text display device or window, so the text may be lost 
  12459.       completely. It is preferred that any textual output generated by a method 
  12460.       be returned as an output string. 
  12461.  
  12462.       Note:  Passing textual output between the client program and the called 
  12463.              method via an "inout string" parameter is strongly discouraged. As 
  12464.              discussed in the CORBA 1.1 specification (page 94), the size of 
  12465.              the output string is constrained by the size of the input string. 
  12466.              If there was no input string value, the size of the output string 
  12467.              would be constrained to 0 bytes. Instead, it is preferred that 
  12468.              textual data be returned either as an output string (DSOM provides 
  12469.              the storage), or by passing a character array buffer (client 
  12470.              provides the storage). 
  12471.  
  12472.      Creating and deleting objects. Methods that create or delete objects may 
  12473.       have to be modified if the created objects are intended to be remote. The 
  12474.       calls to create local objects are different than the calls to create 
  12475.       remote objects. 
  12476.  
  12477.      Using pointers to client-allocated memory in instance variables. Consider 
  12478.       the following example: A class has a method that accepts a pointer to a 
  12479.       data value created by the client (e.g., a string or a struct), and simply 
  12480.       stores the pointer in an instance variable or attribute. However, in 
  12481.       DSOM, the called method is passed a pointer to a copy of the value (in 
  12482.       the request message body), but the copy is freed at the end of the 
  12483.       request. If the data value is meant to persist between requests, the 
  12484.       object is responsible for making its own copy of it. (The implementation 
  12485.       of the "_set_printerName" method in the topic "Wrapping a printer API" 
  12486.       later in this section is an example of a method performing such a copy.) 
  12487.  
  12488.      Using "procedure" methods. Methods having the procedure SOM IDL modifier 
  12489.       cannot be invoked remotely using DSOM.  This is because these "methods" 
  12490.       are called directly, rather than by the normal method resolution 
  12491.       mechanisms on which DSOM relies. 
  12492.  
  12493.  In addition to those coding practices which simply do not "port" to a 
  12494.  distributed environment, there are a few other restrictions that are imposed 
  12495.  by DSOM's (current) implementation. 
  12496.  
  12497.      Using parameter types not supported by DSOM. DSOM can make remote 
  12498.       invocations only of methods whose parameter types are among the following 
  12499.       IDL types:  basic types short, long, unsigned short, unsigned long,float, 
  12500.       double, char, boolean, octet), enum struct, union, sequence, string, 
  12501.       array, any, and object (an interface name, designating a pointer to an 
  12502.       object that supports that interface).  The members of a struct, union, 
  12503.       sequence, or array, and the value of any any, must also be from the above 
  12504.       list of supported DSOM types. 
  12505.  
  12506.       In addition to the above types, DSOM also supports method parameters of 
  12507.       type pointer to one of the above types (for example,  long*).  Pointers 
  12508.       to pointers are not supported, however, and pointers embedded within one 
  12509.       of the above types (for example, a pointer within a struct) are not 
  12510.       supported.  The "void*" type is also not supported.  Currently, DSOM has 
  12511.       the limitation that NULL pointer values cannot be returned as inout or 
  12512.       out method arguments, although it is expected that this limitation will 
  12513.       be addressed in the future release. 
  12514.  
  12515.       Types declared as SOMFOREIGN types are not currently supported by DSOM. 
  12516.  
  12517.      Packing of structures used as method arguments. If a compiler option is 
  12518.       used to pack or optimize storage of structs (including reordering of 
  12519.       struct members) or unions, it is important to indicate the exact 
  12520.       alignment of the structures using alignment modifiers expressed in the 
  12521.       implementation section of the IDL file. This information must then be 
  12522.       updated in the Interface Repository. 
  12523.  
  12524.  Some applications may need to associate specific identification information 
  12525.  with an object, to support application-specific object location or activation. 
  12526.  In that case, an application server should create object references 
  12527.  explicitly, using the create or create_constant method in SOMOA. A logical 
  12528.  place to put these calls is in a subclass of SOMDServer, as it is the server 
  12529.  object that is responsible for producing/activating objects from object 
  12530.  references. 
  12531.  
  12532.  
  12533. ΓòÉΓòÉΓòÉ 7.15.2. Using other object implementations ΓòÉΓòÉΓòÉ
  12534.  
  12535. As an Object Request Broker, DSOM must support a wide range of object 
  12536. implementations, including non-SOM implementations. For example, in a print 
  12537. spooler application, the implementation of a print queue object may be provided 
  12538. by the operating system, where the methods on the print queue are executable 
  12539. programs or system commands. As another example, consider an application that 
  12540. uses a large, existing class library that is not implemented using SOM. 
  12541.  
  12542. In each of these examples, the application must participate  in object 
  12543. identification, activation, initialization, and request dispatching. Each 
  12544. server supplies a server object (derived from SOMDServer) that works in 
  12545. conjunction with the SOMOA for this purpose. 
  12546.  
  12547.  
  12548. ΓòÉΓòÉΓòÉ 7.15.2.1. Wrapping a printer API ΓòÉΓòÉΓòÉ
  12549.  
  12550. Presented below is a simple example showing how an existing API could be 
  12551. "wrapped" as SOM objects. The API is admittedly trivial, but it is hoped that 
  12552. readers understand this simple example well enough to create more sophisticated 
  12553. applications of their own. This example is given for OS/2, rather than for 
  12554. Windows 95 /NT. Again, it is intented to serve as a simple conceptual framework 
  12555. that 
  12556.  
  12557.  will serve as a basis for developing more sophisticated "wrappers".
  12558. The "API" wrapped in this example is comprised of two system calls. 
  12559.  
  12560.  
  12561. The first one asks for a file to be printed on a specific printer: 
  12562.  
  12563. print /D:<printerName> <filename>
  12564.  
  12565. The second one asks for the file currently being printed on device 
  12566. <printerName> to be cancelled. 
  12567.  
  12568. print /D:<printerName> /C
  12569.  
  12570. Two IDL interfaces are declared in the module "PrinterModule": "Printer" and 
  12571. "PrinterServer". The "Printer" interface wraps the two system calls. The 
  12572. "PrinterServer" interface describes a subclass of SOMDServer. 
  12573. "PrinterModule::PrinterServer" will be the class of the server object in the 
  12574. print-server application. 
  12575.  
  12576. #include <somdserv.idl>
  12577.  
  12578. module PrinterModule {
  12579.   interface Printer : SOMObject {
  12580.     attribute string printerName;
  12581.     void print(in string fname);
  12582.     void cancel();
  12583.     #ifdef __SOMIDL__
  12584.     implementation {
  12585.       printerName: noset;   // memory to be allocated
  12586.       };
  12587.     #endif
  12588.   };
  12589.  
  12590.   interface PrinterServer :SOMDServer{
  12591.     #ifdef __SOMIDL__
  12592.     implementation {
  12593.       somdCreateObj: override;
  12594.       somdRefFromSOMObj: override;
  12595.       somdSOMObjFromRef: override;
  12596.       };
  12597.     #endif
  12598.   };
  12599.  
  12600. };
  12601.  
  12602. Note that the "Printer" interface defines one attribute, "printerName", that 
  12603. will be used to identify the printer. It will be set when a "Printer" is 
  12604. created. Printer's two operations, "print" and "cancel", correspond to the two 
  12605. system commands the interface is encapsulating. The "PrinterServer" interface 
  12606. does not introduce any new attributes or operations. It does specify that three 
  12607. of SOMDServer's methods will have their implementations overridden. 
  12608.  
  12609. The next three method procedures show how the "Printer" interface is 
  12610. implemented for the "_set_printerName", "print", and "cancel" methods. Recall 
  12611. (from the earlier topic "Implementation constraints") that "_set" methods for 
  12612. attributes must be explicitly implemented in order to allocate their memory, if 
  12613. data values need to persist between DSOM requests. 
  12614.  
  12615. SOM_Scope void  SOMLINK PrinterModule_Printer_set_printerName(
  12616.  PrinterModule_Printer somSelf, Environment *ev, string printerName)
  12617. {
  12618.     PrinterModule_PrinterData *somThis =
  12619.       PrinterModule_PrinterGetData(somSelf);
  12620.  
  12621.     if (_printerName) SOMFree(_printerName);
  12622.     _printerName = (string)SOMMalloc(strlen(printerName) + 1);
  12623.     strcpy(_printerName, printerName);
  12624. }
  12625.  
  12626.  
  12627. SOM_Scope void  SOMLINK PrinterModule_Printerprint(
  12628.  PrinterModule_Printer somSelf, Environment *ev, string fname)
  12629. {
  12630.     long rc;
  12631.     PrinterModule_PrinterData *somThis =
  12632.       PrinterModule_PrinterGetData(somSelf);
  12633.     string printCommand = (string)
  12634.       SOMMalloc(strlen(_printerName) + strlen(fname) + 10 + 1);
  12635.  
  12636.     sprintf(printCommand,"print /D:%s %s",_printerName,fname);
  12637.     rc = system(printCommand);
  12638.     if (rc) raiseException(ev,rc);
  12639. }
  12640.  
  12641.  
  12642. SOM_Scope void  SOMLINK PrinterModule_Printercancel(
  12643.  PrinterModule_Printer somSelf, Environment *ev)
  12644. {
  12645.     long rc;
  12646.     PrinterModule_PrinterData *somThis =
  12647.       PrinterModule_PrinterGetData(somSelf);
  12648.     string printCommand =
  12649.       (string) SOMMalloc(strlen(_printerName) + 12 + 1);
  12650.  
  12651.     sprintf(printCommand,"print /D:%s /C",_printerName);
  12652.     rc = system(printCommand);
  12653.     if (rc) raiseExeception(ev,rc);
  12654. }
  12655.  
  12656. Note:  The implementation of the "raiseException" procedure shown in the 
  12657.        example above must be provided by the application. However, it is not 
  12658.        shown in this example. 
  12659.  
  12660.  The three method procedures that implement the "PrinterServer" interface's 
  12661.  three overridden methods of SOMServer are very similar to the method 
  12662.  procedures of the "MyPServer" server-object class presented in the previous 
  12663.  section (6.4), and therefore have not been shown here. 
  12664.  
  12665.  
  12666. ΓòÉΓòÉΓòÉ 7.15.3. Parameter memory management ΓòÉΓòÉΓòÉ
  12667.  
  12668. There are five SOM IDL modifiers available for specifying the memory-management 
  12669. policy for the parameters of a method (regardless of whether the caller or the 
  12670. object owns the parameters' memory after the method is invoked). These 
  12671. modifiers are: 
  12672.  
  12673.   memory_management,  caller_owns_result,  caller_owns_parameters, 
  12674.  
  12675.     object_owns_result, and  object_owns_parameters.
  12676.  
  12677. See the section entitled "Implementation Statements" in Chapter 4, "SOM IDL and 
  12678. the SOM Compiler," for a complete description of these modifiers and their 
  12679. meanings. Note that the memory-management policy for a particular parameter 
  12680. applies to the parameter and all the memory embedded within it (for example, if 
  12681. a struct is owned by the caller, then so are all the struct's members). 
  12682.  
  12683. When a class contains the memory_management = corba SOM IDL modifier, this 
  12684. signifies that all methods introduced by the class follow the CORBA 
  12685. specification for parameter memory management, except where a particular method 
  12686. has an explicit modifier  (object_owns_result or object_owns_parameters) that 
  12687. indicates otherwise. For a description of the CORBA specification, see the 
  12688. earlier subtopic entitled "The CORBA policy for parameter memory management" 
  12689. (under the topic "Memory Management" in Section 6.3 of this chapter). 
  12690.  
  12691.  
  12692. ΓòÉΓòÉΓòÉ 7.15.4. Building and registering class libraries ΓòÉΓòÉΓòÉ
  12693.  
  12694. The generic server uses SOM's run-time facilities to load class libraries 
  12695. dynamically. Thus, dynamically linked libraries (DLLs) should be created for 
  12696. the classes, just as they would be for non-distributed SOM-based applications. 
  12697. For more information, see the topic Creating a SOM class library in Chapter 5 
  12698. "Implementing classes in SOM." 
  12699.  
  12700. During the development of the DLL, it is important to remember the following 
  12701. steps: 
  12702.  
  12703.      Export a routine called SOMInitModule in the DLL, which will be called by 
  12704.       SOM to initialize the class objects implemented in that library. 
  12705.       SOMInitModule should contain a <className>NewClass call for each class in 
  12706.       the DLL. 
  12707.  
  12708.      For each class in the DLL, specify the DLL name in the class's IDL file. 
  12709.       The DLL name is specified using the dllname=<name> modifier in the 
  12710.       implementation statement of the interface definition. If not specified, 
  12711.       the DLL filename is assumed to be the same as the class name. 
  12712.  
  12713.      For each class in the DLL, compile the IDL description of the class into 
  12714.       the Interface Repository. This is accomplished by invoking the following 
  12715.       command syntax: 
  12716.  
  12717.  
  12718.                     sc -sir -u stack.idl
  12719.  
  12720.       Note:  If the classes are not compiled into the Interface Repository, 
  12721.              DSOM will generate a run-time error (30056: 
  12722.              SOMDERROR_BadDescriptor) when an attempt is made to lookup the 
  12723.              signature of a method in the class (for example, on a method 
  12724.              call). 
  12725.  
  12726.      Put the DLL in one of the directories or listed in PATH for Windows. AIX, 
  12727.       and Windows.) 
  12728.  
  12729.  
  12730. ΓòÉΓòÉΓòÉ 7.16. Configuring DSOM Applications ΓòÉΓòÉΓòÉ
  12731.  
  12732. The following subjects are discussed in this section: 
  12733.  
  12734.      Preparing the environment 
  12735.      Registering class interfaces 
  12736.      Registering servers and classes 
  12737.      The 'regimpl', registration utility 
  12738.      Programmatic interface to the Implementation Repository 
  12739.  
  12740.  
  12741. ΓòÉΓòÉΓòÉ 7.16.1. Preparing the environment ΓòÉΓòÉΓòÉ
  12742.  
  12743. Some environment variables must be defined before running DSOM. 
  12744.  
  12745.  HOSTNAME=<name>                   Each machine that is running DSOM must have 
  12746.                                    its HOSTNAME variable set. For Workstation 
  12747.                                    DSOM; <name> must be set to "localhost". 
  12748.  
  12749.  USER=<name>                       USER specifies the name of the DSOM user 
  12750.                                    running a client program. 
  12751.  
  12752.  SOMIR=<file(s)>                   SOMIR specifies a list of files (separated 
  12753.                                    by a semicolon ) which together make up the 
  12754.                                    Interface Repository. See Chapter 7, "The 
  12755.                                    Interface Repository Framework," for more 
  12756.                                    information on how to set this variable. 
  12757.  
  12758.                                    Note:  For DSOM, it is preferable to use 
  12759.                                           full pathnames in the list of IR 
  12760.                                           files, since the IR will be shared by 
  12761.                                           several programs that may not all be 
  12762.                                           started in the same directory. 
  12763.  
  12764.  SOMDDIR=<directory>               SOMDDIR specifies the directory where 
  12765.                                    various DSOM files should be located, 
  12766.                                    including the Implementation Repository 
  12767.                                    files. See the later section in this chapter 
  12768.                                    entitled "Registering servers and classes" 
  12769.                                    for more information. 
  12770.  
  12771.                                    Note:  If this value is not set, DSOM will 
  12772.                                           attempt to use a default directory: 
  12773.                                           and %SOMBASE%\ETC\DSOM 
  12774.  
  12775.  SOMDPORT=<integer>                In DSOM, servers, clients and DSOM daemons 
  12776.                                    communicate with each other using a 
  12777.                                    "sockets" abstraction. In particular DSOM 
  12778.                                    clients establish connections to DSOM 
  12779.                                    servers by communicating with the DSOM 
  12780.                                    daemon, somdd, running on each server 
  12781.                                    machine. The daemon is designed to listen 
  12782.                                    for client requests on a well-known port. 
  12783.  
  12784.                                    Normally, somdd will look in the 
  12785.                                    %ETC%\SERVICES file for its well-known port 
  12786.                                    number. However, if the user has set the 
  12787.                                    SOMDPORT environment variable, the value of 
  12788.                                    SOMDPORT will be used and the "services" 
  12789.                                    file will not be consulted. The user should 
  12790.                                    pick a 16-bit integer that is not likely to 
  12791.                                    be in use by another application (check the 
  12792.                                    "services" file for ports reserved for use 
  12793.                                    on your machine). Typically, values below 
  12794.                                    1024 are reserved and should not  be used. 
  12795.  
  12796.                                    Note:  If there is no "services" file and 
  12797.                                           the SOMDPORT environment variable is 
  12798.                                           not set, DSOM will use a default port 
  12799.                                           number (currently 9393). 
  12800.  
  12801.  SOMDTIMEOUT=<integer>             SOMDTIMEOUT specifies how long a receiver 
  12802.                                    should wait for a message. The value should 
  12803.                                    be expressed in seconds. The default value 
  12804.                                    is 600 seconds (10 minutes). 
  12805.  
  12806.  SOMDDEBUG=<integer>               SOMDDEBUG may optionally be set to enable 
  12807.                                    DSOM run-time error messages. If set to 0, 
  12808.                                    error reporting is disabled. If set to 1, 
  12809.                                    error reporting is enabled. Error reports 
  12810.                                    may be directed to the file named by 
  12811.                                    SOMDMESSAGELOG, if set. 
  12812.  
  12813.  SOMDMESSAGELOG=<file>             SOMDMESSAGELOG may optionally be set to the 
  12814.                                    name of a file where DSOM run-time error 
  12815.                                    messages are recorded. If not set, error 
  12816.                                    messages will be reported on the standard 
  12817.                                    output device. 
  12818.  
  12819.  SOMDNUMTHREADS=<integer>          SOMDNUMTHREADS may optionally be set to the 
  12820.                                    maximum number of requests threads created 
  12821.                                    per server.  If SOMDNUMTHREADS is not set, 
  12822.                                    then a separate thread will be created for 
  12823.                                    each request. 
  12824.  
  12825.  
  12826. ΓòÉΓòÉΓòÉ 7.16.2. Registering class interfaces ΓòÉΓòÉΓòÉ
  12827.  
  12828. DSOM relies heavily on the Interface Repository for information on method 
  12829. signatures (that is, a description of the method's parameters and return 
  12830. value). It is important to compile the IDL for all application classes into the 
  12831. IR before running the application. 
  12832.  
  12833. For each class in the DLL, compile the IDL description of the class into the 
  12834. Interface Repository. This is accomplished by invoking the following command 
  12835. syntax: 
  12836.  
  12837.     sc -sir -u stack.idl
  12838.     .*(on AIX or OS/2)
  12839.  
  12840. If the default SOM IR (supplied with the SOMobjects Toolkit and Run times) is 
  12841. not used by the application, the user's IR must include the interface 
  12842. definitions for: 
  12843.  
  12844.      the Sockets class 
  12845.  
  12846.      the server class (derived from SOMDServer), and 
  12847.  
  12848.      the definitions of the standard DSOM exceptions (found in file 
  12849.       "stexcep.idl") that may be returned by a method call. 
  12850.  
  12851.  
  12852. ΓòÉΓòÉΓòÉ 7.16.3. Registering servers and classes ΓòÉΓòÉΓòÉ
  12853.  
  12854. Implementation definitions: 
  12855.  
  12856. The Implementation Repository holds ImplementationDef objects The 
  12857. ImplementationDef class defines attributes necessary for the SOMOA to find and 
  12858. activate the implementation of an object. Details of the ImplementationDef 
  12859. object are not currently defined in the CORBA 1.1 specification; the attributes 
  12860. that have been defined are required by DSOM. 
  12861.  
  12862. Listed below is each available attribute, with its corresponding type in 
  12863. parentheses, followed by a description of its purpose: 
  12864.  
  12865.  impl_id (string)              Contains the DSOM-generated identifier for a 
  12866.                                server implementation. 
  12867.  
  12868.  impl_alias (string)           Contains the "alias" (user-friendly name) for a 
  12869.                                server implementation. 
  12870.  
  12871.  impl_program (string)         Contains the name of the program or command file 
  12872.                                which will be executed when a process for this 
  12873.                                server is started automatically by somdd. If the 
  12874.                                full pathname is not specified, the directories 
  12875.                                specified in the  PATH environment variable will 
  12876.                                be searched for the named program or command 
  12877.                                file. 
  12878.  
  12879.                                Optionally, the server program can be run under 
  12880.                                control of a "shell" or debugger, by specifying 
  12881.                                the shell or debugger name first, followed by 
  12882.                                the name of the server program. (A space 
  12883.                                separates the two program names.)  For example, 
  12884.  
  12885.                                                                                 idbg myprogram.exe
  12886.  
  12887.                                will start the program "myprogram" under control 
  12888.                                of "idbg". 
  12889.  
  12890.                                Servers that are started automatically by somdd 
  12891.                                will always be passed their impl_id as the first 
  12892.                                parameter, in order to retrieve their 
  12893.                                ImplementationDef (if desired). 
  12894.  
  12895.  impl_flags (Flags)            Contains a bit-vector of flags used to identify 
  12896.                                server options (for example, the 
  12897.                                IMPLDEF_MULTI_THREAD flag indicates 
  12898.                                multi-threading). See the impldef.idl file for 
  12899.                                the complete set of valid ImplementationDef 
  12900.                                flags. Unused flag bits are reserved for future 
  12901.                                use by IBM. 
  12902.  
  12903.  impl_server_class (string)    Contains the name of the SOMDServer class or 
  12904.                                subclass created by the server process. 
  12905.  
  12906.  impl_refdata_file (string)    Contains the full pathname of the file used to 
  12907.                                store ReferenceData for the server. 
  12908.  
  12909.  impl_refdata_bkup (string)    Contains the full pathname of the backup mirror 
  12910.                                file used to store ReferenceData for the server. 
  12911.                                This file can be used to restore a copy of the 
  12912.                                primary file in case it becomes corrupted. (It 
  12913.                                would be a good idea to keep the primary and 
  12914.                                backup files in different disk volumes.) 
  12915.  
  12916.  impl_hostname (string)        Contains the hostname of the machine where the 
  12917.                                server is located. 
  12918.  
  12919.  
  12920. ΓòÉΓòÉΓòÉ 7.16.4. Implementation registration utilities ΓòÉΓòÉΓòÉ
  12921.  
  12922. Before an implementation (a server program and class libraries) can be used by 
  12923. client applications, it must be registered with DSOM by running the 
  12924. implementation registration utility, regimpl The  regimpl  utility can also be 
  12925. executed from the DOS command line;  this facility is available primarily for 
  12926. use in batch files. During execution of regimpl, DSOM updates it database to 
  12927. include the new server implementation and the associated classes. This enables 
  12928. DSOM to find and, if necessary, to activate the server so that clients can 
  12929. invoke methods on it. 
  12930.  
  12931. Typically, DSOM users employ the generic SOM-object server program, described 
  12932. below. A discussion on how to write a specific (non-generic) server program is 
  12933. found in the earlier section, "Basic Server Programming." 
  12934.  
  12935.  
  12936. ΓòÉΓòÉΓòÉ 7.16.4.1. Registration steps Using 'regimpl' ΓòÉΓòÉΓòÉ
  12937.  
  12938. Registering a server implementation and its classes requires the steps 
  12939. described in the following paragraphs. 
  12940.  
  12941. First, make sure the SOMDDIR environment variable is defined to the name of the 
  12942. Implementation Repository directory, as discussed in the section "Preparing the 
  12943. Environment." 
  12944.  
  12945. Then, to run the regimpl utility, at the system prompt enter: 
  12946.  
  12947. > regimpl 
  12948.  
  12949. This brings up the DSOM Implementation Registration Utility menu, shown below. 
  12950. To begin registering the new implementation, select "1.Add" from the 
  12951. IMPLEMENTATION OPERATIONS section; that is, at the "Enter operation:" prompt, 
  12952. enter "1" (as shown in bold): 
  12953.  
  12954. DSOM IMPLEMENTATION REGISTRATION UTILITY
  12955. (C) Copyright IBM Corp. 1992,1993.  All rights reserved.
  12956.  
  12957. Implementation data being loaded from: /u/xyz/dsomRepos/
  12958.  
  12959. [ IMPLEMENTATION OPERATIONS ]
  12960.  1.Add  2.Delete  3.Change
  12961.  4.Show one  5.Show all  6.List aliases
  12962. [ CLASS OPERATIONS ]
  12963.  7.Add  8.Delete  9.Delete from all  10.List classes
  12964. [ SAVE & EXIT OPERATIONS ]
  12965.  11.Save data  12.Exit
  12966. Enter operation: 1
  12967.  
  12968. The regimpl utility then issues several prompts for information about the 
  12969. server implementation (typical responses are shown in bold as an example). 
  12970.  
  12971. Implementation alias.  Enter a "shorthand" name for conveniently referencing 
  12972. the registered server implementation while using regimpl: 
  12973.  
  12974. Enter an alias for new implementation:  myServer
  12975.  
  12976. Program name.  Enter the name of the program that will execute as the server. 
  12977. This may be the name of one of the DSOM generic servers (discussed under the 
  12978. later topic "Running DSOM Servers") or a user-defined name for one of these 
  12979. servers. If the program is located in PATH, only the program name needs to be 
  12980. specified. Otherwise, the pathname must be specified. 
  12981.  
  12982. Enter server program name:(default: somdsvr)  <return>
  12983.  
  12984. Multi-threading.  Specify whether or not the server expects the SOM Object 
  12985. Adapter (SOMOA) to run each method in a separate thread or not. Notes: You must 
  12986. ensure that methods executed by the server are "thread safe". 
  12987.  
  12988. Allow multiple threads in the server? [y/n]
  12989. (default: n) : n
  12990.  
  12991. Server class.  Enter the name of the SOMDServer class or subclass that will 
  12992. manage the objects in the server. 
  12993.  
  12994. Enter server class (default: SOMDServer) : <return>
  12995.  
  12996. Reference data file name.  Enter the full pathname of the file used to store 
  12997. ReferenceData associated with object references created by this server. Note: A 
  12998. file name is required only  if the server is using the create method to 
  12999. generate object references. 
  13000.  
  13001. Enter object reference file name (optional) :  <return>
  13002. Backup reference data file name.  Enter the full pathname of the backup file 
  13003. used to mirror the primary ReferenceData file for this server. Note: a file 
  13004. name is required only if (1) a primary reference data file has been specified, 
  13005. and (2) the application desires an online backup to be maintained. This file 
  13006. can be used to restore a copy of the primary file should it become corrupted. 
  13007.  
  13008. Enter object reference backup file name (optional) : <return>
  13009.  
  13010. Host machine name.  This is the name of the machine on which the server program 
  13011. code is stored. The same name should be indicated in the HOSTNAME environment 
  13012. variable. (If "localhost" is entered, the contents of the HOSTNAME environment 
  13013. variable will be used. 
  13014.  
  13015. Enter host machine name:(default: localhost)  <return>
  13016.  
  13017. The regimpl system next displays a summary of the information defined thus far, 
  13018. and asks for confirmation before adding it. Enter "y" to save the 
  13019. implementation information in the Implementation Repository. 
  13020.  
  13021.  
  13022. ================================================================
  13023. Implementation id.........: 2befc82b-13a11e00-7f-00-10005ac9272a
  13024. Implementation alias......: myServer
  13025. Program name..............: somdsvr
  13026. Multithreaded.............: No
  13027. Server class..............:SOMDServer
  13028. Object reference file.....:
  13029. Object reference backup...:
  13030. Host Name.................: localhost
  13031.  
  13032. The above implementation is about to be added. Add? [y/n] y
  13033. Implementation 'myServer' successfully added
  13034. Add class.  Once the server implementation is added, the complete menu 
  13035. reappears. The next series of prompts and entries will identify the classes 
  13036. associated with this server. To begin, from the CLASS OPERATIONS section, 
  13037. select "7.Add": 
  13038.  
  13039.  
  13040. [ IMPLEMENTATION OPERATIONS ]
  13041.  1.Add  2.Delete  3.Change
  13042.  4.Show one  5.Show all  6.List aliases
  13043. [ CLASS OPERATIONS ]
  13044.  7.Add  8.Delete  9.Delete from all  10.List classes
  13045. [ SAVE & EXIT OPERATIONS ]
  13046.  11.Save data  12.Exit
  13047.  
  13048. Enter operation: 7
  13049. Class name.  Enter the name of a class associated with the implementation 
  13050. alias. 
  13051.  
  13052. Enter name of class:  class1
  13053.  
  13054. Implementation alias.  Enter the alias for the server that implements the new 
  13055. class (this should be the same alias as given above). 
  13056.  
  13057. Enter alias of implementation that implements class:  myServer
  13058.  
  13059. Class 'class1' now associated with implementation 'myServer'
  13060.  
  13061. The top-level menu will then reappear. Repeat the previous three steps until 
  13062. all classes have been associated with the server. 
  13063.  
  13064. Then, from the SAVE & EXIT OPERATIONS section, select "11.Save data" to 
  13065. complete the registration. Finally, select "12.Exit" to exit the regimpl 
  13066. utility. 
  13067.  
  13068. [ IMPLEMENTATION OPERATIONS ]
  13069.  1.Add  2.Delete  3.Change
  13070.  4.Show one  5.Show all  6.List aliases
  13071. [ CLASS OPERATIONS ]
  13072.  7.Add  8.Delete  9.Delete from all  10.List classes
  13073. [ SAVE & EXIT OPERATIONS ]
  13074.  11.Save data  12.Exit
  13075.  
  13076. Enter operation:  11
  13077.  
  13078. Enter operation:  12
  13079.  
  13080.  
  13081. ΓòÉΓòÉΓòÉ 7.16.4.2. Command line interface to 'regimpl' ΓòÉΓòÉΓòÉ
  13082.  
  13083. The regimpl utility also has a command line interface. The command flags 
  13084. correspond to the interactive commands described above. The syntax of the 
  13085. regimpl commands follow. 
  13086.  
  13087. Note:  The regimpl command and any optional regimpl command flags can be 
  13088.        entered at a system prompt, and the command will execute as described 
  13089.        below. 
  13090.  
  13091.  To enter interactive mode: 
  13092.  
  13093.     regimpl
  13094.  
  13095.  To add an implementation: 
  13096.  
  13097.     regimpl -A -i <str> [-p <str>] [-v <str>] [-f <str>] [-b <str>]
  13098.                           [-h <str>] [-m {on|off}] [-z <str>] [-n {on|off}]
  13099.  
  13100.  To update an implementation: 
  13101.  
  13102.     regimpl -U -i <str> [-p <str>] [-v<str>] [-f <str>]  [-b <str>]
  13103.                            [-h <str>] [-m {on|off}] [-n {on|off}]
  13104.  
  13105.  To delete one or more implementations: 
  13106.  
  13107.     regimpl -D -i <str> [-i ...]
  13108.  
  13109.  To list all, or selected, implementations: 
  13110.  
  13111.     regimpl -L  [-i <str> [-i ...]]
  13112.  
  13113.  To list all implementation aliases: 
  13114.  
  13115.     regimpl -S
  13116.  
  13117.  To add class associations to one or more implementations: 
  13118.  
  13119.     regimpl -a -c <str> [-c ...] -i <str> [-i ...rbrk.
  13120.  
  13121.  To delete class associations from all, or selected, implementations: 
  13122.  
  13123.    regimpl -d -c <str> [-c ...][-i <str> [-...]]
  13124.  
  13125.  To list classes associated with all, or selected, implementation: 
  13126.  
  13127.     regimpl -l [-i <str> [-i ...]]
  13128.  
  13129.  The following parameters are used in the commands described above: 
  13130.  
  13131.  
  13132.   -i <str>    = Implementation alias name(maximum of 16 -i names)
  13133.   -p <str>    = Server program name  (default: somdsvr)
  13134.   -v <str>    = Server-class name  (default: SOMDServer)
  13135.   -f <str>    = Reference data file name  (optional)
  13136.   -b <str>    = Reference data backup file name  (optional)
  13137.   -h <str>    = Host machine name  (default: localhost)
  13138.   -m {on|off} = Enable multi-threaded server  (optional)
  13139.   -z <str>    = Implementation ID (optional)
  13140.   -c <str>    = Class name(maximum of 16 -c names)
  13141.   -n {on|off} = Designate the server as nonstoppable (optional),
  13142.                 meaning that the server cannot be stopped using
  13143.                 the SOMDServerMgr interfaces or the "dsom" utility.
  13144.  
  13145.  
  13146. ΓòÉΓòÉΓòÉ 7.16.5. Programmatic interface to the Implementation Repository ΓòÉΓòÉΓòÉ
  13147.  
  13148. The Implementation Repository can be accessed and updated dynamically using the 
  13149. programmatic interface provided by the ImplRepository class (defined in 
  13150. "implrep.idl"). The global variable SOMD_ImplRepObject is initialized by 
  13151. SOMD_Init to point to the ImplRepositor object. The following methods are 
  13152. defined on it: 
  13153.  
  13154.             void  add_impldef (in ImplementationDef impldef)
  13155.  
  13156.       Adds an implementation definition to the Implementation Repository. 
  13157.       (Note: The value of the "impl_id" attribute is ignored. A unique ImplId 
  13158.       will be generated for the newly added ImplementationDef.) 
  13159.  
  13160.             void  delete_impldef (in ImplId implid);
  13161.  
  13162.       Deletes an implementation definition from the Implementation Repository. 
  13163.  
  13164.             void update_impldef(in ImplementationDef impldef);
  13165.  
  13166.       Updates the implementation definition (defined by the "impl_id" of the 
  13167.       supplied implementationDef) in the Implementation Repository. 
  13168.  
  13169.             ImplementationDef find_impldef(in ImplId implid);
  13170.  
  13171.       Returns a server implementation definition given its ID. 
  13172.  
  13173.             ImplementationDef find_impldef_by_alias(in string alias_name);
  13174.  
  13175.       Returns a server implementation definition, given its user-friendly 
  13176.       alias. 
  13177.  
  13178.             sequence<ImplementationDef>  find_impldef_by_class
  13179.                                                         (in string classname)
  13180.  
  13181.       Returns a sequence of ImplementationDefs for those servers that have an 
  13182.       association with the specified class. Typically, a server is associated 
  13183.       with the classes it knows how to implement, by registering its known 
  13184.       classes via the add_class_to_impldef method. 
  13185.  
  13186.             ORBStatus  find_all_impldefs  (out sequence<ImplementationDef> outimpldefs);
  13187.  
  13188.       Retrieves all ImplementationDef objects in the Implementation Repository. 
  13189.  
  13190.  The following methods maintain an association between server implementations 
  13191.  and the names of the classes they implement. These methods effectively 
  13192.  maintain a mapping of <className, Implid>. 
  13193.  
  13194.             void add_class_to_impldef (in ImplId implid,
  13195.                                         in string classname);
  13196.  
  13197.       Associates a class, identified by name, with a server, identified by its 
  13198.       ImplId. This type of association is used to lookup server implementations 
  13199.       via the find_impldef_by_class method. 
  13200.  
  13201.             void  remove_class_from_impldef (
  13202.                                          in ImplId implid,
  13203.                                          in string classname);
  13204.  
  13205.       Removes the association of a particular class with a server. 
  13206.  
  13207.             void remove_class_from_all (
  13208.  
  13209.                                        in string classname);
  13210.  
  13211.       Removes the association of a particular class from all server 
  13212.       implementations in the Implementation Repository. 
  13213.  
  13214.             sequence<string>  find_classes_by_impldef
  13215.                                           (in ImplId implid);
  13216.  
  13217.       Returns a sequence of class names associated with a server. 
  13218.  
  13219.  With the ImplRepository programmatic interface, it is possible for an 
  13220.  application to define additional server implementations at run time. 
  13221.  
  13222.  
  13223. ΓòÉΓòÉΓòÉ 7.17. Running DSOM Applications ΓòÉΓòÉΓòÉ
  13224.  
  13225. Prior to starting the DSOM processes, the DSOM executables should be installed 
  13226. and the DSOM environment variables should be set appropriately, as discussed in 
  13227. the earlier section, "Configuring DSOM Applications." 
  13228.  
  13229.  
  13230. ΓòÉΓòÉΓòÉ 7.17.1. Running the DSOM daemon (somdd) ΓòÉΓòÉΓòÉ
  13231.  
  13232. To run a DSOM application, the DSOM daemon, somdd, must be started: The daemon 
  13233. can be started manually from the command line, or could be started 
  13234. automatically from a start-up script run at boot time. It may be run in the 
  13235. background with the commands start somdd. (The somdd command has the following 
  13236. syntax: 
  13237.  
  13238. somdd [-q]
  13239.  
  13240. where the optional -q flag signifies "quiet" mode.  By default, somdd will 
  13241. produce a" ready" message when the DSOM daemon is ready to process requests, 
  13242. and it will produce diagnostic messages as errors are encountered if the 
  13243. SOMDDEBUG environment variable is set to 1. In quiet mode, however, the "ready" 
  13244. message will not appear, and diagnostic messages will not appear even if 
  13245. SOMDEBUG is set. Alternatively, if the SOMDMESSAGELOG environment variable is 
  13246. set, diagnostic error messages will be sent directly to the specified message 
  13247. log file, regardless of whether the -q flag is specified. 
  13248.  
  13249.  The somdd daemon is responsible for "binding" a client process to a server 
  13250.  process and will activate the desired server if necessary. The binding 
  13251.  procedure is such that the client will consult the Implementation Repository 
  13252.  to find out which machine contains a desired server, and will then contact the 
  13253.  DSOM daemon on the server's machine to retrieve the server's communications 
  13254.  address (a port). Servers are activated dynamically as separate processes. 
  13255.  
  13256.  
  13257. ΓòÉΓòÉΓòÉ 7.17.2. Running DSOM servers ΓòÉΓòÉΓòÉ
  13258.  
  13259. Once the somdd daemon is running, application programs can be started. If the 
  13260. application uses the generic SOM server, somdsvr, it can be started either from 
  13261. the command line or automatically upon demand. When starting somdsvr from the 
  13262. command line, the server's implementation ID or alias must be supplied as an 
  13263. argument. The command syntax for starting a generic SOM server is: 
  13264.  
  13265.    somdsvr  [ impl_id  | -a alias ]
  13266.  
  13267. For example, the command 
  13268.  
  13269. >  somdsvr  2ad2688fb-00389c00-7f-00-10005ac900d8
  13270.  
  13271. would start a somdsvr for an implementation with the specified ID. Likewise, 
  13272. the command 
  13273.  
  13274. >  somdsvr  -a  myServer
  13275.  
  13276. would start a somdsvr that represents an implementation of "myServer". 
  13277.  
  13278.  
  13279. ΓòÉΓòÉΓòÉ 7.18. DSOM as a CORBA-compliant Object Request Broker ΓòÉΓòÉΓòÉ
  13280.  
  13281. The Object Management Group (OMG) consortium defines the notion of an Object 
  13282. Request Broker (ORB) that supports access to remote objects in a distributed 
  13283. environment. Thus, Distributed SOM is an ORB. SOM and DSOM together comply with 
  13284. the OMG's specification of the Common Object Request Broker Architecture 
  13285. (CORBA). 
  13286.  
  13287. Since the interfaces of SOM and DSOM are largely determined by the CORBA 
  13288. specification, the CORBA components and interfaces are highlighted in this 
  13289. section. 
  13290.  
  13291. The CORBA specification defines the components and interfaces that must be 
  13292. present in an ORB, including the: 
  13293.  
  13294.      Interface Definition Language (IDL) for defining classes (discussed in 
  13295.       Chapter 4, "SOM IDL and the SOM Compiler"). 
  13296.  
  13297.      C usage bindings (procedure-call formats) for invoking methods on remote 
  13298.       objects, 
  13299.  
  13300.      Dynamic Invocation Interface and an Interface Repository, which support 
  13301.       the construction of requests (method calls) at run time (for example, for 
  13302.       interactive desktop applications), and 
  13303.  
  13304.      Object Request Broker run-time programming interfaces. 
  13305.  
  13306.  SOM and DSOM were developed to comply with these specifications (with only 
  13307.  minor extensions to take advantage of SOM services). Although the capabilities 
  13308.  of SOM are integral to the implementation of DSOM, the application programmer 
  13309.  need not be aware of SOM as the implementation technology for the ORB. 
  13310.  
  13311.  This section assumes some familiarity with The Common Object Request Broker: 
  13312.  Architecture and Specification, Revision 1.1 (also referred to as "CORBA 
  13313.  1.1"). The specification is published jointly by the Object Management Group 
  13314.  and x/Open. The mapping of some CORBA 1.1 terms and concepts to DSOM terms and 
  13315.  concepts is described in the remainder of this section. 
  13316.  
  13317.  
  13318. ΓòÉΓòÉΓòÉ 7.18.1. Mapping OMG CORBA terminology onto DSOM ΓòÉΓòÉΓòÉ
  13319.  
  13320. This section discusses how various CORBA concepts and terms are defined in 
  13321. terms of DSOM's implementation of the CORBA 1.1 standard. 
  13322.  
  13323.  
  13324. ΓòÉΓòÉΓòÉ 7.18.1.1. Object Request Broker run-time interfaces ΓòÉΓòÉΓòÉ
  13325.  
  13326. In the previous sections, the SOMDObjectMgr and SOMDServer classes were 
  13327. introduced. These are classes defined by DSOM to provide basic support in 
  13328. managing objects in a distributed application. These classes are built upon 
  13329. Object Request Broker interfaces defined  by  CORBA for building and 
  13330. dispatching requests on objects. The ORB interfaces, SOMDObjectMgr and 
  13331. SOMDServer, together provide the support for implementing distributed 
  13332. applications in DSOM. 
  13333.  
  13334. CORBA 1.1 defines the interfaces to the ORB components in IDL. In DSOM, the ORB 
  13335. components are implemented as SOM classes whose interfaces are expressed using 
  13336. the same CORBA 1.1 IDL. Thus, an application can make calls to the DSOM run 
  13337. time using the SOM language bindings of its choice. 
  13338.  
  13339. Interfaces for the following ORB run-time components are defined in CORBA 1.1, 
  13340. and are implemented in DSOM. They are introduced briefly here, and discussed in 
  13341. more detail throughout this chapter. (See the SOM Programming Reference for the 
  13342. complete interface definitions.) 
  13343.  
  13344.  Object               The Object interface defines operations on an "object 
  13345.                       reference", which is the information needed to specify an 
  13346.                       object within the ORB. 
  13347.  
  13348.                       In DSOM, the class SOMDObject implements the CORBA 1.1 
  13349.                       Object interface. (The"SOMD" prefix was added to 
  13350.                       distinguish this class from SOMObject.) The subclass 
  13351.                       SOMDClientProxy extends SOMDObject with support for proxy 
  13352.                       objects. 
  13353.  
  13354.  ORB                  (Object Request Broker) The ORB interface defines utility 
  13355.                       routines for building requests and saving references to 
  13356.                       distributed objects. The global variable SOMD_ORBObject 
  13357.                       is initialized by SOMD_Init and provides the reference to 
  13358.                       the ORB object. 
  13359.  
  13360.  ImplementationDef    An ImplementationDef object is used to describe an 
  13361.                       object's implementation. Typically, the ImplementationDef 
  13362.                       describes the program that implements an object's server, 
  13363.                       how the program is activated, and so on. 
  13364.  
  13365.                       (CORBA 1.1 introduces ImplementationDef as the name of 
  13366.                       the interface, but leaves the remainder of the IDL 
  13367.                       specification to the particular ORB. DSOM defines an 
  13368.                       interface for ImplementationDef.) 
  13369.  
  13370.                       ImplementationDef objects are stored in the 
  13371.                       Implementation Repository (defined in DSOM by the 
  13372.                       ImplRepository class). 
  13373.  
  13374.  InterfaceDef         An InterfaceDef object is used to describe an IDL 
  13375.                       interface in a manner that can be queried and manipulated 
  13376.                       at run time when building requests dynamically, for 
  13377.                       example. 
  13378.  
  13379.                       InterfaceDef objects are stored in the Interface 
  13380.                       Repository (described fully in Chapter 7, "The Interface 
  13381.                       Repository Framework"). 
  13382.  
  13383.  Request              A Request object represents a specific request on an 
  13384.                       object, constructed at run-time. The Request object 
  13385.                       contains the target object reference, operation (method) 
  13386.                       name, a list of input and output arguments. A Request can 
  13387.                       be invoked synchronously (wait for the response), 
  13388.                       asynchronously (initiate the call, and later, get the 
  13389.                       response), or as a "oneway" call (no response expected). 
  13390.  
  13391.  NVList               An NVList is a list of NamedValue structures, used 
  13392.                       primarily in building Request objects. A NamedValue 
  13393.                       structure consists of a name, typed value, and some flags 
  13394.                       indicating how to interpret the value, how to 
  13395.                       allocate/free the value's memory, and so on. 
  13396.  
  13397.  Context              A Context object contains a list of "properties" that 
  13398.                       represent information about an application process's 
  13399.                       environment. Each Context property consists of a 
  13400.                       <name,string_value> pair,and is used by application 
  13401.                       programs or methods much like the "environment variables" 
  13402.                       commonly found in operating systems like AIX and OS/2 and 
  13403.                       Windows. IDL method interfaces can explicitly list which 
  13404.                       properties are queried by a method, and the ORB will pass 
  13405.                       those property values to a remote target object when 
  13406.                       making a request. 
  13407.  
  13408.  Principal            A Principal object identifies the principal ("user") on 
  13409.                       whose behalf a request is being performed. 
  13410.  
  13411.                       (CORBA 1.1 introduces the name of the interface, 
  13412.                       Principal, but leaves the remainder of the IDL 
  13413.                       specification to the particular ORB. DSOM defines an 
  13414.                       interface for Principal.) 
  13415.  
  13416.  BOA                  (Basic Object Adapter) An Object Adapter provides the 
  13417.                       primary interface between an implementation and the ORB 
  13418.                       "core". An ORB may have a number of Object Adapters, with 
  13419.                       interfaces that are appropriate for specific kinds of 
  13420.                       objects. 
  13421.  
  13422.  The Basic Object Adapter is intended to be a general-purpose Object Adapter 
  13423.  available on all CORBA-compliant Object Request Brokers. The BOA interface 
  13424.  provides support for generation of object references, identification of the 
  13425.  principal making a call, activation and deactivation of objects and 
  13426.  implementations, and method invocation on objects. 
  13427.  
  13428.  In DSOM, BOA is defined as an abstract class. The SOMOA (SOM Object Adapter) 
  13429.  class, derived from BOA, is DSOM's primary Object Adapter implementation. The 
  13430.  SOMOA interface extends the BOA interface with several of its own methods that 
  13431.  are not defined by CORBA 1.1. 
  13432.  
  13433.  
  13434. ΓòÉΓòÉΓòÉ 7.18.1.2. Object references and proxy objects ΓòÉΓòÉΓòÉ
  13435.  
  13436. CORBA 1.1 defines the notion of an object reference, which is the information 
  13437. needed to specify an object in the ORB. An object is defined by its 
  13438. ImplementationDef, InterfaceDef, and application-specific "reference data" used 
  13439. to identify or describe the object. An object reference is used as a handle to 
  13440. a remote object in method calls. When a server wants to export a reference to 
  13441. an object it implements, it supplies the object's ImplementationDef, 
  13442. InterfaceDef, and reference data to the Object Adapter, which returns the 
  13443. reference. 
  13444.  
  13445. The structure of an object reference is opaque to the application, leaving its 
  13446. representation up to the ORB. 
  13447.  
  13448. In DSOM, an object reference is represented as an object that can simply be 
  13449. used to identify the object on that server. The DSOM class that implements 
  13450. simple object references is called SOMDObject (corresponding to Object in CORBA 
  13451. 1.1.) However, in a client's address space, DSOM represents the remote object 
  13452. with a proxy object in order to allow the client to invoke methods on the 
  13453. target object as if it were local. When an object reference is passed from a 
  13454. server to a client, DSOM dynamically and automatically creates a proxy in the 
  13455. client for the remote object. Proxies are specialized forms of SOMDObject; 
  13456. accordingly, the base proxy class in DSOM SOMDClientProxy, is derived from 
  13457. SOMDObject. 
  13458.  
  13459. In order to create a proxy object, DSOM must first build a proxy class. It does 
  13460. so automatically using SOM facilities for building classes at run time. The 
  13461. proxy class is constructed using multiple inheritance: the proxy object 
  13462. functionality is inherited from SOMDClientProxy, while just the interface of 
  13463. the target class is inherited. 
  13464.  
  13465. In the newly derived proxy class, DSOM overrides each method inherited from the 
  13466. target class with a "remote dispatch" method that forwards an invocation 
  13467. request to the remote object. Consequently, the proxy object provides location 
  13468. transparency, and the client code invokes operations (methods) on the remote 
  13469. object using the same language bindings as if it were a local target object. 
  13470.  
  13471. For example, recall the "Stack" class used in the tutorial example given 
  13472. earlier. When a server returns a reference to a remote "Stack" object to the 
  13473. client, DSOM builds a "Stack_ _Proxy" class (note two underscores in the name), 
  13474. derived from SOMDClientProxy and "Stack", and creates a proxy object from that 
  13475. class.  When the client invokes the "push" method on the proxy, 
  13476.  
  13477.  
  13478. _push(stk, &ev, 100);
  13479.  
  13480. the method is redispatched using the remote-dispatch method of the 
  13481. SOMDClientProxy class, and the method is forwarded to the target object. 
  13482.  
  13483. CORBA defines several special operations on object references that operate on 
  13484. the local references (proxies) themselves, rather than on the remote objects. 
  13485. These operations are defined by the classes SOMOA (SOM Object Adapter), 
  13486. SOMDObject (which is DSOM's implementation of CORBA's Object "pseudo-class" and 
  13487. ORB (Object Request Broker class). Some of these operations are listed below, 
  13488. expressed in terms of their IDL definitions. 
  13489.  
  13490. SOMOA methods (inherited from BOA): 
  13491.  
  13492.  
  13493.             sequence <octet,1024> ReferenceData;
  13494.             SOMDObject  create (in ReferenceData id, in InterfaceDef intf
  13495.                                 in ImplementationDef impl);
  13496.  
  13497.  Creates and returns an object reference. 
  13498.  
  13499.  SOMDObject methods: 
  13500.  
  13501.             SOMDObject  duplicate ( );
  13502.  
  13503.       Creates and returns a duplicate object reference. 
  13504.  
  13505.             void  release ( );
  13506.  
  13507.       Destroys an object reference. 
  13508.  
  13509.             boolean  is_nil ( );
  13510.  
  13511.       Tests to see if the object reference is NULL. 
  13512.  
  13513.  ORB methods: 
  13514.  
  13515.             string  object_to_string ( SOMDObject obj );
  13516.  
  13517.       Converts an object reference to a (storable) string form. 
  13518.  
  13519.             SOMDObject  string_to_object ( string str );
  13520.  
  13521.       Converts a string form back to the original object reference. 
  13522.  
  13523.  
  13524. ΓòÉΓòÉΓòÉ 7.18.1.3. Creation of remote objects ΓòÉΓòÉΓòÉ
  13525.  
  13526. The OMG has standardized an "object lifecycle service," built on top of the 
  13527. ORB, for creating and destroying remote objects.  Currently, DSOM provides its 
  13528. own interface for creating and destroying objects (see "Basic Client 
  13529. Programming"), but a future release may provide an OMG-compliant lifecycle 
  13530. service as well. 
  13531.  
  13532.  
  13533. ΓòÉΓòÉΓòÉ 7.18.1.4. Interface definition language ΓòÉΓòÉΓòÉ
  13534.  
  13535. The CORBA specification defines an Interface Definition Language, IDL, for 
  13536. defining object interfaces. The SOM Compiler compiles standard IDL interface 
  13537. specifications, but it also allows the class implementer to include 
  13538. implementation information that will be used in the implementation bindings for 
  13539. a particular language. 
  13540.  
  13541. Note:  Before IDL, SOM (version 1.0) had its own Object Interface Definition 
  13542.        Language (OIDL). SOM classes specified using OIDL must be converted to 
  13543.        IDL before they can be used with DSOM. The SOMobjects Developer Toolkit 
  13544.        provides a migration tool for this purpose. 
  13545.  
  13546.  
  13547. ΓòÉΓòÉΓòÉ 7.18.1.5. C language mapping ΓòÉΓòÉΓòÉ
  13548.  
  13549. The CORBA specification defines the mapping of method interface definitions to 
  13550. C language procedure prototypes, hence SOM defines the same mapping. This 
  13551. mapping requires passing a reference to the target object and a reference to an 
  13552. implementation-specific Environment structure as the first and second 
  13553. parameters, respectively, in any method call. 
  13554.  
  13555. The Environment structure is primarily used for passing error information from 
  13556. a method back to its caller. See also the topic "Exceptions and Error Handling" 
  13557. in Chapter 3, "Using SOM Classes in Client Programs," for a description of how 
  13558. to "get" and "set" error information in the Environment structure. 
  13559.  
  13560.  
  13561. ΓòÉΓòÉΓòÉ 7.18.1.6. Dynamic Invocation Interface (DII) ΓòÉΓòÉΓòÉ
  13562.  
  13563. The CORBA specification defines a Dynamic Invocation Interface (DII) that can 
  13564. be used to dynamically build requests on remote objects. This interface is 
  13565. described in section 6 (page 105) of the CORBA 1.1 document, and is implemented 
  13566. in DSOM. The DSOM implementation of the DII is described later in this chapter, 
  13567. in the topic entitled "Dynamic Invocation Interface" under Section 6.9 
  13568. "Advanced topics." Note that, in DSOM, somDispatch is overridden so that method 
  13569. invocations on proxy objects are forwarded to the remote target object. SOM 
  13570. applications can use the SOM somDispatch method for dynamic method calls 
  13571. whether the object is local or remote. 
  13572.  
  13573.  
  13574. ΓòÉΓòÉΓòÉ 7.18.1.7. Implementations and servers ΓòÉΓòÉΓòÉ
  13575.  
  13576. The CORBA specification defines the term implementation as the code that 
  13577. implements an object. The implementation usually consists of a program and 
  13578. class libraries. 
  13579.  
  13580. Servers are processes that execute object implementations. CORBA 1.1 defines 
  13581. four activation policies for server implementations: shared, unshared, 
  13582. server-per-method, and persistent, as follows. 
  13583.  
  13584.      A shared server implements multiple objects (of arbitrary classes the 
  13585.       same time, and allows multiple methods to be invoked at the same time. 
  13586.  
  13587.      An unshared  server, conversely, implements only a single object and 
  13588.       handles one request at a time. 
  13589.  
  13590.      The server-per-method  policy requires a separate process to be created 
  13591.       for each request on an object and, usually, a separate program implements 
  13592.       each method. 
  13593.  
  13594.       Under the shared, unshared, and server-per-method activation policies, 
  13595.       servers are activated automatically (on demand). 
  13596.  
  13597.      A persistent  server, by contrast, is a shared server that is activated 
  13598.       "by hand" (for example, from the command shell or from a startup script), 
  13599.       vs. being activated automatically when the first method is dispatched to 
  13600.       it. 
  13601.  
  13602.  The term "persistent server" refers to the relative lifetime of the server: it 
  13603.  is "always running" when DSOM is running. (CORBA implies that persistent 
  13604.  servers are usually started at ORB boot time.) It should not be assumed, 
  13605.  however, that a "persistent" server necessarily implements persistent objects 
  13606.  (that persist between ORB reboots). 
  13607.  
  13608.  In DSOM, specific process models are implemented by the server program. That 
  13609.  is, DSOM simply starts a specified program when a client attempts to connect 
  13610.  to a server. The four CORBA activation policies, or any other policies, can be 
  13611.  implemented by the application as necessary. For example, 
  13612.  
  13613.      an object that requires a server-per-method implementation could itself 
  13614.       spawn a process at the beginning of each method execution. Alternatively, 
  13615.       the server object in the "main" server can spawn a process before each 
  13616.       method dispatch. 
  13617.  
  13618.      a dedicated server could be registered for each object that requires an 
  13619.       unshared server implementation (separate process). This may be done 
  13620.       dynamically (see the topic "Programmatic interface to the Implementation 
  13621.       Repository" earlier in this chapter). 
  13622.  
  13623.  An ImplementationDef object, as defined by the CORBA specification, describes 
  13624.  the characteristics of a particular implementation. In DSOM, an 
  13625.  ImplementationDef identifies an implementation's unique ID, the program name, 
  13626.  its location, and so forth. The ImplementationDef objects are stored in an 
  13627.  Implementation Repository, which is represented in DSOM by an ImplRepository 
  13628.  object. 
  13629.  
  13630.  A CORBA-compliant ORB must provide the mechanisms for a server program to 
  13631.  register itself with the ORB. To "register itself with the ORB" simply means 
  13632.  to tell the ORB enough information about the server process so that the ORB 
  13633.  will be able to locate, activate, deactivate, and dispatch methods to the 
  13634.  server process. DSOM supports these mechanisms, so that server programs 
  13635.  written in arbitrary languages can be used with DSOM. (See also the next 
  13636.  topic, "Object Adapters.") 
  13637.  
  13638.  In addition to the generic registration mechanisms provided by all 
  13639.  CORBA-compliant ORBs, DSOM provides extra support for using SOM-class DLLs. 
  13640.  DSOM provides a generic server  program that automatically registers itself 
  13641.  with DSOM, loads SOM-class DLLs on demand, and dispatches incoming requests on 
  13642.  SOM objects. Thus, by using the generic server program (when appropriate), a 
  13643.  user may be able to avoid writing any server program code. 
  13644.  
  13645.  
  13646. ΓòÉΓòÉΓòÉ 7.18.1.8. Object Adapters ΓòÉΓòÉΓòÉ
  13647.  
  13648. An Object Adapter (OA) provides the mechanisms that a server process uses to 
  13649. interact with DSOM, and vice versa. That is, an Object Adapter is responsible 
  13650. for server activation and deactivation, dispatching methods, activation and 
  13651. deactivation of individual objects, and providing the interface for 
  13652. authentication of the principal making a call. 
  13653.  
  13654. DSOM defines a Basic Object Adapter (BOA) interface, described in the CORBA 
  13655. specification, as an abstract class (a class having no implementation, only an 
  13656. interface specification). The BOA interface represents generic Object Adapter 
  13657. methods that a server written in an arbitrary language can use to register 
  13658. itself and its objects with the ORB. Because it is an abstract class having no 
  13659. implementation, however, the BOA class should not be directly instantiated. 
  13660.  
  13661. DSOM provides a SOM Object Adapter, SOMOA, derived from the BOA interface, that 
  13662. uses SOM Compiler and run-time support to accomplish dispatching of methods 
  13663. (that is, accepting messages, turning them into method invocations, and routing 
  13664. the invocations to the target object in the server process). SOMOA can be used 
  13665. to dispatch methods on either SOM or non-SOM object implementations, as 
  13666. described in the sections "Implementing Classes" and "Basic Server 
  13667. Programming." It is possible to use non-SOM based implementations with SOMOA, 
  13668. and often there is no additional programming required to use implementations 
  13669. (class libraries) already developed using SOM. 
  13670.  
  13671. The SOMOA works in conjunction with the application-defined server object to 
  13672. map between objects and object references, and to dispatch methods on objects. 
  13673. By partitioning out these mapping and dispatching functions into the server 
  13674. object, the application can more easily customize them, without having to build 
  13675. object adapter subclasses. 
  13676.  
  13677. SOMOA introduces two methods that handle execution of requests received by the 
  13678. server: 
  13679.  
  13680.       execute_request_loop 
  13681.  
  13682.       execute_next_request 
  13683.  
  13684.  Typically, execute_request_loop is used to receive and execute requests, 
  13685.  continuously, in the server's main thread. The execute_next_request method 
  13686.  allows a single request to be executed. Both methods have a non-blocking 
  13687.  option: when there are no messages pending, the method call will return 
  13688.  instead of wait. 
  13689.  
  13690.  If the server implementation has been registered as "multi-threaded" (via an 
  13691.  IMPLDEF_MULTI_THREAD flag in the ImplementationDef), SOMOA will automatically 
  13692.  run each request in a separate thread. If the "multi-thread" flag is not set, 
  13693.  the server implementation can still choose to manage its own threads. 
  13694.  
  13695.  The generic server program provided by DSOM (described in the preceding topic) 
  13696.  uses execute_request_loop to receive and execute requests on SOM objects. 
  13697.  
  13698.  
  13699. ΓòÉΓòÉΓòÉ 7.18.1.9. Extensions and limitations ΓòÉΓòÉΓòÉ
  13700.  
  13701. The DSOM implementation has the following extensions and limitations in its 
  13702. implementation of the CORBA specification: 
  13703.  
  13704.      As just described, the current release of DSOM supports a simple server 
  13705.       activation policy, which is equivalent to the "shared" and "persistent" 
  13706.       policies defined by CORBA. DSOM does not explicitly support the 
  13707.       "unshared" or "server-per-method" server activation policies. Policies 
  13708.       other than the basic activation scheme must be implemented by the 
  13709.       application. 
  13710.  
  13711.      DSOM provides null implementations for the object_is_ready or 
  13712.       deactivate_obj methods, defined by the BOA interface for the unshared 
  13713.       server activation policy. 
  13714.  
  13715.      DSOM does not support the change_implementation method, defined by the 
  13716.       BOAinterface to allow an application to change the implementation 
  13717.       definition associated with an object. In DSOM, the ImplementationDef 
  13718.       identifies the server which implements an object.  In these terms, 
  13719.       changing an object's ImplementationDef would result in a change in the 
  13720.       object's server ID. Any existing object references that have the old 
  13721.       server ID would be rendered invalid. 
  13722.  
  13723.       It is possible, however, to change the program which implements an 
  13724.       object's server, or change the class library which implements an object's 
  13725.       class. To modify the program associated with an ImplementationDef, use 
  13726.       the update_impldef method defined on ImplRepository. To change the 
  13727.       implementation of an object's class, replace the corresponding class 
  13728.       library with a new (upward-compatible) one. 
  13729.  
  13730.      The OUT_list_MEMORY, IN_COPY_VALUE, and DEPENDENT_LIST flags, used with 
  13731.       the Dynamic Invocation Interface, are not yet supported. 
  13732.  
  13733.      The SOM Object Adapter (SOMOA) provides a method (change_id) to update 
  13734.       the ReferenceData  associated with an object reference created by the 
  13735.       create call This is useful if the information which describes the object 
  13736.       must be changed without invalidating copies of the existing object 
  13737.       reference. CORBA defines no such method;  change_id is an extension to 
  13738.       the standard BOA methods. 
  13739.  
  13740.      The SOMOA provides some specialized object reference types which, in 
  13741.       certain situations, are more efficient or easier-to-use than standard 
  13742.       object references. 
  13743.  
  13744.      DSOM supports the SOM extension to IDL that allows method parameters that 
  13745.       are pointers. Structure, sequence, and array parameters may only contain 
  13746.       pointers to objects (not arbitrary types). 
  13747.  
  13748.      The Context::get_values method currently does not support the 
  13749.       CTX_RESTRICT_SCOPE flag. 
  13750.  
  13751.  
  13752. ΓòÉΓòÉΓòÉ 7.19. Advanced Topics ΓòÉΓòÉΓòÉ
  13753.  
  13754. The following subjects are discussed in this section: 
  13755.  
  13756.      Peer vs. client/server processes 
  13757.      Dynamic Invocation Interface 
  13758.      Creating user-supplied proxies 
  13759.      Customizing the default base proxy class 
  13760.  
  13761.  
  13762. ΓòÉΓòÉΓòÉ 7.19.1. Peer vs. client/server processes ΓòÉΓòÉΓòÉ
  13763.  
  13764. The client/server model of distributed computing is appropriate when it is 
  13765. convenient (or necessary) to centralize the implementation and management of a 
  13766. set of shared objects in one or more servers. However, some applications 
  13767. require more flexibility in the distribution of objects among processes. 
  13768. Specifically, it is often useful to allow processes to manage and export some 
  13769. of their objects, as well as access remote objects owned by other processes. In 
  13770. these cases, the application processes do not adhere to a strict client/server 
  13771. relationship; instead, they cooperate as "peers", behaving both as clients and 
  13772. as servers. 
  13773.  
  13774. Peer applications must be written to respond to incoming asynchronous requests, 
  13775. in addition to performing their normal processing. In a multi-threaded system 
  13776. (like NT), this is best accomplished by dedicating a separate process t  hread 
  13777. that handles DSOM communications and dispatching. In systems that do not 
  13778. currently support multi-threading (like AIX), peer applications must be 
  13779. structured as event-driven programs. 
  13780.  
  13781.  
  13782. ΓòÉΓòÉΓòÉ 7.19.1.1. Multi-threaded DSOM programs ΓòÉΓòÉΓòÉ
  13783.  
  13784. In a system that supports multi-threading, like NT, the easiest way to write a 
  13785. peer DSOM program is to dedicate a separate thread to perform the usual 
  13786. "server" processing. This body of this thread would contain the same code as 
  13787. the simple servers described in section 6.4, "Basic Server Programming." 
  13788.  
  13789. DSOM_thread(void *params)
  13790. {
  13791.    Environment ev;
  13792.    SOM_InitEnvironment(&ev);
  13793.  
  13794. /* Initialize the DSOM run-time environment */
  13795.    SOMD_Init(&ev);
  13796.  
  13797. /* Retrieve its ImplementationDef from the Implementation
  13798.    Repository by passing its implementation ID as a key */
  13799.    SOMD_ImplDefObject =
  13800.       _find_impldef(SOMD_ImplRepObject, &ev, *(ImplId *)params);
  13801.  
  13802. /* Create SOM Object Adapter and begin executing requests */
  13803.    SOMD_SOMOAObject = SOMOANew();
  13804.    _impl_is_ready(SOMD_SOMOAObject, &ev, SOMD_ImplDefObject);
  13805.    _execute_request_loop(SOMD_SOMOAObject, &ev, SOMD_WAIT);
  13806. }
  13807.  
  13808. Note:  The DSOM run time is "thread safe"; that is, DSOM protects its own  data 
  13809.        structures and objects from race conditions and update conflicts. 
  13810.        However, it is the application's responsibility to implement its own 
  13811.        concurrency control for concurrent thread access to local shared 
  13812.        application objects. 
  13813.  
  13814.  
  13815. ΓòÉΓòÉΓòÉ 7.19.1.2. Event-driven DSOM programs using EMan ΓòÉΓòÉΓòÉ
  13816.  
  13817. EMan (see Chapter 9 on "The Event Management Framework") is not a replacement 
  13818. for threads, but it supports processing of asynchronous requests. EMan allows a 
  13819. program to handle events from multiple input sources; but the handlers run on a 
  13820. single thread, under control of EMan's main loop. 
  13821.  
  13822. DSOM provides a runtime function, SOMD_RegisterCallback, which is used by DSOM 
  13823. to associate user-supplied event handlers with DSOM's communications sockets 
  13824. and message queues with EMan. Example code is shown below. 
  13825.  
  13826. DSOM server programs which use EMan must be very careful not to get into 
  13827. deadlock situations. This is quite easy to do with DSOM, since method calls are 
  13828. synchronous. If two cooperating processes simultaneously make calls on each 
  13829. other, a deadlock could result. Likewise, if a method call on remote object B 
  13830. from A requires a method call back to A, a deadlock cycle will exist. (Of 
  13831. course, the number of processes and objects which create the cyclic dependency 
  13832. could be greater than two.) 
  13833.  
  13834. The application developer must be careful to avoid situations where cooperating 
  13835. processes are likely to make calls upon each other, creating a cyclic 
  13836. dependency. Some applications may find it appropriate to use oneway messages to 
  13837. avoid deadlock cycles, since oneway messages do not cause a process to block. 
  13838. It may also be possible for an application to defer the actual processing of a 
  13839. method that may "call back" an originating process, by scheduling work using 
  13840. EMan client events. 
  13841.  
  13842.  
  13843. ΓòÉΓòÉΓòÉ 7.19.2. Dynamic Invocation Interface ΓòÉΓòÉΓòÉ
  13844.  
  13845. DSOM supports the CORBA dynamic invocation interface (DII), which clients can 
  13846. use to dynamically build and invoke requests on objects. This section describes 
  13847. how to use the DSOM DII. Currently, DSOM supports dynamic request invocation 
  13848. only on objects outside the address space of the request initiator, via 
  13849. proxies. The somDispatch method (non-CORBA) can be used to invoke methods 
  13850. dynamically on either local or remote objects, however. 
  13851.  
  13852. To invoke a request on an object using the DII, the client must explicitly 
  13853. construct and initiate the request. A request is comprised of an object 
  13854. reference, an operation, a list of arguments for the operation, and a return 
  13855. value from the operation. A key to proper construction of the request is the 
  13856. correct usage of the NamedValue structure and the NVList object. The return 
  13857. value for an operation is supplied to the request in the form of a NamedValue 
  13858. structure. In addition, it is usually most convenient to supply the arguments 
  13859. for a request in the form of an NVList object, which is an ordered set of 
  13860. NamedValues. This section begins with a description of NamedValues and NVLists 
  13861. and then details the procedure for building and initiating requests. 
  13862.  
  13863.  
  13864. ΓòÉΓòÉΓòÉ 7.19.2.1. The NamedValue structure ΓòÉΓòÉΓòÉ
  13865.  
  13866. The NamedValue structure is defined in C as: 
  13867.  
  13868. typedef unsigned long Flags;
  13869.  
  13870. struct NamedValue {
  13871.         Identifier  name;         // argument name
  13872.         any         argument;     // argument
  13873.         long        len;          // length/count of arg value
  13874.         Flags       arg_modes;    // argument mode flags
  13875. };
  13876.  
  13877. where: name is an Identifier string as defined in the CORBA specification, and 
  13878. argument is an any structure with the following declaration: 
  13879.  
  13880.  
  13881.         struct any {
  13882.                 TypeCode        _type;
  13883.                 void*           _value;
  13884.         };
  13885.  
  13886. _type  is a TypeCode, which has an opaque representation with operations 
  13887. defined on it to allow access to its constituent parts. Essentially the 
  13888. Typecode is composed of a field specifying the CORBA type represented and 
  13889. possibly additional fields needed to fully describe the type. See Chapter 7 of 
  13890. this manual for a complete explanation of TypeCodes. 
  13891.  
  13892. _value  is a pointer to the value of the any structure. Important: The contents 
  13893. of "_value" should always be a pointer to the value, regardless of whether the 
  13894. value is a primitive, a structure, or is itself a pointer (as in the case of 
  13895. object references, strings and arrays). For object references, strings and 
  13896. arrays, _value should contain pointer to the pointer that references the value. 
  13897. For example: 
  13898.  
  13899.  
  13900.         string          testString;
  13901.         any             testAny;
  13902.  
  13903.         testAny._value = &testString;
  13904.  
  13905. len is the number of bytes that the argument value occupies. The following 
  13906. table gives the length of data values for the C language bindings. The value of 
  13907. len must be consistent with the TypeCode. 
  13908.  
  13909.  
  13910. Data type               Length
  13911. short                   sizeof(short)
  13912. unsigned short          sizeof(unsigned short)
  13913. long                    sizeof(long)
  13914. unsigned long           sizeof(unsigned long)
  13915. float                   sizeof(float)
  13916. double                  sizeof(double)
  13917. char                    sizeof(char)
  13918. boolean                 sizeof(boolean)
  13919. octet                   sizeof(octet)
  13920. string                  strlen(string) - does not include '\0' byte
  13921. enum E{}                sizeof(unsigned long)
  13922. union U                 sizeof(U)
  13923. struct S{}              sizeof(S)
  13924. Object                  1
  13925. array N of type T1      Length(T1)*N
  13926. sequence V of type T2   Length(T2)*V - V is the actual # of elements
  13927.  
  13928. The arg_modes field is a bitmask (unsigned long) and may contain the following 
  13929. flag values: 
  13930.  
  13931. ARG_IN              the associated value is an input-only argument
  13932. ARG_OUT             the associated value is an output-only argument
  13933. ARG_INOUT           the associated argument is an in/out argument
  13934.  
  13935. These flag values identify the parameter passing mode for the arguments. 
  13936. Additional flag values have specific meanings for Request and NVList methods 
  13937. and are listed with their associated methods. 
  13938.  
  13939.  
  13940. ΓòÉΓòÉΓòÉ 7.19.2.2. The NVList class ΓòÉΓòÉΓòÉ
  13941.  
  13942. An NVList contains an ordered set of NamedValues. The CORBA specification 
  13943. defines several operations that the NVList supports. The IDL prototypes for 
  13944. these methods are as follows: 
  13945.  
  13946.  
  13947. // get the number of elements in the NVList
  13948. ORBStatus get_count(
  13949.                 out  long count );
  13950.  
  13951. // add an element to an NVList
  13952. ORBStatus add_item(
  13953.                 in  Identifier      item_name,
  13954.                 in  TypeCode    item_type,
  13955.                 in  void* value,
  13956.                 in  Flags item_flags );
  13957.  
  13958. // frees the NVList and any associated memory
  13959. ORBStatus free();
  13960.  
  13961.  
  13962. // frees dynamically allocated memory associated with the list
  13963. ORBStatus free_memory();
  13964.  
  13965. In DSOM, the NVList is a full-fledged object with methods for getting and 
  13966. setting elements: 
  13967.  
  13968.  
  13969. //set the contents of an element in an NVList
  13970. ORBStatus set_item(
  13971.                 in  long            item_number, /* element # to set */
  13972.                 in  Identifier      item_name,
  13973.                 in  TypeCode        item_type,
  13974.                 in  void*           item_value,
  13975.                 in  long            value_len,
  13976.                 in  Flags           item_flags );
  13977.  
  13978.  
  13979. // get the contents of an element in an NVList
  13980. ORBStatus get_item(
  13981.                 in  long            item_number, /* element # to get */
  13982.                 out Identifier      item_name,
  13983.                 out TypeCode        item_type,
  13984.                 out void*           item_value,
  13985.                 out long            value_len,
  13986.                 out Flags           item_flags );
  13987.  
  13988.  
  13989. ΓòÉΓòÉΓòÉ 7.19.2.3. Creating argument lists ΓòÉΓòÉΓòÉ
  13990.  
  13991. A very important use of the NVList is to pass the argument list for an 
  13992. operation when creating a request. CORBA 1.1 specifies two methods, defined in 
  13993. the ORB class, to build an argument list: create_list and 
  13994. create_operation_list. The IDL prototypes for these methods are as follows: 
  13995.  
  13996. ORBStatus create_list(
  13997.                         in  long        count,        /* # of items */
  13998.                         out NVList      new_list );
  13999.  
  14000. ORBStatus create_operation_list(
  14001.                         in  OperationDef oper,
  14002.                         out NVList       new_list );
  14003.  
  14004. The create_list method returns an NVList with the specified number of elements. 
  14005. Each of the elements is empty. It is the client's responsibility to fill the 
  14006. elements in the list with the correct information using the set_item method. 
  14007. Elements in the NVList must contain the arguments in the same order as they 
  14008. were defined for the operation. Elements are numbered from 0 to count-1. 
  14009.  
  14010. The create_operation_list method returns an NVList initialized with the 
  14011. argument descriptions for a given operation (specified by the OperationDef). 
  14012. The arguments are returned in the same order as they were defined for the 
  14013. operation. The client only needs to fill in the item_value and value_len in the 
  14014. elemens of the NVList. 
  14015.  
  14016. In addition to these CORBA-defined methods, DSOM provides a third version, 
  14017. defined in the SOMDObject class. The IDL prototype for this method is as 
  14018. follows: 
  14019.  
  14020.  
  14021. ORBStatus create_request_args(
  14022.                         in Identifier operation,
  14023.                         out NVList arg_list,
  14024.                         out NamedValue result );
  14025.  
  14026. Like create_operation_list, the create_request_args method creates the 
  14027. appropriate NVList for the specified operation.  In addition, 
  14028. create_request_args initializes the NamedValue that will hold the result with 
  14029. the expected return type. The create_request_args method is defined as a 
  14030. companion to the create_request method, and has the advantage that the 
  14031. InterfaceDef for the operation does not have to be retrieved from the Interface 
  14032. Repository. 
  14033.  
  14034. Note:  The create_request_args method is not  defined in CORBA 1.1. Hence, the 
  14035.        create_operation_list method, defined on the ORB class, should be used 
  14036.        instead when writing portable CORBA-compliant programs. 
  14037.  
  14038.  
  14039. ΓòÉΓòÉΓòÉ 7.19.2.4. Building a Request ΓòÉΓòÉΓòÉ
  14040.  
  14041. There are two ways to build a Request object. Both begin by calling the 
  14042. create_request method defined by the SOMDObject class. The IDL prototype for 
  14043. create_request is as follows: 
  14044.  
  14045. ORBStatus create_request(
  14046.                 in  Context            ctx,
  14047.                 in  Identifier         operation,
  14048.                 in  NVList             arg_list,
  14049.                 inout NamedValue       result,
  14050.                 out Request            request,
  14051.                 in  Flags              req_flags );
  14052.  
  14053. The arg_list can be constructed using the procedures described above and is 
  14054. passed to the Request object in the create_request call. Alternatively, 
  14055. arg_list can be specified as NULL and repetitive calls to add_arg  can be used 
  14056. to specify the argument list. The add_arg method, defined by the Request class, 
  14057. has the following IDL prototype: 
  14058.  
  14059. ORBStatus add_arg(
  14060.                 in  Identifier  name,
  14061.                 in  TypeCode    arg_type,
  14062.                 in  void*       value,
  14063.                 in  long        len,
  14064.                 in  Flags       arg_flags );
  14065.  
  14066.  
  14067. ΓòÉΓòÉΓòÉ 7.19.2.5. Initiating a Request ΓòÉΓòÉΓòÉ
  14068.  
  14069. There are two ways to initiate a request, using either the invoke or send 
  14070. method defined by the Request class. The IDL prototypes for these two 
  14071. operations ar as follows: 
  14072.  
  14073.  
  14074. ORBStatus invoke(
  14075.                 in Flags        invoke_flags );
  14076.  
  14077. ORBStatus send(
  14078.                 in Flags        send_flags );
  14079.  
  14080. The invoke method calls the ORB, which handles the remote method invocation and 
  14081. returns the result. This method will block while awaiting return of the result. 
  14082.  
  14083. The send method calls the ORB but does not wait for the operation to complete 
  14084. before returning. To determine when the operation is complete, the client must 
  14085. call the get_response method (also defined by the Request class), which has 
  14086. this IDL prototype: 
  14087.  
  14088.  
  14089. ORBStatus get_response(
  14090.                 in Flags        response_flags );
  14091.  
  14092. The following flag is defined for get_response: 
  14093.  
  14094.  
  14095. RESP_NO_WAIT       Means that the caller does not want to wait for a 
  14096.  
  14097.                  response.
  14098.  
  14099. get_response determines whether a request has competed. If the RESP_NO_WAIT 
  14100. flag is set, get_response returns immediately even if the request is still in 
  14101. progress. If RESP_NO_WAIT is not set, get_response waits until the request is 
  14102. done before returning. 
  14103.  
  14104.  
  14105. ΓòÉΓòÉΓòÉ 7.19.2.6. Example code ΓòÉΓòÉΓòÉ
  14106.  
  14107. Following is an incomplete example showing how to use the DII to invoke a 
  14108. request having the method procedure prototype shown here: 
  14109.  
  14110.  
  14111. string _testMethod( testObject              obj,
  14112.                     Environment             *ev,
  14113.                     long                    input_value,
  14114. );
  14115.  
  14116. main()
  14117. {
  14118.    ORBStatus rc;
  14119.    Environment ev;
  14120.    SOMDObject obj;
  14121.    NVList arglist;
  14122.    NamedValue result;
  14123.    Context ctx;
  14124.    Request reqObj;
  14125.    OperationDef opdef;
  14126.    Description desc;
  14127.    OperationDescription opdesc;
  14128.    static long input_value = 999;
  14129.  
  14130.    SOM_InitEnvironment(&ev);
  14131.    SOMD_Init(&ev);
  14132.  
  14133. /* create the argument list */
  14134. /* get the operation description from the interface repository */
  14135.    opdef = _lookup_id(SOM_InterfaceRepository, *ev,
  14136.                   "testObject::testMethod");
  14137.    desc = _describe(opdef, &ev);
  14138.    opdesc = (OperationDescription *) desc.value._value;
  14139.  
  14140. /* fill in the TypeCode field for the result */
  14141.    result.argument._type = opdesc->result;
  14142.  
  14143. /* Initialize the argument list */
  14144.    rc = _create_operation_list(SOMD_ORBObject, &ev, opdef,
  14145.                                &arglist);
  14146.  
  14147. /* get default context */
  14148.    rc = _get_default_context(SOMD_ORBObject, &ev, &ctx);
  14149.  
  14150. /* put value and length into the NVList */
  14151.    _get_item(arglist, &ev, 0, &name, &tc, &dummy, &dummylen,
  14152.              &flags);
  14153.  
  14154.    _set_item(arglist, &ev, 0, name, tc, &input_value,
  14155.              sizeof(input_value),flags);
  14156.     ...
  14157. /* create the request - assume the object reference came from
  14158.    somewhere -- from a file or returned by a previous request*/
  14159.    rc = _create_request(obj, &ev, ctx,
  14160.                         "testMethod", arglist, &result, &reqObj,
  14161.                         (Flags)0);
  14162.  
  14163. /* invoke request */
  14164.    rc = invoke(reqObj, &ev, (Flags)0);
  14165.  
  14166. /* print result */
  14167.    printf("result: %s\n",*(string*)(result.argument._value));
  14168.    return(0);
  14169. }
  14170.  
  14171.  
  14172. ΓòÉΓòÉΓòÉ 7.19.3. Creating user-supplied proxies ΓòÉΓòÉΓòÉ
  14173.  
  14174. DSOM uses a proxy object in the client's address space to represent the remote 
  14175. object. As mentioned earlier in this chapter, the proxy object encapsulates the 
  14176. operations necessary to forward and invoke methods on the remote object and 
  14177. return the results. By default, proxy generation is done automatically by the 
  14178. DSOM run time. However, if desired, the programmer can cause a user-supplied 
  14179. proxy class to be loaded instead of letting the run time dynamically generate a 
  14180. default proxy class. User-supplied proxies can be useful in specialized 
  14181. circumstances when local processing or data caching is desired. 
  14182.  
  14183. To build a user-supplied proxy class, it is necessary to understand a bit about 
  14184. how dynamic proxy classes are constructed by the DSOM run time. The DSOM run 
  14185. time constructs a proxy class by creating an instance of a class that inherits 
  14186. the interface and implementation of SOMDClientProxy, and the interface (but not 
  14187. the implementation) of the target class. The methods in the interface of the 
  14188. target object are all overridden to call the somDispatch method (For more 
  14189. details, see "Object references and proxy objects" in section 6.8.) 
  14190.  
  14191. Every SOM object contains the somDispatch method, inherited from SOMObject. 
  14192. This method is used to dynamically dispatch a method on an object, and can be 
  14193. overridden with application-specific dispatching mechanisms. In 
  14194. SOMDClientProxy, the somDispatch method is overridden to forward method calls 
  14195. to the corresponding remote target object. 
  14196.  
  14197. So, in effect, when a method is called on a default proxy object created by the 
  14198. DSOM run time, it redispatches the method to the remote object using DSOM's 
  14199. version of somDispatch. 
  14200.  
  14201. Below is a simple example of a user-supplied proxy class. In this particular 
  14202. example, the proxy object maintains a local, unshared copy of an attribute 
  14203. ("attribute_long") defined in the remote object ("Foo"), while forwarding 
  14204. method invocations ("method1") on to the remote object. The result is that, 
  14205. when multiple clients are talking to the same remote "Foo" object, each client 
  14206. has a local copy of the attribute but all clients share the "Foo" object's 
  14207. implementation of "method1". 
  14208.  
  14209. Note:  It is important to understand that simply setting the attribute in one 
  14210.        client's proxy does not affect the value of the attribute in other 
  14211.        proxies. Maintaining consistency of the cached data values, if desired, 
  14212.        is the responsibility of the user-supplied proxy class. 
  14213.  
  14214.  Following is the IDL file for the "Foo" class: 
  14215.  
  14216.  
  14217.   // foo.idl
  14218.  
  14219.  
  14220.   #include <somdtype.idl>
  14221.   #include <somobj.idl>
  14222.  
  14223.  
  14224.   interface Foo : SOMObject
  14225.   {
  14226.           string  method1(out string a, inout long b,
  14227.                           in ReferenceData c);
  14228.           attribute long attribute_long;
  14229.  
  14230.  
  14231.     implementation
  14232.     {
  14233.        releaseorder: method1, _set_attribute_long,
  14234.                      _get_attribute_long;
  14235.        dllname="foo.dll";
  14236.        somDefaultInit: override;
  14237.     };
  14238.   };
  14239.  
  14240.  The user-supplied proxy class is created by using multiple inheritance between 
  14241.  SOMDClientProxy and the target object (in this case "Foo"). Thus, the IDL file 
  14242.  for the user-supplied proxy class "Foo__Proxy" (note the two underscores) is 
  14243.  as follows: 
  14244.  
  14245.  
  14246.   // fooproxy.idl
  14247.  
  14248.  
  14249.   #include <somdcprx.idl>
  14250.   #include <foo.idl>
  14251.  
  14252.  
  14253.   interface Foo__Proxy : SOMDClientProxy, Foo
  14254.   {
  14255.     implementation
  14256.     {
  14257.        dllname="fooproxy.dll";
  14258.        method1: override;
  14259.     };
  14260.   };
  14261.  
  14262.  When a dynamic proxy class is created by the DSOM run time, the methods 
  14263.  inherited from the target class are automatically overridden to use 
  14264.  somDispatch. When you build a user-supplied proxy, you need to do this 
  14265.  explicitly. This is why "method1" is overridden in the implementation section 
  14266.  of the "fooproxy.idl" file. 
  14267.  
  14268.  The implementation of "method1", which was added to the template produced by 
  14269.  the SOM Compiler, simply calls the somDispatch method on "somSelf" Because 
  14270.  "Foo__Proxy" has inherited the implementation of SOMDClientProxy, calling 
  14271.  somDispatch within "method1" sends the method to the remote "Foo" object. 
  14272.  
  14273.   /* fooproxy.c */
  14274.  
  14275.   #include <somdtype.h>
  14276.   #include <fooproxy.ih>
  14277.  
  14278.   SOM_Scope string  SOMLINK method1(Foo__Proxy somSelf,
  14279.                                     Environment *ev,
  14280.                                     string* a, long* b,
  14281.                                     ReferenceData* c)
  14282.   {
  14283.       string ret_str;
  14284.       somId  methodId;
  14285.  
  14286.  
  14287.   /*  Foo__ProxyData *somThis = Foo__ProxyGetData(somSelf); */
  14288.       Foo__ProxyMethodDebug("Foo__Proxy","method1");
  14289.  
  14290.  
  14291.       /* redispatch method, remotely */
  14292.       methodId = somIdFromString("method1");
  14293.       _somDispatch(somSelf, (void**)&ret_str,
  14294.                    methodId, somSelf, ev, a, b, c);
  14295.       SOMFree(methodId);
  14296.  
  14297.  
  14298.       return ret_str;
  14299.   }
  14300.  
  14301.  In summary, to build a user-supplied proxy class: 
  14302.  
  14303.      Create the .idl file with the proxy class inheriting from both 
  14304.       SOMDClientProxy and from the target class. Important: The user-supplied 
  14305.       proxy class must be named "<targetClassName>_ _Proxy" (with two 
  14306.       underscores in the name) and SOMDClientProxy must be the first class in 
  14307.       the list of parent classes; for example, 
  14308.  
  14309.  
  14310.                     interface Foo_ _Proxy : SOMDClientProxy, Foo
  14311.  
  14312.       Putting SOMDClientProxy first ensures that its version of somDispatch 
  14313.       will be used to dispatch remote method calls. 
  14314.  
  14315.       In the implementation section of the .idl file, override all methods that 
  14316.       are to be invoked on the target class. Do not override methods that are 
  14317.       to be invoked on the local proxy. 
  14318.  
  14319.      Compile the .idl file. Be sure the Interface Repository gets updated with 
  14320.       the .idl file. In the implementation file, for each overridden method, 
  14321.       call somDispatch with the method name and parameters passed into the 
  14322.       overridden method. If the proxy class provides an implementation for the 
  14323.       somInit or somDefaultInit method, then it is important to ensure that 
  14324.       calling that method more than once on the same proxy object has no 
  14325.       negative effect. 
  14326.  
  14327.      Build the DLL and place it in the PATH. Before creating the default 
  14328.       proxy, the DSOM run time checks the PATH for a DLL containing the class 
  14329.       named "   <targetClassName>_ _Proxy" If such a DLL is found, DSOM loads 
  14330.       it instead of dynamically generating a proxy class. 
  14331.  
  14332.  
  14333. ΓòÉΓòÉΓòÉ 7.19.4. Customizing the default base proxy class ΓòÉΓòÉΓòÉ
  14334.  
  14335. Continuing the example from the previous topic, imagine that an application 
  14336. derives 100 subclasses from the "Foo" class. If the application wishes to cache 
  14337. the "Foo::attribute_long" attribute in the proxies for all remote Foo-based 
  14338. objects, the application could supply 100 user-supplied proxy classes, 
  14339. developed in the manner described above. However, this would become a very 
  14340. tedious and repetitive task! 
  14341.  
  14342. Alternatively, it is possible to provide a customized base proxy class for use 
  14343. in the dynamic generation of DSOM proxy classes. This allows an application to 
  14344. provide a customized base proxy class, from which other dynamic DSOM proxy 
  14345. classes can be derived. This is particularly useful in situations where an 
  14346. application would like to enhance many or all dynamically generated proxy 
  14347. classes with a common feature. 
  14348.  
  14349. As described in the previous topic, proxy classes are derived from the 
  14350. SOMDClientProxy class by default. It is the SOMDClientProxy class that 
  14351. overrides somDispatch in order to forward method calls to remote objects. 
  14352.  
  14353. The SOMDClientProxy class can be customized by deriving a subclass in the usual 
  14354. way (being careful not to replace somDispatch or other methods that are 
  14355. fundamental to implementing the proxy's behavior). To extend the above example 
  14356. further, the application might define a base proxy class called "MyClientProxy" 
  14357. that defines a long attribute called "attribute_long," which will be inherited 
  14358. by Foo-based proxy classes. 
  14359.  
  14360. The SOM IDL modifier baseproxyclass can be used to specify which base proxy 
  14361. class DSOM should use during dynamic proxy-class generation. To continue the 
  14362. example, if the class "MyClientProxy" were used to construct the proxy class 
  14363. for a class "XYZ," then the baseproxyclass modifier would be specified s 
  14364. follows: 
  14365.  
  14366. // xyz.idl
  14367.  
  14368. #include <somdtype.idl>
  14369. #include <foo.idl>
  14370.  
  14371. interface XYZ : Foo
  14372. {
  14373.   ...
  14374.   implementation
  14375.   {
  14376.      ...
  14377.      baseproxyclass = MyClientProxy;
  14378.   };
  14379. };
  14380.  
  14381. It should be noted that: 
  14382.  
  14383.      Base proxy classes must be derived from SOMDClientProxy. 
  14384.  
  14385.      If a class "XYZ" specifies a custom base-proxy class, as in the above 
  14386.       example, subclasses of "XYZ" do not  inherit the value of the 
  14387.       baseproxyclass modifier. If needed, the  baseproxyclass modifier must be 
  14388.       specified explicitly in each class. 
  14389.  
  14390.  
  14391. ΓòÉΓòÉΓòÉ 7.20. Error Reporting and Troubleshooting ΓòÉΓòÉΓòÉ
  14392.  
  14393. When the DSOM run-time environment encounters an error during execution of a 
  14394. method or procedure, a SYSTEM_EXCEPTION will be raised. The standard system 
  14395. exceptions are discussed in the topic "Exceptions and Error Handling" in 
  14396. Chapter 3 "Using SOM Classes in Client Programs." The "minor" field of the 
  14397. returned exception value will contain a DSOM error code. The DSOM error codes 
  14398. are listed below. 
  14399.  
  14400. Although a returned exception value can indicate that a DSOM run-time error 
  14401. occurred, it may be difficult for the user or application to determine what 
  14402. caused the error. Consequently, DSOM has been enabled to report run-time error 
  14403. information, for interpretation by IBM support personnel. These error messages 
  14404. take the following form: 
  14405.  
  14406.  
  14407. DSOM <type> error:  <code> [<name>] at  <file>:<line>
  14408.  
  14409. where the arguments are as follows: 
  14410.  
  14411.  
  14412. type    SYSTEM_EXCEPTION type,
  14413. code    DSOM error code,
  14414. name symbol for DSOM error code (from "somderr.h"),
  14415. file    source-file name where the error occurred, and
  14416. line    line number where the error occurred.
  14417.  
  14418. For example, 
  14419.  
  14420.  
  14421. DSOM NO_MEMORY error: 30001 [SOMDERROR_NoMemory] at somdobj.c:250
  14422.  
  14423. indicates that a "NO_MEMORY" error (error code 30001) occurred in file 
  14424. "somdobj.c" at line 250. This information is not usually meaningful to the 
  14425. user; it provides IBM support personnel with a starting point for problem 
  14426. analysis. There will often be a sequence of error messages; together they 
  14427. indicate the context in which the error occurred. It is important to give all 
  14428. reported messages to IBM support personnel for analysis. 
  14429.  
  14430. There is an environment variable, SOMDDEBUG, which is used to activate error 
  14431. reporting. There is a corresponding global variable that can be set by an 
  14432. application program; it is declared as: 
  14433.  
  14434. extern long SOMD_DebugFlag;
  14435.  
  14436. Error reporting is normally disabled. To enable error reporting, the 
  14437. environment variable SOMDDEBUG should be set to a value greater than 0. To 
  14438. disable error reporting, SOMDDEBUG should be set to a value less than or equal 
  14439. to 0. 
  14440.  
  14441. By default, error messages will display on the standard output device. Error 
  14442. messages can also be redirected to a log file. For this, the environment 
  14443. variable SOMDMESSAGELOG should be set to the pathname of the log file. The 
  14444. SOMD_ Init procedure opens the file named in SOMDMESSAGELOG (if any), during 
  14445. process initialization. 
  14446.  
  14447.  
  14448. ΓòÉΓòÉΓòÉ 7.20.1. Error codes ΓòÉΓòÉΓòÉ
  14449.  
  14450. The error codes that may be encountered when using DSOM are listed in Appendix 
  14451. A, "SOMobjects Error Codes," which contains the codes for the entire SOMobjects 
  14452. Toolkit. 
  14453.  
  14454.  
  14455. ΓòÉΓòÉΓòÉ 7.20.2. Troubleshooting hints ΓòÉΓòÉΓòÉ
  14456.  
  14457. The following hints may prove helpful as you develop and test your DSOM 
  14458. application. 
  14459.  
  14460.  
  14461. ΓòÉΓòÉΓòÉ 7.20.2.1. Checking the DSOM setup ΓòÉΓòÉΓòÉ
  14462.  
  14463. This checklist will help you make certain that the DSOM environment is set up 
  14464. correctly. 
  14465.  
  14466.    1. For all application classes, IDL must be compiled into the Interface 
  14467.       Repository.  You can verify that a class exists in the Interface 
  14468.       Repository by executing "irdump<class>" See "Registering class 
  14469.       interfaces" for more information. 
  14470.  
  14471.    2. An implementation (a server program and class libraries) must be 
  14472.       registered with DSOM by running the regimpl utility. See "Registering 
  14473.       servers and classes" for more information. 
  14474.  
  14475.    3. Verify that all class libraries and networking libraries are in 
  14476.       directories specified in PATH. 
  14477.  
  14478.  
  14479. ΓòÉΓòÉΓòÉ 7.20.2.2. Analyzing problem conditions ΓòÉΓòÉΓòÉ
  14480.  
  14481. The DSOM error codes mentioned below can be obtained directly by the 
  14482. application from the "minor" field of the exception data returned in a system 
  14483. exception, or from an error report message when SOMDDEBUG is set to a positive 
  14484. integer value (see the previous topic, "Error reporting"). 
  14485.  
  14486. Symptom:  When running regimpl, a "PERSIST_STORE" or "NO_IMPLEMENT" exception 
  14487. is returned. The DSOM error code is SOMDERROR_IO or SOMDERROR_NoImplDatabase. 
  14488.  
  14489.      This may indicate that the Implementation Repository files are not found 
  14490.       or cannot be accessed. Verify that SOMDDIR is set correctly, to a 
  14491.       directory that has granted read/write permission to the DSOM user. (It is 
  14492.       best if the directory name is fully qualified.) If the SOMDDIR variable 
  14493.       is not set, verify that the default directory %SOMBASE%\etc\dsom) has 
  14494.       been set up with the correct permissions. Ensure that the the files 
  14495.       contained in the directory all have read/write permission granted to the 
  14496.       DSOM user. 
  14497.  
  14498.  Symptom:  When starting somdd, an "INITIALIZE" exception is returned with 
  14499.  error code SOMDAlreadyRunning. 
  14500.  
  14501.      This indicates that there is already an instance of somdd running.  If 
  14502.       the current instance of somdd does not seem to be responding properly, 
  14503.       delete all instances of somdd and restart a new copy of somdd. 
  14504.  
  14505.  Symptom:  When starting up a server program, an exception is returned with a 
  14506.  DSOM error code of SOMDERROR_ServerAlreadyExists. 
  14507.  
  14508.      This may indicate that a server process that is already running has 
  14509.       already registered itself with the DSOM daemon, somdd, using the 
  14510.       implementation ID of the desired server program. 
  14511.  
  14512.  Symptom:  A remote method invocation fails and an "INTF_REPOS" exception is 
  14513.  returned. The DSOM error code is SOMDERROR_BadDescriptor or 
  14514.  SOMDERROR_ClassNotlnIR. 
  14515.  
  14516.      This may indicate that the interface describing the method or the method 
  14517.       itself cannot be found in the Interface Repository. Verify that SOMIR is 
  14518.       set correctly, and that the IR contains all interfaces used by your 
  14519.       application. 
  14520.  
  14521.       If the default SOM IR (supplied with the SOMobjects Toolkit and Runtimes) 
  14522.       is not used by the application, the user's IR must include the interface 
  14523.       definitions for the Sockets class, server class (derived from 
  14524.       SOMDServer), and the definitions of the standard DSOM exceptions (found 
  14525.       in file "stexcep.idl") that may be returned by a method call. 
  14526.  
  14527.  Symptom:  A SOMDERROR_ClassNotFound error is returned by a client either when 
  14528.  creating a remote object using somdNewObject, or when finding a server object 
  14529.  using somdFindAnyServerByClass. (The methods are defined on the SOMDObjectMgr 
  14530.  class.) 
  14531.  
  14532.      This occurs when the class name specified in calls to somdNewObject or 
  14533.       somdFindAnyServerByClass cannot be found in the Implementation 
  14534.       Repository. Make sure that the class name has been associated with at 
  14535.       least one of the server implementations. 
  14536.  
  14537.  Symptom:  A SOMDERROR_ClassNotlnlR error is returned by a server when creating 
  14538.  a new object using somdNewObject, somdCreateObj, or somdGetClassObj. 
  14539.  
  14540.      This error may result if the DLL for the class cannot be found. Verify 
  14541.       hat: 
  14542.  
  14543.            -the interface of the object can be found in the IR; 
  14544.  
  14545.            -the class name is spelled correctly and is appropriately scoped 
  14546.            (for example, the "Printer" class in the "PrintServer" module must 
  14547.            have the identifier "PrintServer:: Printer"). 
  14548.  
  14549.      This error can also result when the shared library is statically linked 
  14550.       to the server program, but the <className>NewClass procedures have not 
  14551.       been called to initialize the classes. 
  14552.  
  14553.  Symptom: When invoking a method returns a proxy for a remote object in the 
  14554.  client, a SOMDERROR_NoParentClass error occurs. 
  14555.  
  14556.      This error may result when the class libraries used to build the proxy 
  14557.       class are statically linked to the program, but the <className>NewClass 
  14558.       procedure have not been called to initialize the classes. 
  14559.  
  14560.  Symptom:  Following a method call, the SOM run-time error message, "A target 
  14561.  object failed basic validity checks during method resolution" is displayed. 
  14562.  
  14563.      Usually this means that the method call was invoked using a bad object 
  14564.       pointer, or the object has been corrupted. 
  14565.  
  14566.  Symptom:  A remote object has an attribute or instance variable that is, or 
  14567.  contains, a pointer to a value in memory (for example, a string, a sequence, 
  14568.  an "any"). The attribute or instance variable value is set by the client with 
  14569.  one method call. When the attribute or instance variable is queried in a 
  14570.  subsequent method call, the value referenced by the pointer is "garbage". 
  14571.  
  14572.      This may occur because DSOM makes a copy  of argument values in a client 
  14573.       call, for use in the remote call. The argument values are valid for the 
  14574.       duration of that call. When the remote call is completed, the copies of 
  14575.       the argument values are freed. 
  14576.  
  14577.       In a DSOM application, a class should not assume ownership of memory 
  14578.       passed to it in a method parameter unless the IDL description of the 
  14579.       method includes the SOM IDL modifier object_owns_parameters.  Otherwise, 
  14580.       if a parameter value is meant to persist between method invocations, then 
  14581.       the object is responsible for making a copy of the parameter value. 
  14582.  
  14583.  Symptom:  A method defines a (char *) parameter that is used to pass a string 
  14584.  input value to an object. The object attempts to print the string value, but 
  14585.  it appears to be "garbage". 
  14586.  
  14587.      DSOM will support method arguments that are of type "pointer-to-X" 
  14588.       (pointer types are a SOM extension), by dereference the pointer in the 
  14589.       call, and copying the base value. The pointer-to-value is reconstructed 
  14590.       on the server before the actual method call is made. 
  14591.  
  14592.       While (char *) is commonly used to refer to NULL-terminated strings in C 
  14593.       programs, (char *) could also be a pointer to a single character or to an 
  14594.       array of characters. Thus, DSOM interprets the argument type literally as 
  14595.       a pointer-to-one-character. 
  14596.  
  14597.       To correctly pass strings or array arguments, the appropriate CORBA type 
  14598.       should be used (for example, "string" or "char foo[4 ]"). 
  14599.  
  14600.  Symptom:  A segmentation violation occurs when passing an "any" argument to a 
  14601.  method call, where the "any" value is a string, array, or object reference. 
  14602.  Note: The NamedValues used in DII calls use "any" fields for the argument 
  14603.  values. 
  14604.  
  14605.      This error may occur because the  "_value"  field of the "any" structure 
  14606.       does not contain the address of a pointer to the target string, array, or 
  14607.       object reference, as it should. (A common mistake is to set the "_value" 
  14608.       field to the address of the string, array, or object reference itself.) 
  14609.  
  14610.  Symptom:  When a server program or a server object makes a call to get_id or 
  14611.  to get_SOM_object on a SOMDObject, a "BAD_OPERATION" exception is returned 
  14612.  with an error code of SOMDERROR_WrongRefType. 
  14613.  
  14614.      This error may occur when the operation get_id is called on a SOMDObject 
  14615.       that does not have any user-supplied ReferenceData (that is, the 
  14616.       SOMDObject is a proxy, is nil, or is a simple "SOM ref" created by 
  14617.       create_SOM_ref). Likewise, this error may occur when the operation 
  14618.       get_SOM_object is called on a SOMDObject that was not created by the 
  14619.       create_SOM_ref method. 
  14620.  
  14621.  Symptom:  A segmentation fault occurs when a SOMD_Uninit call is executed. 
  14622.  
  14623.      This error could occur if the application has already freed any of the 
  14624.       DSOM run-time objects that were allocated by the SOMD_Init call, 
  14625.       including SOMD_ObjectMgr, SOMD_ImplRepObject and SOMD_ORBObject. 
  14626.  
  14627.  Symptom:  Unexplained program crashes. 
  14628.  
  14629.      Verify that all DSOM environment variables are set, as described in the 
  14630.       earlier section "Configuring DSOM Applications". Verify that all class 
  14631.       libraries are in directories specified in in PATH. Verify that the 
  14632.       contents of the Interface Repository, specified by SOMIR, are correct. 
  14633.       Verify that the contents of the Implementation Repository, specified by 
  14634.       SOMDDIR, are correct. Verify that somdd is running. Set SOMDDEBUG to 1 to 
  14635.       obtain additional DSOM error messages. 
  14636.  
  14637.  Symptom:  When starting somdd, an "INITIALIZE" error is returned with error 
  14638.  code SOMDERROR_NoSocketsClass. 
  14639.  
  14640.      If SOMSOCKETS is set, verify that the IR contains the Sockets interface 
  14641.       definition. 
  14642.  
  14643.  
  14644. ΓòÉΓòÉΓòÉ 7.21. Limitations ΓòÉΓòÉΓòÉ
  14645.  
  14646. The following list indicates known limitations of Distributed SOM at the time 
  14647. of this release. 
  14648.  
  14649.    1. Currently, objects cannot be moved from one server to another without 
  14650.       changing the object references (i.e., deleting the object, and creating 
  14651.       it anew in another server). This yields all copies of the previous 
  14652.       reference invalid. 
  14653.  
  14654.    2. The change_implementation method is not supported. This method, defined 
  14655.       by the BOA interface, is intended to allow an application to change the 
  14656.       implementation definition associated with an object. However, in DSOM, 
  14657.       changing the server implementation definition may render existing object 
  14658.       references (which contain the old server ID) invalid. 
  14659.  
  14660.    3. Currently, DSOM has a single server activation policy, which corresponds 
  14661.       to CORBA's "shared" activation policy for dynamic activation, and 
  14662.       "persistent" activation policy for manual activation. Other activation 
  14663.       policies, such as "server-per-method" and "unshared" are not directly 
  14664.       supported, and must be implemented by the application. 
  14665.  
  14666.       Since the unshared server policy is not directly supported, the 
  14667.       object_is_ready and deactivate_obj methods, defined in the BOA interface 
  14668.       have null implementations. 
  14669.  
  14670.    4. If a server program terminates without calling deactivate_impl, 
  14671.       subsequent attempts to start that server may fail. The DSOM daemon 
  14672.       believes the server is still running until it is told it has stopped. 
  14673.       Attempts to start a server that is believed to be exist results in an 
  14674.       error (SOMDERROR_ServerAlreadyExists). 
  14675.  
  14676.    5. Currently, file names used in ImplementationDefs are limited to 255 
  14677.       bytes. Implementations aliases used in ImplementationDefs are limited to 
  14678.       50 bytes. Class names used in the Implementation Repository are limited 
  14679.       to 50 bytes. Hostnames are limited to 32 bytes. 
  14680.  
  14681.    6. The OUT_LIST_MEMORY, IN_COPY_VALUE, and DEPENDENT_LIST flags, used with 
  14682.       Dynamic Invocation Interface, are not yet supported. 
  14683.  
  14684.    7. The Context::get_values method currently does not support the flag 
  14685.       CTX_RESTRICT_SCOPE. 
  14686.  
  14687.  Other important notes concerning DSOM are documented in the "README" file in 
  14688.  the SOMBASE root directory ($SOMBASE on AIX, and %SOMBASE% on OS/2 or 
  14689.  Windows). 
  14690.  
  14691.  
  14692. ΓòÉΓòÉΓòÉ 8. The SOM Interface Repository Framework ΓòÉΓòÉΓòÉ
  14693.  
  14694. This section covers the following subjects: 
  14695.  
  14696.      Introduction 
  14697.      Using the SOM Compiler to Build an Interface Repository 
  14698.      Managing Interface Repository files 
  14699.      Programming with the Interface Repository Objects 
  14700.  
  14701.  
  14702. ΓòÉΓòÉΓòÉ 8.1. Introduction ΓòÉΓòÉΓòÉ
  14703.  
  14704. The SOM Interface Repository (IR) is a database that the SOM Compiler 
  14705. optionally creates and maintains from the information supplied in IDL source 
  14706. files. The Interface Repository contains persistent objects that correspond to 
  14707. the major elements in IDL descriptions. The SOM Interface Repository Framework 
  14708. is a set of classes that provide methods whereby executing programs can access 
  14709. these objects to discover everything known about the programming interfaces of 
  14710. SOM classes. 
  14711.  
  14712. The programming interfaces used to interact with Interface Repository objects, 
  14713. as well as the format and contents of the information they return, are 
  14714. architected and defined as part of the Object Management Group's CORBA 
  14715. standard. The classes composing the SOM Interface Repository Framework 
  14716. implement the programming interface to the CORBA Interface Repository. 
  14717. Accordingly, the SOM Interface Repository Framework supports all of the 
  14718. interfaces described in The Common Object Request Broker: Architecture and 
  14719. Specification (OMG Document Number 91.12.1, Revision 1.1, chapter 7). 
  14720.  
  14721. As an extension to the CORBA standard, the SOM Interface Repository Framework 
  14722. permits storage in the Interface Repository of arbitrary information in the 
  14723. form of SOM IDL modifiers. That is, within the SOM-unique implementation 
  14724. section of an IDL source file or through the use of the #pragma modifier 
  14725. statement, user-defined modifiers can be associated with any element of an IDL 
  14726. specification. (See the section entitled "SOM Interface Definition Language" in 
  14727. Chapter 4, "SOM IDL and the SOM Compiler.") When the SOM Compile creates the 
  14728. Interface Repository from an IDL specification, these potentially arbitrary 
  14729. modifiers are stored in the IR and can then be accessed via the methods 
  14730. provided by the Interface Repository Framework. 
  14731.  
  14732. This chapter describes, first, how to build and manage interface repositories, 
  14733. and second, the programming interfaces embodied in the SOM Interface Repository 
  14734. Framework. 
  14735.  
  14736.  
  14737. ΓòÉΓòÉΓòÉ 8.2. Using the SOM Compiler to Build an Interface Repository ΓòÉΓòÉΓòÉ
  14738.  
  14739. The SOMobjects Toolkit includes an Interface Repository emitter that is invoked 
  14740. whenever the SOM Compiler is run using an sc command with the -u option (which 
  14741. "updates" the interface repository). The IR emitter can be used to create or 
  14742. update an Interface Repository file. The IR emitter expects that an environment 
  14743. variable, SOMIR, was first set to designate a file name for the Interface 
  14744. Repository. For example, to compile an IDL source file named "newcls.idl" and 
  14745. create an Interface Repository named "newcls.ir", use a command sequence 
  14746. similar to the following: 
  14747.  
  14748. set SOMIR=c:\myfiles\newcls.ir
  14749. sc -u newcls
  14750.  
  14751. If the SOMIR environment variable is not set, the Interface Repository emitter 
  14752. creates a file named "som.ir" in the current directory. 
  14753.  
  14754. The sc or command runs the Interface Repository emitter plus any other emitters 
  14755. indicated by the environment variable SMEMIT (described in the topic "Running 
  14756. the SOM Compiler" in Chapter 4, "Implementing SOM Classes"). To run the 
  14757. Interface Repository emitter by itself, issue the sc command with the -s option 
  14758. (which overrides SMEMIT) set to "ir". For example: 
  14759.  
  14760. sc -u -sir newcls
  14761. or equivalently, 
  14762.  
  14763. sc -usir newcls
  14764.  
  14765. The Interface Repository emitter uses the SOMIR environment variable to locate 
  14766. the designated IR file. If the file does not exist, the IR emitter creates it. 
  14767. If the named interface repository already exists, the IR emitter checks all of 
  14768. the "type" information in the IDL source file being compiled for internal 
  14769. consistency, and then changes the contents of the interface repository file to 
  14770. agree with with the new IDL definition. For this reason, the use of the -u 
  14771. compiler flag requires that all of the types mentioned in the IDL source file 
  14772. must be fully defined within the scope of the compilation. Warning messages 
  14773. from the SOM Compiler about undefined types result in actual error messages 
  14774. when using the -u flag. 
  14775.  
  14776. The additional type checking and file updating activity implied by the -u flag 
  14777. increases the time it takes to run the SOM Compiler. Thus, when developing an 
  14778. IDL class description from scratch, where iterative changes are to be expected, 
  14779. it may be preferable not to use the -u compiler option until the class 
  14780. definition has stabilized. 
  14781.  
  14782.  
  14783. ΓòÉΓòÉΓòÉ 8.3. Managing Interface Repository files ΓòÉΓòÉΓòÉ
  14784.  
  14785. Just as the number of interface definitions contained in a single IDL source 
  14786. file is optional, similarly, the number of IDL files compiled into one 
  14787. interface repository file is also at the programmer's discretion. Commonly, 
  14788. however, all interfaces needed for a single project or class framework are kept 
  14789. in one interface repository. 
  14790.  
  14791.  
  14792. ΓòÉΓòÉΓòÉ 8.3.1. The SOM  IR file "som.ir" ΓòÉΓòÉΓòÉ
  14793.  
  14794. The SOMobjects Toolkit includes an Interface Repository file ("som.ir") that 
  14795. contains objects describing all of the types, classes, and methods provided by 
  14796. the various frameworks of the SOMobjects Toolkit. Since all new classes will 
  14797. ultimately be derived from these predefined SOM classes, some of this 
  14798. information also needs to be included in a programmer's own interface 
  14799. repository files. 
  14800.  
  14801. For example, suppose a new class, called "MyClass", is derived from SOMObject. 
  14802. When the SOM Compiler builds an Interface Repository for "MyClass", that IR 
  14803. will also include all of the information associated with the SOMObject class. 
  14804. This happens because the SOMObject class definition is inherited by each new 
  14805. class; thus, all of the SOMObject methods and typedefs are implicitly contained 
  14806. in the new class as well. 
  14807.  
  14808. Eventually, the process of deriving new classes from existing ones would lead 
  14809. to a great deal of duplication of information in separate interface repository 
  14810. files. This would be inefficient, wasteful of space, and extremely difficult to 
  14811. manage. For example, to make an evolutionary change to some class interface, a 
  14812. programmer would need to know about and subsequently update all of the 
  14813. interface repository files where information about that interface occurred. 
  14814.  
  14815. One way to avoid this dilemma would be to keep all interface definitions in a 
  14816. single interface repository (such as "som.ir"). This is not recommended, 
  14817. however. A single interface repository would soon grow to be unwieldy in size 
  14818. and become a source of frequent access contention. Everyone involved in 
  14819. developing class definitions would need update access to this one file, and 
  14820. simultaneous uses might result in longer compile times. 
  14821.  
  14822.  
  14823. ΓòÉΓòÉΓòÉ 8.3.2. Managing IRs via the SOMIR environment variable ΓòÉΓòÉΓòÉ
  14824.  
  14825. The SOMobjects Toolkit offers a more flexible approach to managing interface 
  14826. repositories. The SOMIR environment variable can reference an ordered list of 
  14827. separate IR files, which process from left to right. Taken as a whole, however, 
  14828. this gives the appearance of a single, logical interface repository. A 
  14829. programmer accessing the contents of "the interface repository" through the SOM 
  14830. Interface Repository framework would not be aware of the division of 
  14831. information across separate files. It would seem as though all of the objects 
  14832. resided in a single interface repository file. 
  14833.  
  14834. A typical way to utilize this capability is as follows: 
  14835.  
  14836.      The first (leftmost) Interface Repository in the SOMIR list would be 
  14837.       "som.ir". This file contains the basic interfaces and types needed in all 
  14838.       SOM classes. 
  14839.  
  14840.      The second file in the list might contain interface definitions that are 
  14841.       used globally across a particular enterprise. 
  14842.  
  14843.      A third interface repository file would contain definitions that are 
  14844.       unique to a particular department, and so on. 
  14845.  
  14846.      The final interface repository in the list should be set aside to hold 
  14847.       the interfaces needed for the project currently under development. 
  14848.  
  14849.  Developers working on different projects would each set their SOMIR 
  14850.  environment variables to hold slightly different lists. For the most part, the 
  14851.  leftmost portions of these lists would be the same, but the rightmost 
  14852.  interface repositories would differ. When any given developer is ready to 
  14853.  share his/her interface definitions with other people outside of the immediate 
  14854.  work group, that person's interface repository can be promoted to inclusion in 
  14855.  the master list. 
  14856.  
  14857.  With this arrangement of IR files, the more stable repositories are found at 
  14858.  the left end of the list. For example, a developer should never need to make 
  14859.  any significant changes to "som.ir", because these interfaces are defined by 
  14860.  IBM and would only change with a new release of the SOMobjects Toolkit. 
  14861.  
  14862.  The Interface Repository Framework only permits updates in the rightmost file 
  14863.  of the SOMIR interface repository list. That is, when the SOM Compiler -u flag 
  14864.  is used to update the Interface Repository, only the final file on the IR list 
  14865.  will be affected. The information in all preceding interface repository files 
  14866.  is treated as "read only".  Therefore, to change the definition of an 
  14867.  interface in one of the more global interface repository files, a developer 
  14868.  must overtly construct a special SOMIR list that omits all subsequent (that 
  14869.  is, further to the right) interface repository files, or else petition the 
  14870.  owner of that interface to make the change. 
  14871.  
  14872.  It is important the the rightmost filename in the SOMIR interface repository 
  14873.  list not appear elsewhere in the list.  For Example, the following setting for 
  14874.  SOMIR: 
  14875.  
  14876.        %SOMBASE5\ETC\SOM.IR;SOM.IR;C:\IR\COMPANY.IR;SOM.IR
  14877.  
  14878.  would cause problems when attempting to update the SOM.IR file, because SOM.IR 
  14879.  appears twice in the list. 
  14880.  
  14881.  Here is an example that illustrates the use of multiple IR files with the 
  14882.  SOMIR environment variable. In this example, the SOMBASE environment variable 
  14883.  represents the directory in which the SOMobjects Toolkit files have been 
  14884.  installed. Only the "myown.ir" interface repository file will be updated with 
  14885.  the interfaces found in files "myclass1.idl", "myclass2.idl", and 
  14886.  "myclass3.idl". 
  14887.  
  14888.   set BASE_IRLIST=%SOMBASE%\IR\SOM.IR;C:\IR\COMPANY.IR;C:\IR\DEPT10.IR
  14889.   set SOMIR=%BASE_IRLIST%;D:\MYOWN.IR
  14890.   set SMINCLUDE=.;%SOMBASE%\INCLUDE;C:\COMPANY\INCLUDE;C:\DEPT10\INCLUDE
  14891.   sc -usir myclass1
  14892.   sc -usir myclass2
  14893.   sc -usir myclass3
  14894.  
  14895.  
  14896. ΓòÉΓòÉΓòÉ 8.3.3. Placing `private' information in the Interface Repository ΓòÉΓòÉΓòÉ
  14897.  
  14898. When the SOM Compiler updates the Interface Repository in response to the -u 
  14899. flag, it uses all of the information available from the IDL source file. 
  14900. However, if the __PRIVATE__ preprocessor variable is used to designate certain 
  14901. portions of the IDL file as private, the preprocessor actually removes that 
  14902. information before the SOM Compiler sees it. Consequently, private information 
  14903. will not appear in the Interface Repository unless the -p compiler option is 
  14904. also used in conjunction with -u. For example: 
  14905.  
  14906. sc -up myclass1
  14907.  
  14908. This command will place all of the information in the "myclass1.idl" file, 
  14909. including the private portions, in the Interface Repository. 
  14910.  
  14911. If you are using tools that understand SOM and rely on the Interface Repository 
  14912. to describe the types and instance data in your classes, you may need to 
  14913. include the private sections from your IDL source files when building the 
  14914. Interface Repository. 
  14915.  
  14916.  
  14917. ΓòÉΓòÉΓòÉ 8.4. Programming with the Interface Repository Objects ΓòÉΓòÉΓòÉ
  14918.  
  14919. The SOM Interface Repository Framework provides an object-oriented programming 
  14920. interface to the IDL information processed by the SOM Compiler. Unlike many 
  14921. frameworks that require you to inherit their behavior in order to use it, the 
  14922. Interface Repository Framework is useful in its own right as a set of 
  14923. predefined objects that you can access to obtain information. Of course, if you 
  14924. need to subclass a class to modify its behavior, you can certainly do so; but 
  14925. typically this is not necessary. 
  14926.  
  14927. The SOM Interface Repository contains the fully-analyzed (compiled) contents of 
  14928. all information in an IDL source file. This information takes the the form of 
  14929. persistent objects that can be accessed from a running program. There are ten 
  14930. classes of objects in the Interface Repository that correspond directly to the 
  14931. major elements in IDL source files; in addition, one instance of another class 
  14932. exists outside of the IR itself, as follows: 
  14933.  
  14934.  Contained                All objects in the Interface Repository are instances 
  14935.                           of classes derived from this class and exhibit the 
  14936.                           common behavior defined in this interface. 
  14937.  
  14938.  Container                Some objects in the Interface Repository hold (or 
  14939.                           contain) other objects. (For example, a module 
  14940.                           [ModuleDef] can contain an interface [InterfaceDef].) 
  14941.                           All Interface Repository objects that hold other 
  14942.                           objects are instances of classes derived from this 
  14943.                           class and exhibit the common behavior defined by this 
  14944.                           class. 
  14945.  
  14946.  ModuleDef                An instance of this class exists for each module 
  14947.                           defined in an IDL source file. ModuleDefs are 
  14948.                           Containers, and they can  hold ConstantDefs, 
  14949.                           TypeDefs,  ExceptionDefs, InterfaceDefs, and other 
  14950.                           ModuleDefs. 
  14951.  
  14952.  InterfaceDef             An instance of this class exists for each interface 
  14953.                           named in an IDL source file. (One InterfaceDef 
  14954.                           corresponds to one SOM class.)  InterfaceDefs are 
  14955.                           Containers, and they can hold ConstantDefs, TypeDefs, 
  14956.                           ExceptionDefs, AttributeDefs, and OperationDefs. 
  14957.  
  14958.  AttributeDef             An instance of this class exists for each attribute 
  14959.                           defined in an IDL source file. AttributeDefs are 
  14960.                           found only inside of (contained by) InterfaceDefs. 
  14961.  
  14962.  OperationDef             An instance of this class exists for each operation 
  14963.                           (method, _set_method, and _get_method) defined in an 
  14964.                           IDL source file. OperationDefs are Containers that 
  14965.                           can hold ParameterDefs. OperationDefs are found only 
  14966.                           inside of (contained by) InterfaceDefs. 
  14967.  
  14968.  ParameterDef             An instance of this class exists for each parameter 
  14969.                           of each operation (method) defined in an IDL source 
  14970.                           file. ParameterDefs are found only inside of 
  14971.                           (contained by) OperationDefs. 
  14972.  
  14973.  TypeDef                  An instance of this class exists for each typedef, 
  14974.                           struct, union, or enum defined in an IDL source file. 
  14975.                           TypeDefs may be found inside of (contained by) any 
  14976.                           Interface Repository Container except an 
  14977.                           OperationDef. 
  14978.  
  14979.  ConstantDef              An instance of this class exists for each constant 
  14980.                           defined in an IDL source file. ConstantDefs may be 
  14981.                           found inside (contained by) of any Interface 
  14982.                           Repository Container except an OperationDef. 
  14983.  
  14984.  ExceptionDef             An instance of this class exists for each exception 
  14985.                           defined in an IDL source file. ExceptionDefs may be 
  14986.                           found inside of (contained by) any Interface 
  14987.                           Repository Container except an OperationDef. 
  14988.  
  14989.  Repository               One instance of this class exists for the entire SOM 
  14990.                           Interface Repository, to hold IDL elements that are 
  14991.                           global in scope. The instance of this class does not, 
  14992.                           however, reside within the IR itself. 
  14993.  
  14994.  
  14995. ΓòÉΓòÉΓòÉ 8.4.1. Methods introduced by Interface Repository classes ΓòÉΓòÉΓòÉ
  14996.  
  14997. The Interface Repository classes introduce nine new methods, which are briefly 
  14998. described below. Many of the classes simply override methods to customize them 
  14999. for the corresponding IDL element; this is particularly true for classes 
  15000. representing IDL elements that are only contained within another syntactic 
  15001. element. Full descriptions of each method are found in the SOM Programming 
  15002. Reference. 
  15003.  
  15004.      Contained class methods (all IR objects are instances of this class and 
  15005.       exhibit this behavior): 
  15006.  
  15007.       describe                      Returns a structure of type Description 
  15008.                                     containing all information defined in the 
  15009.                                     IDL specification of the syntactic element 
  15010.                                     corresponding to the target Contained 
  15011.                                     object. For example, for a target 
  15012.                                     InterfaceDef object, the describe method 
  15013.                                     returns information about the IDL interface 
  15014.                                     declaration. The Description structure 
  15015.                                     contains a "name" field with an identifier 
  15016.                                     that categorizes the description (such as, 
  15017.                                     "InterfaceDescription") and a "value" field 
  15018.                                     holding an "any" structure that points to 
  15019.                                     another structure containing the IDL 
  15020.                                     information for that particular element (in 
  15021.                                     this example, the interface's IDL 
  15022.                                     specifications). 
  15023.  
  15024.       within                        Returns a sequence designating the 
  15025.                                     object(s) of the IR within which the target 
  15026.                                     Contained object is contained. For example, 
  15027.                                     for a target TypeDef object, it might be 
  15028.                                     contained within any other IR object(s) 
  15029.                                     except an OperationDef object. 
  15030.  
  15031.      Container class methods (some IR objects contain other objects and 
  15032.       exhibit this behavior): 
  15033.  
  15034.       contents                      Returns a sequence of pointers to the 
  15035.                                     object(s) of the IR that the target 
  15036.                                     Container object contains. (For example, 
  15037.                                     for a target InterfaceDef object, the 
  15038.                                     contents method returns a pointer to each 
  15039.                                     IR object that corresponds to a part of the 
  15040.                                     IDL interface declaration.) The method 
  15041.                                     provides options for excluding inherited 
  15042.                                     objects or for limiting the search to only 
  15043.                                     a specified kind of object (such as 
  15044.                                     AttributeDefs). 
  15045.  
  15046.       describe_contents             Combines the describe and contents methods; 
  15047.                                     returns a sequence of ContainerDescription 
  15048.                                     structures, one for each object contained 
  15049.                                     by the target Container object. Each 
  15050.                                     structure has a pointer to the related 
  15051.                                     object, as well as "name" and "value" 
  15052.                                     fields resulting from the describe method. 
  15053.  
  15054.       lookup_name                   Returns a sequence of pointers to objects 
  15055.                                     of a given name contained within a 
  15056.                                     specified Container object, or within 
  15057.                                     (sub)objects contained in the specified 
  15058.                                     Container object. 
  15059.  
  15060.      ModuleDef class methods: 
  15061.  
  15062.                                     Override describe and within. 
  15063.  
  15064.      InterfaceDef class methods: 
  15065.  
  15066.       describe_interface            Returns a description of all methods and 
  15067.                                     attributes of a given interface definition 
  15068.                                     object that are held in the Interface 
  15069.                                     Repository. 
  15070.  
  15071.                                     Also overrides describe and within. 
  15072.  
  15073.      AttributeDef class method: 
  15074.  
  15075.                                     Overrides describe. 
  15076.  
  15077.      OperationDef class method: 
  15078.  
  15079.                                     Overrides describe. 
  15080.  
  15081.      ParameterDef class method: 
  15082.  
  15083.                                     Overrides describe. 
  15084.  
  15085.      TypeDef  class method: 
  15086.  
  15087.                                     Overrides describe. 
  15088.  
  15089.      ConstantDef class method: 
  15090.  
  15091.                                     Overrides describe. 
  15092.  
  15093.      ExceptionDef class method: 
  15094.  
  15095.                                     Overrides describe. 
  15096.  
  15097.      Repository class methods: 
  15098.  
  15099.       lookup_id                     Returns the Contained object that has a 
  15100.                                     specified RepositoryId. 
  15101.  
  15102.       lookup_modifier               Returns the string value held by a SOM or 
  15103.                                     user-defined modifier, given the name and 
  15104.                                     type of the modifier, and the name of the 
  15105.                                     object that contains the modifier. 
  15106.  
  15107.       release_cache                 Releases, from the internal object cache, 
  15108.                                     the storage used by all currently 
  15109.                                     unreferenced Interface Repository objects. 
  15110.  
  15111.  
  15112. ΓòÉΓòÉΓòÉ 8.4.2. Accessing objects in the Interface Repository ΓòÉΓòÉΓòÉ
  15113.  
  15114. As mentioned above, one instance of the Repository class exists for the entire 
  15115. SOM Interface Repository. This object does not, itself, reside in the Interface 
  15116. Repository (hence it does not exhibit any of the behavior defined by the 
  15117. Contained class). It is, however, a Container, and it holds all ConstantDefs, 
  15118. TypeDefs, ExceptionDefs, InterfaceDefs, and ModuleDefs that are global in scope 
  15119. (that is, not contained inside of any other Containers). 
  15120.  
  15121. When any method provided by the Repository class is used to locate other 
  15122. objects in the Interface Repository, those objects are automatically 
  15123. instantiated and activated. Consequently, when the program is finished using an 
  15124. object from the Interface Repository, the client code should release the object 
  15125. using the somFree method. 
  15126.  
  15127. All objects contained in the Interface Repository have both a "name" and a 
  15128. "Repository ID" associated with them. The name is not guaranteed to be unique, 
  15129. but it does uniquely identify an object within the context of the object that 
  15130. contains it. The Repository ID of each object is guaranteed to uniquely 
  15131. identify that object, regardless of its context. 
  15132.  
  15133. For example, two TypeDef objects may have the same name, provided they occur in 
  15134. separate name scopes (ModuleDefs or InterfaceDefs). In this case, asking the 
  15135. Interface Repository to locate the TypeDef object based on its name would 
  15136. result in both TypeDef objects being returned. On the other hand, if the name 
  15137. is looked up from a particular ModuleDef or InterfaceDef object, only the 
  15138. TypeDef object within the scope of that ModuleDef or InterfaceDef would be 
  15139. returned. By contrast, once the Repository ID of an object is known, that 
  15140. object can always be directly obtained from the Repository object via its 
  15141. Repository ID. 
  15142.  
  15143. C or C++ programmers can obtain an instance of the Repository class using the 
  15144. RepositoryNew macro. Programmers using other languages (and C/C++ programmers 
  15145. without static linkage to the Repository class) should invoke the method 
  15146. somGetInterfaceRepository on the SOMClassMgrObject. For example, 
  15147.  
  15148. For C or C++ (static linkage): 
  15149.  
  15150. #include <repostry.h>
  15151. Repository repo;
  15152.  
  15153. repo = RepositoryNew();
  15154.  
  15155. From other languages (and for dynamic linkage in C/C++): 
  15156.  
  15157.    1. Use the somEnvironmentNew function to obtain a pointer to the 
  15158.       SOMClassMgrObject, as described in Chapter 3, "Using SOM Classes." 
  15159.  
  15160.    2. Use the somResolve or somResolveByName function to obtain a pointer to 
  15161.       the somGetInterfaceRepository method procedure. 
  15162.  
  15163.    3. Invoke the method procedure on the SOMClassMgrObject, with no additional 
  15164.       arguments, to obtain a pointer to the Repository object. 
  15165.  
  15166.  After obtaining a pointer to the Repository object, use the methods it 
  15167.  inherits from Container or its own lookup_id method to instantiate objects in 
  15168.  the Interface Repository. As an example, the contents method shown in the C 
  15169.  fragment below activates every object with global scope in the Interface 
  15170.  Repository and returns a sequence containing a pointer to every global object: 
  15171.  
  15172.   #include <containd.h>      /* Behavior common to all
  15173.   IR objects */
  15174.   Environment *ev;
  15175.   int i;
  15176.   sequence(Contained) everyGlobalObject;
  15177.  
  15178.   ev = SOM_CreateLocalEnvironment(); /* Get an environment to use */
  15179.   printf ("Every global object in the Interface Repository:\n");
  15180.  
  15181.   everyGlobalObject = Container_contents (repo, ev, "all", TRUE);
  15182.  
  15183.   for (i=0; i < everyGlobalObject._length; i++) {
  15184.       Contained aContained;
  15185.  
  15186.       aContained = (Contained) everyGlobalObject._buffer[i];
  15187.       printf ("Name: %s, Id: %s\n",
  15188.           Contained__get_name (aContained, ev),
  15189.           Contained__get_id (aContained, ev));
  15190.       SOMObject_somFree (aContained);
  15191.   }
  15192.  
  15193.  Taking this example one step further, here is a complete program that accesses 
  15194.  every object in the entire Interface Repository. It, too, uses the contents 
  15195.  method, but this time recursively calls the contents method until every object 
  15196.  in every container has been found: 
  15197.  
  15198.   #include <stdio.h>
  15199.   #include <containd.h>
  15200.   #include <repostry.h>
  15201.  
  15202.   void showContainer (Container c, int *next);
  15203.  
  15204.   main ()
  15205.   {
  15206.       int count = 0;
  15207.       Repository repo;
  15208.  
  15209.       repo = RepositoryNew ();
  15210.       printf ("Every object in the Interface Repository:\n\n");
  15211.       showContainer ((Container) repo, &count);
  15212.       SOMObject_somFree (repo);
  15213.       printf ("%d objects found\n", count);
  15214.       exit (0);
  15215.   }
  15216.  
  15217.   void showContainer (Container c, int *next)
  15218.   {
  15219.       Environment *ev;
  15220.       int i;
  15221.       sequence(Contained) everyObject;
  15222.  
  15223.       ev = SOM_CreateLocalEnvironment (); /* Get an environment */
  15224.       everyObject = Container_contents (c, ev, "all", TRUE);
  15225.  
  15226.       for (i=0; i<everyObject._length; i++) {
  15227.           Contained aContained;
  15228.  
  15229.           (*next)++;
  15230.           aContained = (Contained) everyObject._buffer[i];
  15231.           printf ("%6d. Type: %-12s id: %s\n", *next,
  15232.               SOMObject_somGetClassName (aContained),
  15233.               Contained__get_id (aContained, ev));
  15234.           if (SOMObject_somIsA (aContained, _Container))
  15235.               showContainer ((Container) aContained, next);
  15236.           SOMObject_somFree (aContained);
  15237.       }
  15238.   }
  15239.  
  15240.  Once an object has been retrieved, the methods and attributes appropriate for 
  15241.  that particular object can then be used to access the information contained in 
  15242.  the object. The methods supported by each class of object in the Interface 
  15243.  Repository, as well as the classes themselves, are documented in the SOM 
  15244.  Programming Reference. 
  15245.  
  15246.  
  15247. ΓòÉΓòÉΓòÉ 8.4.3. A word about memory management ΓòÉΓòÉΓòÉ
  15248.  
  15249. Several conventions are built into the SOM Interface Repository with regard to 
  15250. memory management. You will need to understand these conventions to know when 
  15251. it is safe and appropriate to free memory references and also when it is your 
  15252. responsibility to do so. 
  15253.  
  15254. All methods that access attributes (such as, the _get_<attribute> methods) 
  15255. always return either simple values or direct references to data within the 
  15256. target object. This is necessary because these methods are heavily used and 
  15257. must be fast and efficient. Consequently, you should never free any of the 
  15258. memory references obtained through attributes. This memory will be released 
  15259. automatically when the object that contains it is freed. 
  15260.  
  15261. For all methods that give out object references (there are five: within, 
  15262. contents, lookup_name, lookup_id,  and describe_contents), when finished with 
  15263. the object, you are expected to release the object reference by invoking the 
  15264. somFree method. (This is illustrated in the sample program that accesses all 
  15265. Interface Repository objects.) Do not release the object reference until you 
  15266. have either copied or finished using all of the information obtained from the 
  15267. object. 
  15268.  
  15269. The describe methods (describe, describe_contents, and describe_interface) 
  15270. return structures and sequences that contain information. The actual structures 
  15271. returned by these methods are passed by value (and hence should only be freed 
  15272. if you have allocated the memory used to receive them). However, you may be 
  15273. required to free some of the information contained in the returned structures 
  15274. when you are finished. Consult the specific method in the SOM Programming 
  15275. Reference for more details about what to free. 
  15276.  
  15277. During execution of the describe and lookup methods, sometimes intermediate 
  15278. objects are activated automatically. These objects are kept in an internal 
  15279. cache of objects that are in use, but for which no explicit object references 
  15280. have been returned as results. Consequently, there is no way to identify or 
  15281. free these objects individually. However, whenever your program is finished 
  15282. using all of the information obtained thus far from the Interface Repository, 
  15283. invoking the release_cache method causes the Interface Repository to purge its 
  15284. internal cache of these implicitly referenced objects. This cache will 
  15285. replenish itself automatically if the need to do so subsequently arises. 
  15286.  
  15287.  
  15288. ΓòÉΓòÉΓòÉ 8.4.4. Using TypeCode pseudo-objects ΓòÉΓòÉΓòÉ
  15289.  
  15290. Much of the detailed information contained in Interface Repository objects is 
  15291. represented in the form of TypeCodes. TypeCodes are complex data structures 
  15292. whose actual representation is hidden.  A TypeCode is an architected way of 
  15293. describing in complete detail everything that is known about a particular data 
  15294. type in the IDL language, regardless of whether it is a (built-in) basic type 
  15295. or a  (user-defined) aggregate  type. 
  15296.  
  15297. Conceptually, every TypeCode contains a "kind" field (which classifies it), and 
  15298. one or more parameters that carry descriptive information appropriate for that 
  15299. particular category of TypeCode. For example, if the data type is long, its 
  15300. TypeCode would contain a "kind" field with the value tk_long. No additional 
  15301. parameters are needed to completely describe this particular data type, since 
  15302. long is a basic type in the IDL language. 
  15303.  
  15304. By contrast, if the TypeCode describes an IDL struct, its "kind" field would 
  15305. contain the value tk_struct, and it would possess the following parameters: a 
  15306. string giving the name of the struct, and two additional parameters for each 
  15307. member of the struct: a string giving the member name and another (inner) 
  15308. TypeCode representing the member's type. This example illustrates the fact that 
  15309. TypeCodes can be nested and arbitrarily complex, as appropriate to express the 
  15310. type of data they describe. Thus, a structure that has N members will have a 
  15311. TypeCode of tk_struct with 2N+1 parameters (a name and TypeCode parameter for 
  15312. each member, plus a name for the struct itself). 
  15313.  
  15314. A tk_union TypeCode representing a union with N members has 3N+2 parameters: 
  15315. the type name of the union, the switch TypeCode, and a label value, member name 
  15316. and associated TypeCode for each member. (The label values all have the same 
  15317. type as the switch, except that the default member, if present, has a label 
  15318. value of zero octet.) 
  15319.  
  15320. A tk_enum TypeCode  (which represents an enum) has  N+1 parameters: the name of 
  15321. the enum followed by a string for each enumeration identifier. A tk_string 
  15322. TypeCode has a single parameter: the maximum string length, as an integer. (A 
  15323. maximum length of zero signifies an unbounded string.) 
  15324.  
  15325. A tk_sequence TypeCode has two parameters: a TypeCode for the sequence 
  15326. elements, and the maximum size, as an integer.  (Again, zero signifies 
  15327. unbounded.) 
  15328.  
  15329. A tk_array TypeCode has two parameters: a TypeCode for the array elements, and 
  15330. the array length, as an integer. (Arrays must be bounded.) 
  15331.  
  15332. The tk_objref TypeCode represents an object reference; its parameter is a 
  15333. repository ID that identifies its interface. 
  15334.  
  15335. See the TypeCode_kind function of the Interface Repository Framework in the SOM 
  15336. Programming Reference. 
  15337.  
  15338. TypeCodes are not actually "objects" in the formal sense. TypeCodes are 
  15339. referred to in the CORBA standard as pseudo-objects and described as "opaque". 
  15340. This means that, in reality, TypeCodes are special data structures whose 
  15341. precise definition is not fully exposed. Their implementation can vary from one 
  15342. platform to another, but all implementations must exhibit a minimal set of 
  15343. architected behavior. SOM TypeCodes support the architected behavior and have 
  15344. additional capability as well (for example, they can be copied and freed). 
  15345.  
  15346. Although TypeCodes are not objects, the programming interfaces that support 
  15347. them adhere to the same conventions used for IDL method invocations in SOM. 
  15348. That is, the first argument is always a TypeCode pseudo-object, and the second 
  15349. argument is a pointer to an Environment structure. Similarly, the names of the 
  15350. TypeCode functions are constructed like SOM's C-language method-invocation 
  15351. macros (all functions that operate on TypeCodes are named 
  15352. TypeCode_<function-name>). Because of this ostensible similarity to an IDL 
  15353. class, the TypeCode programming interfaces can be conveniently defined in IDL 
  15354. as shown below. 
  15355.  
  15356. See the TypeCode_kind function of the Interface Repository Framework in the SOM 
  15357. Programming Reference. 
  15358.  
  15359. interface TypeCode {
  15360.  
  15361. enum TCKind {
  15362.     tk_null, tk_void,
  15363.     tk_short, tk_long, tk_ushort, tk_ulong,
  15364.     tk_float, tk_double, tk_boolean, tk_char,
  15365.     tk_octet, tk_any, tk_TypeCode, tk_Principal, tk_objref,
  15366.     tk_struct, tk_union, tk_enum, tk_string,
  15367.     tk_sequence, tk_array,
  15368.  
  15369.     // The remaining enumerators are SOM-unique extensions
  15370.     // to the CORBA standard.
  15371.     //
  15372.     tk_pointer, tk_self, tk_foreign
  15373. };
  15374.  
  15375. exception Bounds {};
  15376. // This exception is returned if an attempt is made
  15377. // by the parameter() operation (described below) to
  15378. // access more parameters than exist in the receiving
  15379. // TypeCode.
  15380.  
  15381. boolean equal (in TypeCode tc);
  15382. // Compares the argument with the receiver and returns TRUE
  15383. // if both TypeCodes are equivalent.  This is NOT a test for
  15384. // identity.
  15385.  
  15386. TCKind kind ();
  15387. // Returns the type of the receiver as a TCKind.
  15388.  
  15389. long param_count ();
  15390. // Returns the number of parameters that make up the
  15391. // receiving TypeCode.
  15392.  
  15393. any parameter (in long index) raises (Bounds);
  15394. // Returns the indexed parameter from the receiving TypeCode.
  15395. // Parameters are indexed from 0 to param_count()-1.
  15396. //
  15397. //  The remaining operations are SOM-unique extensions.
  15398. //
  15399.  
  15400. short alignment ();
  15401. // This operation returns the alignment required for an instance
  15402. // of the type described by the receiving TypeCode.
  15403.  
  15404. TypeCode copy (in TypeCode tc);
  15405. // This operation returns a copy of the receiving TypeCode.
  15406.  
  15407. void free (in TypeCode tc);
  15408. // This operation frees the memory associated with the
  15409. // receiving TypeCode. Subsequently, no further use can be
  15410. // made of the receiver, which, in effect, ceases to exist.
  15411.  
  15412. void print (in TypeCode tc);
  15413. // This operation writes a readable representation of the
  15414. // receiving TypeCode to stdout.  Useful for examining
  15415. // TypeCodes when debugging.
  15416.  
  15417. void setAlignment (in short align);
  15418. // This operation overrides the required alignment for an
  15419. // instance of the type described by the receiving TypeCode.
  15420.  
  15421. long size (in TypeCode tc);
  15422. // This operation returns the size of an instance of the
  15423. // type represented by the receiving TypeCode.
  15424. };
  15425.  
  15426. A detailed description of the programming interfaces for TypeCodes is given in 
  15427. the SOM Programming Reference. 
  15428.  
  15429.  
  15430. ΓòÉΓòÉΓòÉ 8.4.4.1. Providing `alignment' information ΓòÉΓòÉΓòÉ
  15431.  
  15432. In addition to the parameters in the TypeCodes that describe each type, a 
  15433. SOM-unique extension to the TypeCode functionality allows each TypeCode to 
  15434. carry alignment information as a "hidden" parameter. Use the TypeCode_alignment 
  15435. function to access the alignment value. The alignment value is a short integer 
  15436. that should evenly divide any memory address where an instance of the type will 
  15437. occur. 
  15438.  
  15439. If no alignment information is provided in your IDL source files, all TypeCodes 
  15440. carry default alignment information. The default alignment for a type is the 
  15441. natural boundary for the type, based on the natural boundary for the basic 
  15442. types of which it may be composed. This information can vary from one hardware 
  15443. platform to another. The  TypeCode will contain the default alignment 
  15444. information appropriate to the platform where it was defined. 
  15445.  
  15446. To provide alignment information for the types and instances of types in your 
  15447. IDL source file, use the "align=N" modifier, where N is your specified 
  15448. alignment. Use standard modifier syntax of the SOM Compiler to attach the 
  15449. alignment information to a particular element in the IDL source file. In the 
  15450. following example,  align=1 (that is, unaligned or no alignment) is attached to 
  15451. the struct "abc" and to one particular instance of struct "def" (the instance 
  15452. data item "y"). 
  15453.  
  15454. interface i {
  15455.     struct abc {
  15456.         long a;
  15457.         char b;
  15458.         long c;
  15459.     };
  15460.     struct def {
  15461.         char l;
  15462.         long m;
  15463.     };
  15464.  
  15465.     void foo ();
  15466.  
  15467.     implementation {
  15468.  
  15469.     //# instance data
  15470.         abc x;
  15471.         def y;
  15472.         def z;
  15473.  
  15474.     //# alignment modifiers
  15475.         abc: align=1;
  15476.         y: align=1;
  15477.     };
  15478. };
  15479.  
  15480. Be aware that assigning the required alignment information to a type does not 
  15481. guarantee that instances of that type will actually be aligned as indicated. To 
  15482. ensure that, you must find a way to instruct your compiler to provide the 
  15483. desired alignment. In practice, this can be difficult except in simple cases. 
  15484. Most compilers can be instructed to treat all data as aligned (that is, default 
  15485. alignment) or as unaligned, by using a compile-time option or #pragma. The more 
  15486. important consideration is to make certain that the TypeCodes going into the 
  15487. Interface Repository actually reflect the alignment that your compiler 
  15488. provides. This way, when programs (such as the DSOM Framework) need to 
  15489. interpret the layout of data during their execution, they will be able to 
  15490. accurately map your data structures. This happens automatically when using the 
  15491. normal default alignment. 
  15492.  
  15493. If you wish to use unaligned instance data when implementing a class, place an 
  15494. "unattached" align=1 modifier in the implementation section. An unattached 
  15495. align=N modifier is presumed to pertain to the class's instance data structure, 
  15496. and will by implication be attached to all of the instance data items. 
  15497.  
  15498. When designing your own public types, be aware that the best practice of all 
  15499. (and the one that offers the best opportunity for language neutrality) is to 
  15500. lay out your types carefully so that it will make no difference whether they 
  15501. are compiled as aligned or unaligned! 
  15502.  
  15503.  
  15504. ΓòÉΓòÉΓòÉ 8.4.4.2. Using the `tk_foreign' TypeCode ΓòÉΓòÉΓòÉ
  15505.  
  15506. TypeCodes can be used to partially describe types that cannot be described in 
  15507. IDL (for example, a FILE type in C, or a specific class type in C++). The 
  15508. SOM-unique extension tk_foreign is used for this purpose. A  tk_foreign 
  15509. TypeCode contains three parameters: 
  15510.  
  15511.    1. The name of the type, 
  15512.    2. An implementation context string, and 
  15513.    3. A length. 
  15514.  
  15515.  The implementation context string can be used to carry an arbitrarily long 
  15516.  description that identifies the context where the foreign type can be used and 
  15517.  understood. If the length of the type is also known, it can be provided with 
  15518.  the length parameter. If the length is not known or is not constant, it should 
  15519.  be specified as zero. If the length is not specified, it will default to the 
  15520.  size of a pointer. A tk_foreign TypeCode  can also have alignment information 
  15521.  specified, just like any other TypeCode. 
  15522.  
  15523.  Using the following steps causes the SOM Compiler to create a foreign TypeCode 
  15524.  in the Interface Repository: 
  15525.  
  15526.    1. Define the foreign type as a typedef SOMFOREIGN in the IDL source file. 
  15527.  
  15528.    2. Use the #pragma modifier statement to supply the additional information 
  15529.       for the TypeCode as modifiers. The implementation context information is 
  15530.       supplied using the "impctx" modifier. 
  15531.  
  15532.    3. Compile the IDL file using the -u option to place the information in the 
  15533.       Interface Repository. 
  15534.  
  15535.  For example: 
  15536.  
  15537.   typedef SOMFOREIGN Point;
  15538.   #pragma modifier Point: impctx="C++ Point class",length=12,align=4;
  15539.  
  15540.  If a foreign type is used to define instance data, structs, unions, 
  15541.  attributes, or methods in an IDL source file, it is your responsibility to 
  15542.  ensure that the implementation and/or usage bindings contain an appropriate 
  15543.  definition of the type that will satisfy your compiler. You can use the 
  15544.  passthru statement in your IDL file to supply this definition. However, it is 
  15545.  not recommended that you expose foreign data in attributes, methods, or any of 
  15546.  the public types, if this can be avoided, because there is no guarantee that 
  15547.  appropriate usage binding information can be provided for all languages. If 
  15548.  you know that all users of the class will be using the same implementation 
  15549.  language that your class uses, you may be able to disregard this 
  15550.  recommendation. 
  15551.  
  15552.  
  15553. ΓòÉΓòÉΓòÉ 8.4.4.3. TypeCode constants ΓòÉΓòÉΓòÉ
  15554.  
  15555. TypeCodes are actually available in two forms: In addition to the TypeCode 
  15556. information provided by the methods of the Interface Repository, TypeCode 
  15557. constants can be generated by the SOM Compiler in your C or C++ usage bindings 
  15558. upon request. A TypeCode constant contains the same information found in the 
  15559. corresponding IR TypeCode, but has the advantage that it can be used as a 
  15560. literal in a C or C++ program anywhere a normal TypeCode would be acceptable. 
  15561.  
  15562. TypeCode constants have the form TC_< typename>, where <typename> is the name 
  15563. of a type (that is, a typedef, union, struct, or enum) that you have defined in 
  15564. an IDL source file. In addition, all IDL basic types and certain types dictated 
  15565. by the OMG CORBA standard come with pre-defined TypeCode constants (such as 
  15566. TC_long, TC_short, TC_char, and so forth). A full list of the pre-defined 
  15567. TypeCode constants can be found in the file "somtcnst.h". You must explicitly 
  15568. include this file in your source program to use the pre-defined TypeCode 
  15569. constants. 
  15570.  
  15571. Since the generation of TypeCode constants can increase the time required by 
  15572. the SOM Compiler to process your IDL files, you must explicitly request the 
  15573. production of TypeCode constants if you need them. To do so, use the 
  15574. "tcconsts" modifier with the -m option of the sc or somc command. For example, 
  15575. the command 
  15576.  
  15577. sc -sh -mtcconsts myclass.idl
  15578.  
  15579. will cause the SOM Compiler to generate a "myclass.h" file that contains 
  15580. TypeCode constants for the types defined in "myclass.idl". 
  15581.  
  15582.  
  15583. ΓòÉΓòÉΓòÉ 8.4.4.4. Using the IDL basic type `any' ΓòÉΓòÉΓòÉ
  15584.  
  15585. Some Interface Repository methods and TypeCode functions return information 
  15586. typed as the IDL basic type any. Usually this is done when a wide variety of 
  15587. different types of data may need to be returned through a common interface. The 
  15588. type any actually consists of a structure with two fields: a _type field and a 
  15589. _value field. The _value field is a pointer to the actual datum that was 
  15590. returned, while the _type field holds a TypeCode that describes the datum. 
  15591.  
  15592. In many cases, the context in which an operation occurs makes the type of the 
  15593. datum apparent. If so, there is no need to examine the TypeCode unless it is 
  15594. simply as a consistency check. For example, when accessing the first parameter 
  15595. of a tk_struct TypeCode, the type of the result will always be the name of the 
  15596. structure (a string). Because this is known ahead of time, there is no need to 
  15597. examine the returned TypeCode in the any_type field to verify that it is a 
  15598. tk_string TypeCode. You can just rely on the fact that it is a string; or, you 
  15599. can check the TypeCode in the _type field to verify it, if you so choose. 
  15600.  
  15601. An IDL any type can be used in an interface as a way of bypassing the strong 
  15602. type checking that occurs in languages like ANSI C and C++. Your compiler can 
  15603. only check that the interface returns the any structure; it has no way of 
  15604. knowing what type of data will be carried by the any during execution of the 
  15605. program. Consequently, in order to write C or C++ code that accesses the 
  15606. contents of the any correctly, you must always cast the _value field to reflect 
  15607. the actual type of the datum at the time of the access. 
  15608.  
  15609. Here is an example of a code fragment written in C that illustrates how the 
  15610. casting must be done to extract various values from an any: 
  15611.  
  15612. #include <som.h>    /* For "any" & "Environment" typedefs */
  15613. #include <somtc.h>  /* For TypeCode_kind prototype        */
  15614.  
  15615. any result;
  15616. Environment *ev;
  15617.  
  15618. printf ("result._value = ");
  15619. switch (TypeCode_kind (result._type, ev)) {
  15620.  
  15621.     case tk_string:
  15622.         printf ("%s\n", *((string *) result._value));
  15623.         break;
  15624.  
  15625.     case tk_long:
  15626.         printf ("%ld\n", *((long *) result._value));
  15627.         break;
  15628.  
  15629.     case tk_boolean:
  15630.         printf ("%d\n", *((boolean *) result._value));
  15631.         break;
  15632.  
  15633.     case tk_float:
  15634.         printf ("%f\n", *((float *) result._value));
  15635.         break;
  15636.  
  15637.     case tk_double:
  15638.         printf ("%f\n", *((double *) result._value));
  15639.         break;
  15640.  
  15641.     default:
  15642.         printf ("something else!\n");
  15643. }
  15644.  
  15645. Note: Of course, an any has no restriction, per se, on the type of datum that 
  15646. it can carry. Frequently, however, methods that return an any or that accept an 
  15647. any as an argument do place semantic restrictions on the actual type of data 
  15648. they can accept or return. Always consult the reference page for a method that 
  15649. uses an any to determine whether it limits the range of types that may be 
  15650. acceptable. 
  15651.  
  15652.  
  15653. ΓòÉΓòÉΓòÉ 9. The Metaclass Framework ΓòÉΓòÉΓòÉ
  15654.  
  15655. In SOM, classes are objects; metaclasses are classes and thus are objects, too. 
  15656. Also depicted are the three primitive class objects of the SOM run time: 
  15657. SOMClass, SOMobject, and SOMClassMgr. 
  15658.  
  15659.  
  15660. Primitive objects of the SOM run time
  15661.  
  15662. The important point to be aware of here is that any class that is a subclass of 
  15663. SOMClass is a metaclass This chapter describes metaclasses that are available 
  15664. in SOMobjects Toolkit. There are two kinds of metaclasses: 
  15665.  
  15666. Framework metaclasses-metaclasses for building new metaclasses and Utility 
  15667. metaclasses - metaclasses to help you write applications 
  15668.  
  15669. Briefly, the SOMobjects Toolkit provides the following metaclasses of each 
  15670. category for use by programmers: 
  15671.  
  15672.      Framework metaclasses: 
  15673.  
  15674.     SOMMBeforeAfter Used to create a metaclass that has "before" and "after" 
  15675.            methods for all methods (inherited or introduced) invoked on 
  15676.            instances of its classes. 
  15677.  
  15678.      Utility metaclasses: 
  15679.  
  15680.     SOMMSingleInstance Used to create a class that may have at most one 
  15681.            instance. 
  15682.  
  15683.     SOMMTraced Provides tracing for every invocation of all methods on 
  15684.            instances of its classes. 
  15685.  
  15686.  The following sections describe each metaclass more fully. 
  15687.  
  15688.  
  15689.   Class organization of the Metaclass Framework.
  15690.  
  15691.  
  15692. ΓòÉΓòÉΓòÉ 9.1. A note about metaclass programming ΓòÉΓòÉΓòÉ
  15693.  
  15694. SOM metaclasses are carefully constructed so that they compose (see Section 8.1 
  15695. below). If you need to create a metaclass, you can introduce new class methods, 
  15696. and new class variables, but you should not override any of the methods 
  15697. introduced by SOMClass. If you need more than this, request access to the 
  15698. experimental Cooperative metaclass used to implement the Metaclass Framework 
  15699. metaclasses described in this chapter. 
  15700.  
  15701.  
  15702. ΓòÉΓòÉΓòÉ 9.2. Framework Metaclasses for "Before/After" Behavior ΓòÉΓòÉΓòÉ
  15703.  
  15704. This section covers the following subjects: 
  15705.  
  15706.      The 'SOMMBeforeAfter' metaclass 
  15707.      Composition of before/after metaclasses 
  15708.      Notes and advantages of 'before/after' usage 
  15709.  
  15710.  
  15711. ΓòÉΓòÉΓòÉ 9.2.1. The 'SOMMBeforeAfter' metaclass ΓòÉΓòÉΓòÉ
  15712.  
  15713. SOMMBeforeAfter is a metaclass that allows the user to create a class for which 
  15714. a particular method is invoked before each invocation of every method,and for 
  15715. which a second method is invoked after each invocation. SOMMBeforeAfter defines 
  15716. two methods: sommBeforeMethod and sommAfterMethod.  These two methods are 
  15717. intended to be overridden in the child of SOMMBeforeAfter to define the 
  15718. particular "before" and "after" methods needed for the client application. 
  15719.  
  15720. For example, suppose a "Barking" metaclass (a subclass of SOMMBeforeAfter 
  15721. overrides the sommBeforeMethod and sommAfterMethod with a method that emits one 
  15722. bark when invoked. Thus, one can create the "BarkingDog" class, whose instances 
  15723. (such as "Lassie") bark twice when "disturbed" by a method invocation. 
  15724.  
  15725.  
  15726. A hierarchy of metaclasses
  15727.  
  15728. The SOMMBeforeAfter metaclass is designed to be subclassed; a subclass (or 
  15729. child) of SOMMBeforeAfter is also a metaclass. The subclass overrides 
  15730. sommBeforeMethod or sommAfterMethod or both. These (redefned) methods are 
  15731. invoked before and after any method supported by instances of the subclass 
  15732. (these methods are called primary methods). That is, they are invoked before 
  15733. and after methods invoked on the ordinary objects that are instances of the 
  15734. class objects that are instances of the subclass of SOMMBeforeAfter. 
  15735.  
  15736. The sommBeforeMethod returns a boolean value. This allows the "before" method 
  15737. to control whether the "after" method and the primary method get invoked. If 
  15738. sommBeforeMethod returns TRUE, normal processing occurs. If FALSE is returned, 
  15739. neither the primary method nor the corresponding sommAfterMethod is invoked. In 
  15740. addition, no more deeply nested before/after methods are invoked (see 
  15741. "Composition of before/after metaclasses" below). This facility can be used, 
  15742. for example, to allow a before/after metaclass to provide secure access to an 
  15743. object. The implication of this convention is that, if sommBeforeMethod is 
  15744. going to return FALSE, it must do any post-processing that might otherwise be 
  15745. done in the "after" method. 
  15746.  
  15747. Caution: somInit and somFree are among the methods that get before/after 
  15748. behavior. This implies the following two obligations are imposed on the 
  15749. programmer of a SOMMBeforeAfter class. First, the implementation must guard 
  15750. against sommBeforeMethod being called before somInit has executed, and the 
  15751. object is not yet fully initialized. Second, the implementation must guard 
  15752. against sommAfterMethod being called after somFree, at which time the object no 
  15753. longer exists (see the example "C implementation for 'Barking' metaclass" 
  15754. below). 
  15755.  
  15756. The following example shows the IDL needed to create a Barking metaclass. Just 
  15757. run the appropriate emitter to get an implementation binding, and then provide 
  15758. the appropriate "before" behavior and "after" behavior. 
  15759.  
  15760. SOM IDL for 'Barking' metaclass 
  15761.  
  15762. #ifndef Barking_idl
  15763. #define Barking_idl
  15764.  
  15765. #include <sombacls.idl>
  15766. interface  Barking : SOMMBeforeAfter
  15767. {
  15768. #ifdef __SOMIDL__
  15769. implementation
  15770. {
  15771.   //# Class Modifiers
  15772.   filestem = barking;
  15773.   callstyle = idl;
  15774.  
  15775.   //# Method Modifiers
  15776.   sommBeforeMethod : override;
  15777.   sommAfterMethod : override;
  15778. };
  15779. #endif /* __SOMIDL__ */
  15780. };
  15781. #endif  /* Barking_idl */
  15782.  
  15783. The next example shows an implementation of the Barking metaclass in which no 
  15784. barking occurs when somFree is invoked. 
  15785.  
  15786. C implementation for 'Barking' metaclass 
  15787.  
  15788. #define Barking_Class_Source
  15789. #include <barking.ih>
  15790.  
  15791. static char *somMN_somFree = "somFree";
  15792. static somId somId_somFree = &somMN_somFree;
  15793.  
  15794. SOM_Scope boolean  SOMLINK sommBeforeMethod(Barking somSelf,
  15795.                                             Environment *ev,
  15796.                                             SOMObject object,
  15797.                                             somId methodId,
  15798.                                             va_list ap)
  15799. {
  15800.     if ( !somCompareIds( methodId, somId_somFree )
  15801.        printf( "WOOF" );
  15802. }
  15803.  
  15804. SOM_Scope void  SOMLINK sommAfterMethod(Barking somSelf,
  15805.                                         Environment *ev,
  15806.                                         SOMObject object,
  15807.                                         somId methodId,
  15808.                                         somId descriptor,
  15809.                                         somToken returnedvalue,
  15810.                                         va_list ap)
  15811. {
  15812.     if ( !somCompareIds( methodId, somId_somFree )
  15813.        printf( "WOOF" );
  15814. }
  15815.  
  15816.  
  15817. ΓòÉΓòÉΓòÉ 9.2.2. Composition of before/after metaclasses ΓòÉΓòÉΓòÉ
  15818.  
  15819. When there are two before/after metaclasses -"Barking" (as before) and 
  15820. "Fierce", which has a sommBeforeMethod and sommAfterMethod that both growl 
  15821. (that is, both methods make a "grrrr" sound when executed). The preceding 
  15822. discussion demonstrated how to create a "FierceDog " or a "BarkingDog ", but 
  15823. has not yet addressed the question of how to compose these properties of fierce 
  15824. and barking. Composability means having the ability to easily create either a 
  15825. "FierceBarkingDog" that goes "grrr woof woof grrr " when it responds to a 
  15826. method call or a "BarkingFierceDog " that goes "woof grrr grrr woof" when it 
  15827. responds to a method call. 
  15828.  
  15829.  
  15830. Example for composition of before or after metaclasses.
  15831.  
  15832. There are several ways to express such compositions. Figure 1 depicts SOM IDL 
  15833. fragments for three techniques in which composition can be indicated by a 
  15834. programmer. These are denoted as Technique 1, Technique 2, and Technique 3, 
  15835. each of which creates a "FierceBarkingDog" class, named "FB-1", "FB-2", and 
  15836. "FB-3", respectively, as follows: 
  15837.  
  15838.      In Technique 1, a new metaclass ("FierceBarking") is created with both 
  15839.       the "Fierce" and "Barking" metaclasses as parents. An instance of this 
  15840.       new metaclass (that is, "FB-1") is a "FierceBarkingDog" (assuming "Dog " 
  15841.       is a parent). 
  15842.  
  15843.      In Technique 2, a new class is created which has parents that are 
  15844.       instances of "Fierce" and "Barking" respectively. That is, "FB-2" is a 
  15845.       "FierceBarkingDog" also (assuming "FierceDog" and "BarkingDog" do not 
  15846.       further specialize "Dog"). 
  15847.  
  15848.      In Technique 3, "FB-3", which also is a "FierceBarkingDog", is created by 
  15849.       declaring that its parent is a "BarkingDog" and that its explicit 
  15850.       (syntactically declared) metaclass is "Fierce". 
  15851.  
  15852.   ΓöîΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÉ
  15853.   Γöé TECHNIQUE 1       Γöé TECHNIQUE 2        Γöé TECHNIQUE 3       Γöé
  15854.   Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  15855.   Γöé interface        Γöé interface         Γöé interface        Γöé
  15856.   Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  15857.   Γöé FB-1:Dog         Γöé FB-2:FierceDog,      Γöé FB-3:BarkingDog     Γöé
  15858.   Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  15859.   Γöé {            Γöé BarkingDog        Γöé {            Γöé
  15860.   Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  15861.   Γöé ...           Γöé {             Γöé ...           Γöé
  15862.   Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  15863.   Γöé implementation      Γöé ...            Γöé implemetation      Γöé
  15864.   Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  15865.   Γöé {            Γöé Implementation      Γöé {            Γöé
  15866.   Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  15867.   Γöé metaclass=FierceBarking;Γöé {             Γöé metaclass=Fierce;    Γöé
  15868.   Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  15869.   Γöé ...           Γöé   ...          Γöé   ...          Γöé
  15870.   Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  15871.   Γöé  };           Γöé  };            Γöé  };           Γöé
  15872.   Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  15873.   Γöé };            Γöé };            Γöé };            Γöé
  15874.   ΓööΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÿ
  15875.  
  15876.  Figure 1.Three techniques for composing before/after metaclasses. 
  15877.  
  15878.  Note that the explicit metaclass in the SOM IDL of "FB-1" is its derived 
  15879.  class, "FierceBarking". The derived metaclass of "FB-2" is also 
  15880.  "FierceBarking". Lastly, the derived metaclass of "FB-3" is  not  the 
  15881.  metaclass explicitly specified in the SOM IDL; rather, it  too is 
  15882.  "FierceBarking." 
  15883.  
  15884.  
  15885. ΓòÉΓòÉΓòÉ 9.2.3. Notes and advantages of 'before/after' usage ΓòÉΓòÉΓòÉ
  15886.  
  15887. Notes on the dispatching of before/after methods: 
  15888.  
  15889.      A before (after) method is invoked just once per primary method 
  15890.       invocation. 
  15891.  
  15892.      The dispatching of before/after methods is thread-safe. 
  15893.  
  15894.      The dispatching of before/after methods is fast. The time overhead for 
  15895.       dispatching a primary method is on the order of N times the time to 
  15896.       invoke a before/after method as a procedure, where N is the total number 
  15897.       of before/after methods to be applied. 
  15898.  
  15899.  In conclusion, consider an example that clearly demonstrates the power of the 
  15900.  composition of before/after metaclasses. Suppose you are creating a class 
  15901.  library that will have n classes. Further suppose there are p properties that 
  15902.  must be included in all combinations for all classes. Potentially, the library 
  15903.  must have n2p classes. Let us hypothesize that (fortunately) all these 
  15904.  properties can be captured by before/after metaclasses. In this case, the size 
  15905.  of the library is n+p. 
  15906.  
  15907.  The user of such a library need only produce those combinations necessary for 
  15908.  a given application. In addition, note that there is none of the usual 
  15909.  programming. Given the IDL for a combination of before/after metaclasses, the 
  15910.  SOM compiler generates the implementation of the combination (in either C or 
  15911.  C++) with no further manual intervention. 
  15912.  
  15913.  
  15914. ΓòÉΓòÉΓòÉ 9.3. The 'SOMMSingleInstance' Metaclass ΓòÉΓòÉΓòÉ
  15915.  
  15916. Sometimes it is necessary to define a class for which only one instance can be 
  15917. created. This is easily accomplished with the SOMMSingleInstance metaclass. 
  15918. Suppose the class "Collie" is an instance of SOMMSingleInstance. The first call 
  15919. to CollieNew creates the one possible instance of "Collie"; hence, subsequent 
  15920. calls to CollieNew return the first (and only) instance. 
  15921.  
  15922. Any class whose metaclass is SOMMSingleInstance gets this requisite behavior; 
  15923. nothing further needs to be done. The first instance created is always returned 
  15924. by the <className>New macro. 
  15925.  
  15926. Alternatively, the method sommGetSingleInstance does the same thing as the 
  15927. <className>New macro. This method invoked on a class object (for example, 
  15928. "Collie") is useful because the call site explicitly shows that something 
  15929. special is occurring and that a new object is not necessarily being created. 
  15930. For this reason, one might prefer the second form of creating a single-instance 
  15931. object to the first. 
  15932.  
  15933. Instances of SOMMSingleInstance keep a count of the number of times somNew and 
  15934. sommGetSingleInstance are invoked. Each invocation of somFree decrements this 
  15935. count. An invocation of somFree does not actually free the single instance 
  15936. until the count reaches zero. 
  15937.  
  15938. SOMMSingleInstance overrides somRenew, somRenewNoInit, somRenewNoInitNoZero, 
  15939. and somRenewNoZero so that a proxy is created in the space indicated in the 
  15940. somRenew* call. This proxy redispatches all methods to the single instance, 
  15941. which is always allocated in heap storage. Note that all of these methods 
  15942. (somRenew*) increment the reference count; therefore, somFree should be called 
  15943. on these objects, too. In this case, somFree decrements the reference and frees 
  15944. the single instance (and, of course, takes no action with respect to the 
  15945. storage indicated in the original somRenew* call). 
  15946.  
  15947. If a class is an instance of SOMMSingleInstance, all of its subclasse are also 
  15948. instances of SOMMSingleInstance. Be aware that this also means that each 
  15949. subclass is allowed to have only a single instance. (This may seem obvious. 
  15950. However, it is a common mistake to create a framework class that must have a 
  15951. single instance, while at the same time expecting users of the framework to 
  15952. subclass the single instance class. The result is that two single-instance 
  15953. objects are created: one for the framework class and one for the subclass. One 
  15954. technique that can mitigate this scenario is based on the use of 
  15955. somSubstituteClass. In this case, the creator of the subclass must substitute 
  15956. the subclass for the framework class - before the instance of the framework 
  15957. class is created.) 
  15958.  
  15959.  
  15960. ΓòÉΓòÉΓòÉ 9.4. The 'SOMMTraced' Metaclass ΓòÉΓòÉΓòÉ
  15961.  
  15962. SOMMTraced is a metaclass that facilitates tracing of method invocations. If 
  15963. class "Collie" is an instance of SOMMTraced (if SOMMTraced is the metaclass of 
  15964. "Collie"), any method invoked on an instance of "Collie" is traced. That is, 
  15965. before the method begins execution, a message prints (to standard output) 
  15966. giving the actual parameters. Then, after the method completes execution, a 
  15967. second message prints giving the returned value. This behavior is attained 
  15968. merely by being an instance of the SOMMTraced metaclass. 
  15969.  
  15970. If the class being traced is contained in the Interface Repository, actual 
  15971. parameters are printed as part of the trace. If the class is not contained in 
  15972. the Interface Repository, an ellipsis is printed. 
  15973.  
  15974. To be more concrete, suppose that the class "Collie" is a child of "Dog" and is 
  15975. an instance of SOMMTraced. Because SOMMTraced is the metaclass of "Collie," any 
  15976. method invoked on "Lassie" (an instance of "Collie") is traced. 
  15977.  
  15978. It is easy to use SOMMTraced: Just make a class an instance of SOMMTraced in 
  15979. order to get tracing. 
  15980.  
  15981. There is one more step for using SOMMTraced: Nothing prints unless the 
  15982. environment variable SOMM_TRACED is set. If it is set to the empty string, all 
  15983. traced classes print. If SOMM_TRACED is not the empty string, it should be set 
  15984. to the list of names of classes that should be traced. For example, the 
  15985. following command turns on printing of the trace for "Collie", but not for any 
  15986. other traced class: 
  15987.  
  15988. SET     SOMM_TRACED=Collie
  15989.  
  15990. The example below shows the IDL needed to create a traced dog class: Just run 
  15991. the appropriate emitter to get an implementation binding. 
  15992.  
  15993. SOM IDL for 'TracedDog' class 
  15994.  
  15995. #include "dog.idl"
  15996. #include <somtrcls.idl>
  15997. interface TracedDog : Dog
  15998. {
  15999. #ifdef __SOMIDL__
  16000. implementation
  16001. {
  16002.   //# Class Modifiers
  16003.   filestem = trdog;
  16004.   metaclass = SOMMTraced;
  16005. };
  16006. #endif /* __SOMIDL__ */
  16007. };
  16008.  
  16009.  
  16010. ΓòÉΓòÉΓòÉ 9.5. Error Codes ΓòÉΓòÉΓòÉ
  16011.  
  16012. It is possible to receive the following messages from the Metaclass Framework 
  16013. while an application is running. 
  16014.  
  16015.  60001     An attempt was made to construct a class with SOMMSingleInstance as 
  16016.            a metaclass constraint. (This may occur indirectly because of the 
  16017.            construction of a derived metaclass). The initialization of the 
  16018.            class failed because somInitMIClass defined by SOMMSingleInstance is 
  16019.            in conflict with another metaclass that has overridden somNew. That 
  16020.            is, some other metaclass has already claimed the right to return the 
  16021.            value for somNew. 
  16022.  
  16023.  60002     An attempt was made to construct a class with SOMMSingleInstance as 
  16024.            a metaclass constraint. (This may occur indirectly because of the 
  16025.            construction of a derived metaclass). The initialization of the 
  16026.            class failed because somInitMIClass defined by SOMMSingleInstance is 
  16027.            in conflict with another metaclass that has overridden somFree. That 
  16028.            is, some other metaclass has already claimed this right to override 
  16029.            somFree. 
  16030.  
  16031.  60004     An invocation of somrRepInit was made with a logging type other than 
  16032.            'o' or 'v'. 
  16033.  
  16034.  60005     The sommBeforeMethod or the sommAfterMethod was invoke on a 
  16035.            SOMRReplicbleObject whose logging type is other than 'o' or 'v'. 
  16036.            This error cannot occur normally. The likely cause is that some 
  16037.            method invoked on another object has overwritten this object's 
  16038.            memory. 
  16039.  
  16040.  60006     A Before/After Metaclass must override both sommBeforeMethod an 
  16041.            sommAfterMethod. This message indicates an attempt to create a 
  16042.            Before/After Metaclass where only one of the above methods is 
  16043.            overridden. 
  16044.  
  16045.  
  16046. ΓòÉΓòÉΓòÉ 10. The Event Management Framework ΓòÉΓòÉΓòÉ
  16047.  
  16048. The Event Management Framework is a central facility for registering all events 
  16049. of an application. Such a registration facilitates grouping of various 
  16050. application events and waiting on multiple events in a single event-processing 
  16051. loop. This facility is used by the Replication Framework and by DSOM to wait on 
  16052. their respective events of interest. The Event Management Framework must also 
  16053. be used by any interactive application that contains DSOM or replicated 
  16054. objects. 
  16055.  
  16056.  
  16057. ΓòÉΓòÉΓòÉ 10.1. Event Management Basics ΓòÉΓòÉΓòÉ
  16058.  
  16059. The Event Management Framework consists of an Event Manager (EMan) class, a 
  16060. Registration Data class and several Event classes. It provides a way to 
  16061. organize various application events into groups and to process all events in a 
  16062. single event-processing loop. The need for this kind of facility is seen very 
  16063. clearly in interactive applications that also need to process some background 
  16064. events (say, messages arriving from a remote process). Such applications must 
  16065. maintain contact with the user while responding to events coming from other 
  16066. sources. 
  16067.  
  16068. One solution in a multi-threaded environment is to have a different thread 
  16069. service each different source of events. For a single-threaded environment it 
  16070. should be possible to recognize and process all events of interest in a single 
  16071. main loop. EMan offers precisely this capability. EMan can be useful even when 
  16072. multiple threads are available, because of its simple programming model. It 
  16073. avoids contention for common data objects between EMan event processing and 
  16074. other main-loop processing activity. 
  16075.  
  16076.  
  16077. ΓòÉΓòÉΓòÉ 10.1.1. Model of EMan usage ΓòÉΓòÉΓòÉ
  16078.  
  16079. The programming model of EMan is similar to that of many GUI toolkits. The main 
  16080. program initializes EMan and then registers interest in various types of 
  16081. events. The main program ends by calling a non-returning function of EMan that 
  16082. waits for events and dispatches them as and when they occur. In short, the 
  16083. model includes steps that: 
  16084.  
  16085.    1. Initialize the Event Manager, 
  16086.    2. Register with EMan for all events of interest, and 
  16087.    3. Hand over control to EMan to loop forever and to dispatch events. 
  16088.  
  16089.  The Event Manager is a SOM object and is an instance of the SOMEEMan class. 
  16090.  Since any application requires only one instance of this object, the SOMEEMan 
  16091.  class is an instance of the SOMMSingleInstance class. Creation and 
  16092.  initialization of the Event Manager is accomplished by a function call to 
  16093.  SOMEEmanNew. 
  16094.  
  16095.  Currently, EMan supports the four kinds of events described in the following 
  16096.  topic. An application can register or unregister for events in a callback 
  16097.  routine (explained below) even after control has been turned over to EMan. 
  16098.  
  16099.  
  16100. ΓòÉΓòÉΓòÉ 10.1.2. Event types ΓòÉΓòÉΓòÉ
  16101.  
  16102. Event types are categorized as follows: 
  16103.  
  16104.      Timer events 
  16105.  
  16106.       These can be either one-time timers or interval timers. 
  16107.  
  16108.      Sink events (sockets, file descriptors, and message queues) 
  16109.  
  16110.       Sink events are not supported in Windows NT and Windows 95. 
  16111.  
  16112.      Client events (any event that the application wants to queue with EMan) 
  16113.  
  16114.       These events are defined, created, processed, and destroyed by the 
  16115.       application. EMan simply acts as a place to queue these events for 
  16116.       processing. EMan dispatches these client events whenever it sees them. 
  16117.       Typically, this happens immediately after the event is queued. 
  16118.  
  16119.      Work procedure events (procedures that can be called when there is no 
  16120.       other event) 
  16121.  
  16122.       These are typically background procedures that the application intends to 
  16123.       execute when there are spare processor cycles. When there are no other 
  16124.       events to process, EMan calls all registered work procedures. A work 
  16125.       procedure event is called only after all other higher priority events 
  16126.       have been called. A work procedure event is not called if there are no 
  16127.       other events to be processed. 
  16128.  
  16129.  The Event Management Framework is extendible (that is, other event types can 
  16130.  be added to it) through subclassing. The event types currently supported by 
  16131.  EMan are at a sufficiently low level so as to enable building other higher 
  16132.  level application events on top of them. For example, you can build an X-event 
  16133.  handler by simply registering the file descriptor for the X connection with 
  16134.  EMan and getting notified when any X-event occurs. 
  16135.  
  16136.  
  16137. ΓòÉΓòÉΓòÉ 10.1.3. Registration ΓòÉΓòÉΓòÉ
  16138.  
  16139. This topic illustrates how to register for an event type. 
  16140.  
  16141.  
  16142. ΓòÉΓòÉΓòÉ 10.1.3.1. Callbacks ΓòÉΓòÉΓòÉ
  16143.  
  16144. The programmer decides what processing needs to be done when an event occurs 
  16145. and then places the appropriate code either in a procedure or in a method of an 
  16146. object. This procedure or method is called a callback. (The callback is 
  16147. provided to EMan at the time of registration and is called by EMan when a 
  16148. registered event occurs.) The signature of a callback is fixed by the framework 
  16149. and must have one of the following three signatures: 
  16150.  
  16151. void SOMLINK EMRegProc(SOMEEvent, void *);
  16152. void SOMLINK EMMethodProc(SOMObject, SOMEEvent, void *);
  16153. void SOMLINK EMMethodProcEv(SOMObject, Environment *Ev,
  16154.                             SOMEEvent, void *);
  16155. /* On OS/2, they all use "system" linkage  */
  16156. /* On Windows NT/95, they all use "__stdcall" linkage. */
  16157.  
  16158. The three specified prototypes correspond to a simple callback procedure, a 
  16159. callback method using OIDL call style, and a callback method using IDL call 
  16160. style. The parameter type SOMEEvent refers to an event object passed by EMan to 
  16161. the callback.  Event objects are described below. 
  16162.  
  16163. NOTE: When the callbacks are methods, EMan calls these methods using 
  16164. Name-lookup Resolution (see Method Resolution in Chapter 5). One of the 
  16165. implications is that at the time of registration EMan queries the target 
  16166. object's class object to provide a method pointer for the method name supplied 
  16167. to it. EMan uses this pointer for making event callbacks. 
  16168.  
  16169.  
  16170. ΓòÉΓòÉΓòÉ 10.1.3.2. Event classes ΓòÉΓòÉΓòÉ
  16171.  
  16172. All event objects are instances of either the SOMEEvent class or a subclass of 
  16173. it. The hierarchy of event classes is as follows: 
  16174.  
  16175.  
  16176. SOMObject_________SOMEEvent_________ё__________SOMETimerEvent
  16177.  
  16178.                   ΓòÆ__________SOMEClientEvent
  16179.  
  16180.                   ΓòÆ__________SOMESinkEvent
  16181.  
  16182.                   ΓòÆ__________SOMEWorkProcEvent
  16183.  
  16184. When called by EMan, a callback expects the appropriate event instance as a 
  16185. parameter. For example, a callback registered for a timer event expects a 
  16186. SOMETimerEvent instance from EMan. 
  16187.  
  16188.  
  16189. ΓòÉΓòÉΓòÉ 10.1.3.3. EMan parameters ΓòÉΓòÉΓòÉ
  16190.  
  16191. Several method calls in the Event Management Framework make use of bit masks 
  16192. and constants as parameters (for example, EMSinkEvent or EMInputReadMask). 
  16193. These methods are defined in the include file "eventmsk.h". When a user plans 
  16194. to extend the Event Management Framework, care must be taken to avoid name and 
  16195. value collisions with the definitions in "eventmsk.h". For convenience, the 
  16196. contents of the "eventmsk.h" file are shown below. 
  16197.  
  16198. #ifndef H_EVENTMASKDEF
  16199. #define H_EVENTMASKDEF
  16200.  
  16201. /* Event Types */
  16202. #define EMTimerEvent                    54
  16203. #define EMSignalEvent                   55
  16204. #define EMSinkEvent                     56
  16205.  
  16206. #define EMWorkProcEvent                 57
  16207.  
  16208. #define EMClientEvent                   58
  16209.  
  16210.  
  16211. /* Sink input/output condition mask */
  16212.  
  16213. #define EMInputReadMask                 (1L<0)
  16214. #define EMInputWriteMask                (1L<1)
  16215. #define EMInputExceptMask               (1L<2)
  16216.  
  16217. /* Process Event mask */
  16218.  
  16219. #define EMProcessTimerEvent             (1L<0)
  16220. #define EMProcessSinkEvent              (1L<1)
  16221. #define EMProcessWorkProcEvent          (1L<2)
  16222. #define EMProcessClientEvent            (1L<3)
  16223. #define EMProcessAllEvents              (1L<6)
  16224.  
  16225. #endif   /* H_EVENTMASKDEF */
  16226.  
  16227.  
  16228. ΓòÉΓòÉΓòÉ 10.1.3.4. Registering for events ΓòÉΓòÉΓòÉ
  16229.  
  16230. In addition to the event classes, the Event Management Framework uses a 
  16231. registration data class (SOMEEMRegisterData) to capture all event-related 
  16232. registration information. The procedure for registering interest in an event is 
  16233. as follows: 
  16234.  
  16235.    1. Create an instance of the SOMEEMRegisterData class (this will be referred 
  16236.       to as a "RegData" object). 
  16237.  
  16238.    2. Set the event type of "RegData." 
  16239.  
  16240.    3. Set the various fields of "RegData" to supply information about the 
  16241.       particular event for which an interest is being registered. 
  16242.  
  16243.    4. Call the registration method of EMan, using "RegData" and the callback 
  16244.       method information as parameters. The callback information varies, 
  16245.       depending upon whether it is a simple procedure, a method called using 
  16246.       OIDL call style, or a method called using IDL call style. 
  16247.  
  16248.  The following code segment illustrates how to register input interest in a 
  16249.  socket "sock" and provide a callback procedure "ReadMsg". 
  16250.  
  16251.   data = SOMEEMRegisterDataNew( );       /* create a RegData object */
  16252.   _someClearRegData(data, Ev);
  16253.   _someSetRegDataEventMask(data,Ev,EMSinkEvent,NULL); /* Event type */
  16254.   _someSetRegDataSink(data, Ev, sock);     /* provide the socket id */
  16255.   _someSetRegDataSinkMask(data,Ev, EMInputReadMask );
  16256.                                                    /*input interest */
  16257.   regId = _someRegisterProc(some_gEMan,Ev,data,ReadMsg,"UserData" );
  16258.   /* some_gEMan points to EMan. The last parameter "userData" is any
  16259.      data the user wants to be passed to the callback procedure as a
  16260.      second parameter */
  16261.  
  16262.  
  16263. ΓòÉΓòÉΓòÉ 10.1.4. Unregistering for events ΓòÉΓòÉΓòÉ
  16264.  
  16265. One can unregister interest in a given event type at any time. To unregister, 
  16266. you must provide the registration id returned by EMan at the time of 
  16267. registration. Unregistering a non-existent event (such as, an invalid 
  16268. registration id) is a no-op. The following example unregisters the socket 
  16269. registered above: 
  16270.  
  16271. _someUnRegister(some_gEMan, Ev, regId);
  16272.  
  16273.  
  16274. ΓòÉΓòÉΓòÉ 10.1.5. An example callback procedure ΓòÉΓòÉΓòÉ
  16275.  
  16276. The following code segment illustrates how to write a callback procedure: 
  16277.  
  16278. void SOMLINK ReadMsg( SOMEEvent  event, void  *targetData )
  16279. {
  16280. int sock;
  16281.     printf( "Data = %s\n", targetData );
  16282.     switch( _somevGetEventType( event )) {
  16283.     case  EMSinkEvent:
  16284.         printf("callback: Perceived Sink Event\n");
  16285.         sock = _somevGetEventSink(event);
  16286.         /* code to read the message off the socket */
  16287.         break;
  16288.     default: printf("Unknown Event type in socket callback\n");
  16289.     }
  16290. }
  16291. /* On OS/2, "system" linkage is also required.  */
  16292.  
  16293.  
  16294. ΓòÉΓòÉΓòÉ 10.1.6. Generating client events ΓòÉΓòÉΓòÉ
  16295.  
  16296. While the other events are caused by the operating system (for example, Timer), 
  16297. by I/O devices, or by external processes, client events are caused by the 
  16298. application itself. The application creates these events and enqueues them with 
  16299. EMan. When client events are dispatched, they are processed in a callback 
  16300. routine just like any other event. The following code segment illustrates how 
  16301. to create and enqueue client events. 
  16302.  
  16303. clientEvent1 = SOMEClientEventNew();  /* create a client event */
  16304. _somevSetEventClientType( clientEvent1, Ev, "MyClientType" );
  16305. _somevSetEventClientData( clientEvent1, Ev,
  16306.                                    "I can give any data here");
  16307. /* assuming that "MyClientType" is already registered with EMan */
  16308. /* enqueue the above event with EMan */
  16309. _someQueueEvent(some_gEMan, Ev, clientEvent1);
  16310.  
  16311.  
  16312. ΓòÉΓòÉΓòÉ 10.1.7. Examples of using other events ΓòÉΓòÉΓòÉ
  16313.  
  16314. The sample program shipped with the Event Management Framework illustrates the 
  16315. tasks listed below. (Due to its large size, the source code is not included 
  16316. here.) 
  16317.  
  16318.      Registering and unregistering for Timer events. 
  16319.  
  16320.      Registering and unregistering for Workproc events. 
  16321.  
  16322.     
  16323.  
  16324.      Registering and unregistering Client events. 
  16325.  
  16326.     
  16327.  
  16328.  
  16329. ΓòÉΓòÉΓòÉ 10.1.8. Processing events ΓòÉΓòÉΓòÉ
  16330.  
  16331. After all registrations are finished, an application typically turns over 
  16332. control to EMan and is completely event driven thereafter. Typically, an 
  16333. application main program ends with the following call to EMan: 
  16334.  
  16335. _someProcessEvents(some_gEMan, Ev);
  16336.  
  16337. An equivalent way to process events is to write a main loop and call 
  16338. someProcessEvent from inside the main loop, as indicated: 
  16339.  
  16340. while (1) { /* do forever */
  16341.       _someProcessEvent( some_gEMan, Ev, EMProcessTimerEvent  Γöé
  16342.                                          EMProcessSinkEvent   Γöé
  16343.                                          EMProcessClientEvent Γöé
  16344.                                          EMProcessWorkProcEvent );
  16345.       /***  Do other main loop work, as needed. ***/
  16346. }
  16347.  
  16348. The second way allows more precise control over what type of events to process 
  16349. in each call. The example above enables all four types to be processed. The 
  16350. required subset is formed by logically OR'ing the appropriate bit constants 
  16351. (these are defined in "eventmsk.h)".  Another difference is that the second way 
  16352. is a non-blocking call to EMan. That is, if there are no events to process, 
  16353. control returns to the main loop immediately, whereas someProcessEvents is a 
  16354. non-returning blocking call. For most applications, the first way of calling 
  16355. EMan is better, since it does not waste processor cycles when there are no 
  16356. events to process. 
  16357.  
  16358.  
  16359. ΓòÉΓòÉΓòÉ 10.1.9. Interactive applications ΓòÉΓòÉΓòÉ
  16360.  
  16361. Interactive applications need special attention when coupled with EMan. Once 
  16362. control is turned over to EMan by calling someProcessEvents, a single-threaded 
  16363. application (for example, on AIX) has no way of responding to keyboard input. 
  16364. The user must register interest in "stdin" with EMan and provide a callback 
  16365. function that handles keyboard input. In a multi-threaded environment (for 
  16366. example, Windows NT), this problem can be solved by spawning a thread to 
  16367. execute someProcessEvents and another to handle keyboard input. (These two 
  16368. options are illustrated in the sample program shipped with the Event Management 
  16369. Framework.) 
  16370.  
  16371.  
  16372. ΓòÉΓòÉΓòÉ 10.2. Event Manager Advanced Topics ΓòÉΓòÉΓòÉ
  16373.  
  16374. This section contains the following subjects: 
  16375.  
  16376.      Extending EMan 
  16377.      Using EMan from C++ 
  16378.      Using EMan from other languages 
  16379.      Tips on using EMan 
  16380.  
  16381.  
  16382. ΓòÉΓòÉΓòÉ 10.2.1. Extending EMan ΓòÉΓòÉΓòÉ
  16383.  
  16384. The current event manager can be extended without having access to the source 
  16385. code. Several other extensions are possible. For example, new event types can 
  16386. be defined by subclassing either directly from SOMEEvent class or from any of 
  16387. its subclasses in the framework. There are three main problems to solve in 
  16388. adding a new event type: 
  16389.  
  16390.      How to register a new event type with EMan? 
  16391.  
  16392.      How to make EMan recognize the occurrence of the new event? 
  16393.  
  16394.      How to make EMan create and send the new event object (a subclass of 
  16395.       SOMEEvent) to the callback when the event is dispatched? 
  16396.  
  16397.  Because the registration information is supplied with appropriate "set" 
  16398.  methods of a RegData object, the RegData object should be extended to include 
  16399.  additional methods.  This can be achieved by subclassing from 
  16400.  SOMEEMRegisterData and building a new registration data class that has methods 
  16401.  to "set" and "get" additional fields of information that are needed to 
  16402.  describe the new event types fully. To handle registrations with instances of 
  16403.  new registration data subclass, we must also subclass from SOMEEMan and 
  16404.  override the someRegister and the someUnRegister methods. These methods should 
  16405.  handle the information in the new fields introduced by the new registration 
  16406.  data class and call parent methods to handle the rest. 
  16407.  
  16408.  Making EMan recognize the occurrence of the new event is primarily limited by 
  16409.  the primitive events EMan can wait on. Thus the new event would have to be 
  16410.  wrapped in a primitive event that EMan can recognize. For example, to wait on 
  16411.  a message queue on Windows NT /95 concurrently with other EMan events, a 
  16412.  separate thread can be made to wait on the message queue and to enqueue a 
  16413.  client event with EMan when a message arrives on this message queue. We can 
  16414.  thus bring multiple event sources into the single EMan main loop. 
  16415.  
  16416.  The third problem of creating new event objects unknown to EMan can be easily 
  16417.  done by applying the previous technique of wrapping the new event in terms of 
  16418.  a known event. In a callback routine of the known event, we can create and 
  16419.  dispatch the new event unknown to EMan. Of course, this does introduce an 
  16420.  intermediate callback routine which would not be needed if EMan directly 
  16421.  understood the new event type. 
  16422.  
  16423.  A general way of extending EMan is to look for newly defined event types by 
  16424.  overriding someProcessEvent and someProcessEvents in a subclass of EMan. 
  16425.  
  16426.  
  16427. ΓòÉΓòÉΓòÉ 10.2.2. Using EMan from C++ ΓòÉΓòÉΓòÉ
  16428.  
  16429. The Event Management framework can be used from C++ just like any other 
  16430. framework in the SOMobjects Toolkit. You must ensure that the C++ usage 
  16431. bindings (that is, the .xh files) are available for the Event Management 
  16432. Framework classes. These .xh files are generated by the SOM Compiler in the 
  16433. SOMobjects Toolkit when the -s option includes an xh emitter. 
  16434.  
  16435.  
  16436. ΓòÉΓòÉΓòÉ 10.2.3. Using EMan from other languages ΓòÉΓòÉΓòÉ
  16437.  
  16438. The event manager and the other classes can be used from other languages, 
  16439. provided usage bindings are available for them. These usage bindings are 
  16440. produced from .idl files of the framework classes by the appropriate language 
  16441. emitter. 
  16442.  
  16443.  
  16444. ΓòÉΓòÉΓòÉ 10.2.4. Tips on using EMan ΓòÉΓòÉΓòÉ
  16445.  
  16446. The following are some do's and don'ts for EMan: 
  16447.  
  16448.      EMan callback procedures or methods must return quickly. You cannot wait 
  16449.       for long periods of time to return from the callbacks. If such long 
  16450.       delays occur, then the application may not notice some subsequent events 
  16451.       in time to process them meaningfully (for example, a timer event may not 
  16452.       be noticed until long after it occurred). 
  16453.  
  16454.      It follows from the previous tip that you should not do independent 
  16455.       "select" system calls on file descriptors while inside a callback.  (This 
  16456.       applies to sockets and message queues, as well.) In general, a callback 
  16457.       should not do any blocking of system calls. If an application must do 
  16458.       this, then it must be done with a small timeout value. 
  16459.  
  16460.      Since EMan callbacks must return quickly, no callback should wait on a 
  16461.       semaphore indefinitely. If a callback has to obtain some semaphores 
  16462.       during its processing, then the callback should try to acquire all of 
  16463.       them at the very beginning, and should be prepared to abort and return to 
  16464.       EMan if it fails to acquire the necessary semaphores. 
  16465.  
  16466.      EMan callback methods are called using name-lookup resolution. Therefore, 
  16467.       the parameters to an EMan registration call must be such that the class 
  16468.       object of the object parameter must be able to provide a pointer to the 
  16469.       method indicated by the method parameter. Although this requirement is 
  16470.       satisfied in a majority of cases, there are exceptions.  For example, if 
  16471.       the object is a proxy (in the DSOM sense) to a remote object, then the 
  16472.       "real" class object cannot provide a meaningful method pointer. Also note 
  16473.       that, when somDispatch is overridden, the effect of such an override will 
  16474.       not  apply  to the callback from EMan.  Do not use a method callback in 
  16475.       these situations; instead, use a procedure callback. 
  16476.  
  16477.  
  16478. ΓòÉΓòÉΓòÉ 10.3. Limitations ΓòÉΓòÉΓòÉ
  16479.  
  16480. The present implementation of the Event Management framework has the 
  16481. limitations described below. For a more up-to-date list of limitations, refer 
  16482. to the README file on EMan in the SOMobjects Developer Toolkit. Sink Events are 
  16483. not supported on Windows NT or on Windows 95. 
  16484.  
  16485.  
  16486. ΓòÉΓòÉΓòÉ 10.3.1. Use of EMan DLL ΓòÉΓòÉΓòÉ
  16487.  
  16488. The Windows NT/95 Event Manager Framework does not use a Sockets class, so 
  16489. SOMSockets cannot be set in the environment. Note that the EMan will look at 
  16490. its thread message queue so that messages will continue to be processed. It is 
  16491. best, however, to always run the EMan in its own thread. 
  16492.  
  16493.  
  16494. ΓòÉΓòÉΓòÉ 11. SOMobjects Error Codes ΓòÉΓòÉΓòÉ
  16495.  
  16496. This section covers the following subjects: 
  16497.  
  16498.      SOM Kernel Error Codes 
  16499.      DSOM Error Codes 
  16500.      Metaclass Framework Error Codes 
  16501.  
  16502.  
  16503. ΓòÉΓòÉΓòÉ 11.1. SOM Kernel Error Codes ΓòÉΓòÉΓòÉ
  16504.  
  16505. Following are error codes with messages/explanations for the SOM kernel and the 
  16506. various frameworks of the SOMobjects Developer Toolkit. 
  16507.  
  16508.  Value     Symbolic Name and Description 
  16509.  
  16510.  20011     SOMERROR_CCNullClass 
  16511.            The somDescendedFrom method was passed a null class argument. 
  16512.  
  16513.  20029     SOMERROR_SompntOverflow 
  16514.            The internal buffer used in somPrintf overflowed. 
  16515.  
  16516.  20039     SOMERROR_MethodNotFound 
  16517.            somFindMethodOk failed to find the indicated method. 
  16518.  
  16519.  20049     SOMERROR_StaticMethodTableOverflow 
  16520.            A Method-table overflow occurred in somAddStaticMethod. 
  16521.  
  16522.  20059     SOMERROR_DefaultMethod 
  16523.            The somDefaultMethod was called; a defined method probably was not 
  16524.            added before it was invoked. 
  16525.  
  16526.  20069     SOMERROR_MissingMethod 
  16527.            The specified method was not defined on the target object. 
  16528.  
  16529.  20079     SOMERROR_BadVersion 
  16530.            An attempt to load, create, or use a version of a class-object 
  16531.            implementation is incompatible with the using program. 
  16532.  
  16533.  20089     SOMERROR_NullId 
  16534.            The SOM_CheckId was given a null ID to check. 
  16535.  
  16536.  20099     SOMERROR_OutOfMemory 
  16537.            Memory is exhausted. 
  16538.  
  16539.  20109     SOMERROR_TestObjectFailure 
  16540.            The somObjectTest found problems with the object it was testing. 
  16541.  
  16542.  20119     SOMERROR_FailedTest 
  16543.            The somTest detected a failure; generated only by test code. 
  16544.  
  16545.  20121     SOMERROR_ClassNotFound 
  16546.            The somFindClass could not find the requested class. 
  16547.  
  16548.  20131     SOMERROR_OldMethod 
  16549.            An old-style method name was used; change to an appropriate name. 
  16550.  
  16551.  20149     SOMERROR_CouldNotStartup 
  16552.            The somEnvironmentNew failed to complete. 
  16553.  
  16554.  20159     SOMERROR_NotRegistered 
  16555.            The somUnloadClassFile argument was not a registered class. 
  16556.  
  16557.  20169     SOMERROR_BadOverride 
  16558.            The somOverrideSMethod was invoked for a method that was not defined 
  16559.            in a parent class. 
  16560.  
  16561.  20179     SOMERROR_NotImplementedYet 
  16562.            The method raising the error message is not implemented yet. 
  16563.  
  16564.  20189     SOMERROR_MustOverride 
  16565.            The method raising the error message should have been overridden. 
  16566.  
  16567.  20199     SOMERROR_BadArgument 
  16568.            An argument to a core SOM method failed a validity test. 
  16569.  
  16570.  20219     SOMERROR_NoParentClass 
  16571.            During the creation of a class object, the parent class could not be 
  16572.            found. 
  16573.  
  16574.  20229     SOMERROR_NoMetaClass 
  16575.            During the creation of a class object, the metaclass object could 
  16576.            not be found. 
  16577.  
  16578.  
  16579. ΓòÉΓòÉΓòÉ 11.2. DSOM Error Codes ΓòÉΓòÉΓòÉ
  16580.  
  16581. The  following table lists the error codes that may be encountered when using 
  16582. DSOM. 
  16583.  
  16584.  Value     Description 
  16585.  
  16586.  30001     SOMDERROR_NoMemory 
  16587.            Memory is exhausted. 
  16588.  
  16589.  30002     SOMDERROR_NotImplemented 
  16590.            Function or method has a null implementation. 
  16591.  
  16592.  30003     SOMDERROR_UnexpectedNULL 
  16593.            Internal error:  a pointer variable was found to be NULL, 
  16594.            unexpectedly. 
  16595.  
  16596.  30004     SOMDERROR_IO 
  16597.            I/O error while accessing a file located in SOMDDIR. 
  16598.  
  16599.  30005     SOMDERROR_BadVersion 
  16600.            Internal error:  incorrect version of an object reference data 
  16601.            table. 
  16602.  
  16603.  30006     SOMDERROR_ParmSize 
  16604.            Internal error:  a parameter of incorrect size was detected. 
  16605.  
  16606.  30007     SOMDERROR_HostName 
  16607.            Communications error:  unable to retrieve local host name. 
  16608.  
  16609.  30008     SOMDERROR_HostAddress 
  16610.            Communications error:  unable to retrieve local host address. 
  16611.  
  16612.  30009     SOMDERROR_SocketCreate 
  16613.            Communications error:  unable to create socket. 
  16614.  
  16615.  30010     SOMDERROR_SocketBind 
  16616.            Communications error:  unable to bind address to socket. 
  16617.  
  16618.  30011     SOMDERROR_SocketName 
  16619.            Communications error:  unable to query socket information. 
  16620.  
  16621.  30012     SOMDERROR_SocketReceive 
  16622.            Communications error:  unable to receive message from socket. 
  16623.  
  16624.  30013     SOMDERROR_SocketSend 
  16625.            Communications error: indicates socket error. 
  16626.  
  16627.  30014     SOMDERROR_SocketIoctl 
  16628.            Communications error:  unable to set socket blocking state. 
  16629.  
  16630.  30015     SOMDERROR_SocketSelect 
  16631.            Communications error:  unable to select on socket. 
  16632.  
  16633.  30016     SOMDERROR_PacketSequence 
  16634.            Communications error:  unexpected message packet received. 
  16635.  
  16636.  30017     SOMDERROR_PacketTooBig 
  16637.            Communications error:  packet too big for allocated message space. 
  16638.  
  16639.  30018     SOMDERROR_AddressNotFound 
  16640.            Uninitialized DSOM communications object. 
  16641.  
  16642.  30019     SOMDERROR_NoMessages 
  16643.            No messages available (and caller specified "no wait"). 
  16644.  
  16645.  30020     SOMDERROR_UnknownAddress 
  16646.            Invalid client or server address. 
  16647.  
  16648.  30021     SOMDERROR_RecvError 
  16649.            Communications error during receive. 
  16650.  
  16651.  30022     SOMDERROR_SendError 
  16652.            Communications error in sending the request. 
  16653.  
  16654.  30023     SOMDERROR_CommTimeOut 
  16655.            Communications timeout. 
  16656.  
  16657.  30024     SOMDERROR_CannotConnect 
  16658.            Unable to initialize connection information. 
  16659.  
  16660.  30025     SOMDERROR_BadConnection 
  16661.            Invalid connection information detected. 
  16662.  
  16663.  30026     SOMDERROR_NoHostName 
  16664.            Unable to get host name. 
  16665.  
  16666.  30027     SOMDERROR_BadBinding 
  16667.            Invalid server location information in proxy object. 
  16668.  
  16669.  30028     SOMDERROR_BadMethodName 
  16670.            Invalid method name in request message. 
  16671.  
  16672.  30029     SOMDERROR_BadEnvironment 
  16673.            Invalid Environment value in request message. 
  16674.  
  16675.  30030     SOMDERROR_BadContext 
  16676.            Invalid Context object in request message. 
  16677.  
  16678.  30031     SOMDERROR_BadNVList 
  16679.            Invalid Named Value List (NVList). 
  16680.  
  16681.  30032     SOMDERROR_BadFlag 
  16682.            Bad flag in NVList item. 
  16683.  
  16684.  30033     SOMDERROR_BadLength 
  16685.            Bad length in NVList item. 
  16686.  
  16687.  30034     SOMDERROR_BadObjref 
  16688.            Invalid object reference. 
  16689.  
  16690.  30035     SOMDERROR_NullField 
  16691.            Unexpected null field in request message. 
  16692.  
  16693.  30036     SOMDERROR_UnknownReposId 
  16694.            Attempt to use Invalid Interface Repository ID. 
  16695.  
  16696.  30037     SOMDERROR_NVListAccess 
  16697.            Invalid NVList object in request message. 
  16698.  
  16699.  30038     SOMDERROR_NVIndexError 
  16700.            Attempt to use an out-of-range NVList index. 
  16701.  
  16702.  30039     SOMDERROR_SysTime 
  16703.            Error retrieving system time. 
  16704.  
  16705.  30040     SOMDERROR_SystemCallFailed 
  16706.            System call failed. 
  16707.  
  16708.  30041     SOMDERROR_CouldNotStartProcess 
  16709.            Unable to start a new process. 
  16710.  
  16711.  30042     SOMDERROR_NoServerClass 
  16712.            No SOMDServer (sub)class specified for server implementation. 
  16713.  
  16714.  30043     SOMDERROR_NoSOMDInit 
  16715.            Missing SOMD_Init call in program. 
  16716.  
  16717.  30044     SOMDERROR_SOMDDIRNotSet 
  16718.            SOMDDIR environment variable not set. 
  16719.  
  16720.  30045     SOMDERROR_NoImplDatabase 
  16721.            Could not open Implementation Repository database. 
  16722.  
  16723.  30046     SOMDERROR_ImplNotFound 
  16724.            Implementation not found in implementation repository. 
  16725.  
  16726.  30047     SOMDERROR_ClassNotFound 
  16727.            Class not found in implementation repository. 
  16728.  
  16729.  30048     SOMDERROR_ServerNotFound 
  16730.            Server not found in somdd's active server table. 
  16731.  
  16732.  30049     SOMDERROR_ServerAlreadyExists 
  16733.            Server already exists in somdd's active server table. 
  16734.  
  16735.  30050     SOMDERROR_ServerNotActive 
  16736.            Server is not active. 
  16737.  
  16738.  30051     SOMDERROR_CouldNotStartSOM 
  16739.            SOM initialization error. 
  16740.  
  16741.  30052     SOMDERROR_ObjectNotFound 
  16742.            Could not find desired object. 
  16743.  
  16744.  30053     SOMDERROR_NoParentClass 
  16745.            Unable to find / load parent class during proxy class creation. 
  16746.  
  16747.  30054     SOMDERROR_DispatchError 
  16748.            Unable to dispatch method. 
  16749.  
  16750.  30055     SOMDERROR_BadTypeCode 
  16751.            Invalid type code. 
  16752.  
  16753.  30056     SOMDERROR_BadDescriptor 
  16754.            Invalid method descriptor. 
  16755.  
  16756.  30057     SOMDERROR_BadResultType 
  16757.            Invalid method result type. 
  16758.  
  16759.  30058     SOMDERROR_KeyInUse 
  16760.            Internal object key is in use. 
  16761.  
  16762.  30059     SOMDERROR_KeyNotFound 
  16763.            Internal object key not found. 
  16764.  
  16765.  30060     SOMDERROR_CtxInvalidPropName 
  16766.            Illegal context property name. 
  16767.  
  16768.  30061     SOMDERROR_CtxNoPropFound 
  16769.            Could not find property name in context. 
  16770.  
  16771.  30062     SOMDERROR_CtxStartScopeNotFound 
  16772.            Could not find specified context start scope. 
  16773.  
  16774.  30063     SOMDERROR_CtxAccess 
  16775.            Error accessing context object. 
  16776.  
  16777.  30064     SOMDERROR_CouldNotStartThread 
  16778.            System error:  Could not start thread. 
  16779.  
  16780.  30065     SOMDERROR_AccessDenied 
  16781.            System error:  Access to a system resource (file, queue, shared 
  16782.            memory, etc.) denied. 
  16783.  
  16784.  30066     SOMDERROR_BadParm 
  16785.            System error:  invalid parameter supplied to a operating system 
  16786.            call. 
  16787.  
  16788.  30067     SOMDERROR_Interrupt 
  16789.            System error:  Interrupted system call. 
  16790.  
  16791.  30068     SOMDERROR_Locked 
  16792.            System error:  Drive locked by another process. 
  16793.  
  16794.  30069     SOMDERROR_Pointer 
  16795.            System error:  Invalid physical address. 
  16796.  
  16797.  30070     SOMDERROR_Boundary 
  16798.            OS/2 system error:  ERROR_CROSSES_OBJECT_BOUNDARY. 
  16799.  
  16800.  30071     SOMDERROR_UnknownError 
  16801.            System error:  Unknown error on operating system call. 
  16802.  
  16803.  30072     SOMDERROR_NoSpace 
  16804.            System error:  No space left on device. 
  16805.  
  16806.  30073     SOMDERROR_DuplicateQueue 
  16807.            System error:  Duplicate queue name. 
  16808.  
  16809.  30074     SOMDERROR_BadQueueName 
  16810.            System error:  Invalid queue name. 
  16811.  
  16812.  30075     SOMDERROR_DuplicateSem 
  16813.            System error:  Duplicate semaphore name used. 
  16814.  
  16815.  30076     SOMDERROR_BadSemName 
  16816.            System error:  Invalid semaphore name. 
  16817.  
  16818.  30077     SOMDERROR_TooManyHandles 
  16819.            System error:  Too many files open (no file handles left). 
  16820.  
  16821.  30078     SOMDERROR_BadAddrFamily 
  16822.            System error:  Invalid address family. 
  16823.  
  16824.  30079     SOMDERROR_BadFormat 
  16825.            System error:  Invalid format. 
  16826.  
  16827.  30080     SOMDERROR_BadDrive 
  16828.            System error:  Invalid drive. 
  16829.  
  16830.  30081     SOMDERROR_SharingViolation 
  16831.            System error:  Sharing violation. 
  16832.  
  16833.  30082     SOMDERROR_BadExeSignature 
  16834.            System error:  Program file contains a DOS mode program or invalid 
  16835.            program. 
  16836.  
  16837.  30083     SOMDERROR_BadExe 
  16838.            Executable file is invalid (linker errors occurred when program file 
  16839.            was created). 
  16840.  
  16841.  30084     SOMDERROR_Busy 
  16842.            System error:  Segment is busy. 
  16843.  
  16844.  30085     SOMDERROR_BadThread 
  16845.            System error:  Invalid thread id. 
  16846.  
  16847.  30086     SOMDERROR_SOMDPORTNotDefined 
  16848.            SOMDPORT not defined. 
  16849.  
  16850.  30087     SOMDERROR_ResourceExists 
  16851.            System resource (file, queue, shared memory segment,. etc.) already 
  16852.            exists. 
  16853.  
  16854.  30088     SOMDERROR_UserName 
  16855.            USER environment variable is not set. 
  16856.  
  16857.  30089     SOMDERROR_WrongRefType 
  16858.            Operation attempted on an object reference is incompatible with the 
  16859.            reference type. 
  16860.  
  16861.  30090     SOMDERROR_MustOverride 
  16862.            This method has no default implementation and must be overridden. 
  16863.  
  16864.  30091     SOMDERROR_NoSocketsClass 
  16865.            Could not find/load Sockets class. 
  16866.  
  16867.  30092     SOMDERROR_EManRegData 
  16868.            Unable to register DSOM events with the Event Manager. 
  16869.  
  16870.  30093     SOMDERROR_NoRemoteComm 
  16871.            Remote communications is disabled (for Workstation DSOM). 
  16872.  
  16873.  30096     SOMDERROR_GlobalAtomError 
  16874.            On Windows only, an error occurred while adding a segment name to 
  16875.            the Windows atom table. 
  16876.  
  16877.  30097     SOMDERROR_NamedMemoryTableError 
  16878.            On Windows only, an error occurred while creating or deleting a 
  16879.            (named) shared memory segment. 
  16880.  
  16881.  30098     SOMDERROR_WMQUIT 
  16882.            On Windows only, indicates DSOM received a Windows WM_QUIT message. 
  16883.            The developer of a server application should check for 
  16884.            SOMDERROR_WMQUIT returned from method execute_request_loop and 
  16885.            handle the error by cleaning up and exiting. 
  16886.  
  16887.  30105     SOMDERROR_DuplicateImplEntry 
  16888.            Implementation repository identifier already exists.  Add wait time 
  16889.            between `regimpl' calls. 
  16890.  
  16891.  30106     SOMDERROR_InvalidSOMSOCKETS 
  16892.            SOMSOCKETS environment variable set incorrectly. 
  16893.  
  16894.  30107     SOMDERR0R_IRNotFound 
  16895.            Interface Repository not found. 
  16896.  
  16897.  30108     SOMDERR0R_ClassNotInIR 
  16898.            Attempt to create an object whose Class is not in the Interface 
  16899.            Repository. 
  16900.  
  16901.  30110     SOMDERROR_SocketError 
  16902.            A communications socket error has occurred.  Make sure the DSOM 
  16903.            daemon is running. 
  16904.  
  16905.  30111     SOMDERROR_PacketError 
  16906.            A communications packet error has occurred. 
  16907.  
  16908.  30112     SOMDERROR_Marshal 
  16909.  
  16910.  30113     SOMDERROR_NotProcessOwner 
  16911.            This error code is returned when the somdd daemon is trying to kill 
  16912.            the server process and if the owner of the server process is 
  16913.            different from that of the somdd daemon. 
  16914.  
  16915.  30114     SOMDERROR_ServerInactive 
  16916.            The specified server is in the process of being activated. 
  16917.  
  16918.  30115     SOMDERROR_ServerDisabled 
  16919.            The server has been disabled by the program servmgr. 
  16920.  
  16921.  30117     SOMDERROR_SOMDAlreadyRunning 
  16922.            The DSOM daemon has been started when another daemon is already 
  16923.            running. 
  16924.  
  16925.  30118     SOMDERROR_ServerToBeDeleted 
  16926.            An attempt has been made to start or connect to a server marked for 
  16927.            deletion. 
  16928.  
  16929.  30119     SOMDERROR_NoObjRefTable 
  16930.            The Object Reference Table cannot be found. 
  16931.  
  16932.  30120     SOMDERROR_UpdateImplDef 
  16933.            The Implementation Repository cannot be updated. 
  16934.  
  16935.  30138     SOMDERROR_NoImplDirectory 
  16936.            The directory signified by SOMDDIR does not exist. 
  16937.  
  16938.  30169     SOMDERROR_ServerNotStoppable 
  16939.            An attempt has been made to stop a server (using the dsom stop 
  16940.            command or a SOMDServerMgr object) registered as nonstoppable. 
  16941.  
  16942.  XXXXX     SOMDERROR_OperatingSystem 
  16943.            On AIX, this is the value of the C error variable "errno" defined in 
  16944.            errno.h; on OS/2 and Windows, it is the DOS API return code. 
  16945.  
  16946.  
  16947. ΓòÉΓòÉΓòÉ 11.3. Metaclass Framework Error Codes ΓòÉΓòÉΓòÉ
  16948.  
  16949. It is possible to receive the following messages from the Metaclass Framework 
  16950. while an application is running. 
  16951.  
  16952.  60001     An attempt was made to construct a class with SOMMSingleInstance as 
  16953.            a metaclass constraint. (This may occur indirectly because of the 
  16954.            construction of a derived metaclass). The initialization of the 
  16955.            class failed because somInitMIClass defined by SOMMSingleInstance is 
  16956.            in conflict with another metaclass that has overridden somNew. That 
  16957.            is, some other metaclass has already claimed the right to return the 
  16958.            value for somNew. 
  16959.  
  16960.  60002     An attempt was made to construct a class with SOMMSingleInstance as 
  16961.            a metaclass constraint. (This may occur indirectly because of the 
  16962.            construction of a derived metaclass). The initialization of the 
  16963.            class failed because somInitMIClass defined by SOMMSingleInstance is 
  16964.            in conflict with another metaclass that has overridden somFree. That 
  16965.            is, some other metaclass has already claimed this right to override 
  16966.            somFree. 
  16967.  
  16968.  60004     An invocation of somrRepInit was made with a logging type other than 
  16969.            `o' or `v'. 
  16970.  
  16971.  60005     The sommBeforeMethod or the sommAfterMethod was invoked on a 
  16972.            SOMRReplicableObject whose logging type is other than `o' or `v'. 
  16973.            This error cannot occur normally. The likely cause is that some 
  16974.            method invoked on another object has overwritten this object's 
  16975.            memory. 
  16976.  
  16977.  60006     A Before/After Metaclass must override both sommBeforeMethod and 
  16978.            sommAfterMethod.  This message indicates an attempt to create a 
  16979.            Before/After Metaclass where only one of the above methods is 
  16980.            overridden. 
  16981.  
  16982.  
  16983. ΓòÉΓòÉΓòÉ 12. Implementing Sockets Subclasses ΓòÉΓòÉΓòÉ
  16984.  
  16985. Distributed SOM (DSOM) and the Replication Framework require basic message 
  16986. services for inter-process communications. The Event Management Framework must 
  16987. be integrated with the same communication services in order to handle 
  16988. communications events. 
  16989.  
  16990. To maximize their portability to a wide variety of local area network transport 
  16991. protocols, the DSOM, Replication, and Event Management Frameworks have been 
  16992. written to use a common communications interface, which is implemented by one 
  16993. or more SOM class libraries using available local protocols. 
  16994.  
  16995. The common communications interface is based on the "sockets" interface used 
  16996. with TCP/IP, since its interface and semantics are fairly widespread and well 
  16997. understood. The IDL interface is named Sockets. There is no implementation 
  16998. associated with the Sockets interface by default; specific protocol 
  16999. implementations are supplied by subclass implementations. 
  17000.  
  17001. Note:  The Sockets classes supplied with the SOMobjects Developer Toolkit and 
  17002.        run-time packages are only intended to support the DSOM, Replication, 
  17003.        and Event Management Frameworks. These class implementations are not 
  17004.        intended for general application usage. 
  17005.  
  17006.  Available Sockets subclasses by SOMobjects product are as follows: 
  17007.  
  17008.      For AIX: 
  17009.            TCPIPSockets class for TCP/IP, 
  17010.            IPXSockets class for Netware IPX/SPX, and 
  17011.            NBSockets class for NetBIOS. 
  17012.      For OS/2 and Windows: 
  17013.            TCPIPSockets class (a) for TCP/IP for Windows or (b) for TCP/IP 
  17014.            1.2.1 on OS/2, 
  17015.            TCPIPSockets32 class for TCP/IP 2.0 on OS/2 only (see Note below), 
  17016.            IPXSockets class for NetWare IPX/SPX, and 
  17017.            NBSockets class for NetBIOS. 
  17018.  
  17019.  Note:  The TCPIPSocket32 class gives greater performance over the TCPIPSockets 
  17020.         class on OS/2, but requires the 32-bit version of TCPP/IP (version 2.0) 
  17021.         rather than the 16-bit version of TCP/IP (version 1.2.1). 
  17022.  
  17023.  Application developers may need to develop their own Sockets  subclass if the 
  17024.  desired transport protocol or product version is not one of those supported by 
  17025.  the SOMobjects run-time packages. This appendix explains how to approach the 
  17026.  implementation of a Sockets subclass, if necessary. 
  17027.  
  17028.  Warning: this may be a non-trivial exercise! 
  17029.  
  17030.  
  17031. ΓòÉΓòÉΓòÉ 12.1. Sockets IDL interface ΓòÉΓòÉΓòÉ
  17032.  
  17033. The base Sockets interface is expressed in IDL in the file somssock.idl, listed 
  17034. below. There is a one-to-one mapping between TCP/IP socket APIs and the methods 
  17035. defined in the Sockets interface. 
  17036.  
  17037. Please note the following: 
  17038.  
  17039.      The semantics of each of the Sockets methods must be that of the 
  17040.       corresponding TCP/IP call. Currently, only Internet address family 
  17041.       (AF_INET) addresses are used by the frameworks. 
  17042.  
  17043.       (The TCP/IP sockets API is not documented as part of the SOMobjects 
  17044.       Developer Toolkit. The implementor is referred to the programming 
  17045.       references for IBM TCP/IP for AIX or OS/2, or to similar references that 
  17046.       describe the sockets interface for TCP/IP.) 
  17047.  
  17048.      Data types, constants, and macros which are part of the Sockets interface 
  17049.       are defined in a C include file, soms.h. This file is supplied with the 
  17050.       SOMobjects Toolkit, and is not shown in this manual. 
  17051.  
  17052.      The Sockets interface is expressed in terms of a 32-bit implementation. 
  17053.  
  17054.      Some of the method parameters and return values are expressed using 
  17055.       pointer types, for example: 
  17056.  
  17057.             hostent *somsGethostent ();
  17058.  
  17059.       This has been done to map TCP/IP socket interfaces as directly as 
  17060.       possible to their IDL equivalent. (Use of strict CORBA IDL was not a 
  17061.       primary goal for the Sockets interface, since it is only used internally 
  17062.       by the frameworks.) 
  17063.  
  17064.      The Sockets class and its subclasses are  single instance classes. 
  17065.  
  17066.  Following is a listing of the file somssock.idl. Each socket call is briefly 
  17067.  described with a comment. 
  17068.  
  17069.   // 96F8647, 96F8648 (C) Copyright IBM Corp. 1992, 1993
  17070.   // All Rights Reserved
  17071.   // Licensed Materials - Property of IBM
  17072.  
  17073.   #ifndef somssock_idl
  17074.   #define somssock_idl
  17075.  
  17076.   #include <somobj.idl>
  17077.   #include <snglicls.idl>
  17078.  
  17079.   interface Sockets : SOMObject
  17080.   {
  17081.       //# The following typedefs are fully defined in <soms.h>.
  17082.       typedef SOMFOREIGN sockaddr;
  17083.       #pragma modifier sockaddr : impctx="C", struct;
  17084.       typedef SOMFOREIGN iovec;
  17085.       #pragma modifier iovec : impctx="C", struct;
  17086.       typedef SOMFOREIGN msghdr;
  17087.       #pragma modifier msghdr : impctx="C", struct;
  17088.       typedef SOMFOREIGN fd_set;
  17089.       #pragma modifier fd_set : impctx="C", struct;
  17090.       typedef SOMFOREIGN timeval;
  17091.       #pragma modifier timeval : impctx="C", struct;
  17092.       typedef SOMFOREIGN hostent;
  17093.       #pragma modifier hostent : impctx="C", struct;
  17094.       typedef SOMFOREIGN servent;
  17095.       #pragma modifier servent : impctx="C", struct;
  17096.       typedef SOMFOREIGN in_addr;
  17097.       #pragma modifier in_addr : impctx="C", struct;
  17098.  
  17099.       long somsAccept (in long s, out sockaddr name, out long namelen);
  17100.       // Accept a connection request from a client.
  17101.  
  17102.       long somsBind (in long s, inout sockaddr name, in long namelen);
  17103.       // Binds a unique local name to the socket with descriptor s.
  17104.  
  17105.       long somsConnect (in long s, inout sockaddr name,
  17106.                         in long namelen);
  17107.       // For streams sockets, attempts to establish a connection
  17108.       // between two sockets.  For datagram sockets, specifies the
  17109.       // socket's peer.
  17110.  
  17111.       hostent *somsGethostbyaddr (in char *addr, in long addrlen,
  17112.                                   in long domain);
  17113.       // Returns a hostent structure for the host address specified on
  17114.       // the call.
  17115.  
  17116.       hostent *somsGethostbyname (in string name);
  17117.       // Returns a hostent structure for the host name specified on
  17118.       // the call.
  17119.  
  17120.       hostent *somsGethostent ();
  17121.       // Returns a pointer to the next entry in the hosts file.
  17122.  
  17123.       unsigned long somsGethostid ();
  17124.       // Returns the unique identifier for the current host.
  17125.  
  17126.       long somsGethostname (in string name, in long namelength);
  17127.       // Retrieves the standard host name of the local host.
  17128.  
  17129.       long somsGetpeername (in long s, out sockaddr name,
  17130.                            out long namelen);
  17131.       // Gets the name of the peer connected to socket s.
  17132.  
  17133.       servent *somsGetservbyname (in string name, in string protocol);
  17134.       // Retrieves an entry from the /etc/services file using the
  17135.       // service name as a search key.
  17136.  
  17137.       long somsGetsockname (in long s, out sockaddr name,
  17138.                             out long namelen);
  17139.       // Stores the current name for the socket specified by the s
  17140.       // parameter into the structure pointed to by the name
  17141.       // parameter.
  17142.  
  17143.       long somsGetsockopt (in long s, in long level, in long optname,
  17144.                           in char *optval, out long option);
  17145.       // Returns the values of socket options at various protocol
  17146.       // levels.
  17147.  
  17148.       unsigned long somsHtonl (in unsigned long a);
  17149.       // Translates an unsigned long integer from host-byte order to
  17150.       // network-byte order.
  17151.  
  17152.       unsigned short somsHtons (in unsigned short a);
  17153.       // Translates an unsigned short integer from host-byte order to
  17154.       // network-byte order.
  17155.  
  17156.       long somsIoctl (in long s, in long cmd, in char *data,
  17157.                       in long length);
  17158.       // Controls the operating characteristics of sockets.
  17159.  
  17160.       unsigned long somsInet_addr (in string cp);
  17161.       // Interprets character strings representing numbers expressed
  17162.       // in standard '.' notation and returns numbers suitable for use
  17163.       // as internet addresses.
  17164.  
  17165.       unsigned long somsInet_lnaof (in in_addr addr);
  17166.       // Breaks apart the internet address and returns the local
  17167.       // network address portion.
  17168.  
  17169.       in_addr somsInet_makeaddr (in unsigned long net,
  17170.                                  in unsigned long lna);
  17171.       // Takes a network number and a local network address and
  17172.       // constructs an internet address.
  17173.  
  17174.       unsigned long somsInet_netof (in in_addr addr);
  17175.       // Returns the network number portion of the given internet
  17176.       // address.
  17177.  
  17178.       unsigned long somsInet_network (in string cp);
  17179.       // Interprets character strings representing numbers expressed
  17180.       // in standard '.' notation and returns numbers suitable for use
  17181.       // as network numbers.
  17182.  
  17183.       string somsInet_ntoa (in in_addr addr);
  17184.       // Returns a pointer to a string expressed in the dotted-decimal
  17185.       // notation.
  17186.  
  17187.       long somsListen (in long s, in long backlog);
  17188.       // Creates a connection request queue of length backlog to queue
  17189.       // incoming connection requests, and then waits for incoming
  17190.       // connection requests.
  17191.  
  17192.       unsigned long somsNtohl (in unsigned long a);
  17193.       // Translates an unsigned long integer from network-byte order
  17194.       // to host-byte order.
  17195.  
  17196.       unsigned short somsNtohs (in unsigned short a);
  17197.       // Translates an unsigned short integer from network-byte order
  17198.       // to host-byte order.
  17199.  
  17200.       long somsReadv (in long s, inout iovec iov, in long iovcnt);
  17201.       // Reads data on socket s and stores it in a set of buffers
  17202.       // described by iov.
  17203.  
  17204.       long somsRecv (in long s, in char *buf, in long len,
  17205.                      in long flags);
  17206.       // Receives data on streams socket s and stores it in buf.
  17207.  
  17208.       long somsRecvfrom (in long s, in char *buf, in long len,
  17209.           in long flags, out sockaddr name, out long namelen);
  17210.       // Receives data on datagram socket s and stores it in buf.
  17211.  
  17212.       long somsRecvmsg (in long s, inout msghdr msg, in long flags);
  17213.       // Receives messages on a socket with descriptor s and stores
  17214.       // them in an array of message headers.
  17215.  
  17216.       long somsSelect (in long nfds, inout fd_set readfds,
  17217.                        inout fd_set writefds, inout fd_set exceptfds,
  17218.                        inout timeval timeout);
  17219.       // Monitors activity on a set of different sockets until a
  17220.       // timeout expires, to see if any sockets are ready for reading
  17221.       // or writing, or if an exceptional condition is pending.
  17222.  
  17223.       long somsSend (in long s, in char *msg, in long len,
  17224.                      in long flags);
  17225.       // Sends msg on streams socket s.
  17226.  
  17227.       long somsSendmsg (in long s, inout msghdr msg, in long flags);
  17228.       // Sends messages passed in an array of message headers on a
  17229.       // socket with descriptor s.
  17230.  
  17231.       long somsSendto (in long s, inout char msg, in long len,
  17232.                        in long flags, inout sockaddr to, in long tolen);
  17233.       // Sends msg on datagram socket s.
  17234.  
  17235.       long somsSetsockopt (in long s, in long level, in long optname,
  17236.                            in char *optval, in long optlen);
  17237.       // Sets options associated with a socket.
  17238.  
  17239.       long somsShutdown (in long s, in long how);
  17240.       // Shuts down all or part of a full-duplex connection.
  17241.  
  17242.       long somsSocket (in long domain, in long type,
  17243.                        in long protocol);
  17244.       // Creates an endpoint for communication and returns a socket
  17245.       // descriptor representing the endpoint.
  17246.  
  17247.       long somsSoclose (in long s);
  17248.       // Shuts down socket s and frees resources allocated to the
  17249.       // socket.
  17250.  
  17251.       long somsWritev (in long s, inout iovec iov, in long iovcnt);
  17252.       // Writes data on socket s.  The data is gathered from the
  17253.       // buffers described by iov.
  17254.  
  17255.       attribute long serrno;
  17256.       // Used to pass error numbers.
  17257.  
  17258.   #ifdef __SOMIDL__
  17259.       implementation
  17260.       {
  17261.       releaseorder:
  17262.           somsAccept, somsBind, somsConnect, somsGethostbyaddr,
  17263.           somsGethostbyname, somsGethostent, somsGethostid,
  17264.           somsGethostname, somsGetpeername, somsGetsockname,
  17265.           somsGetsockopt, somsHtonl, somsHtons, somsIoctl,
  17266.           somsInet_addr, somsInet_lnaof, somsInet_makeaddr,
  17267.           somsInet_netof, somsInet_network, somsInet_ntoa,
  17268.           somsListen, somsNtohl, somsNtohs, somsReadv,
  17269.           somsRecv, somsRecvfrom, somsRecvmsg, somsSelect,
  17270.           somsSend, somsSendmsg, somsSendto, somsSetsockopt,
  17271.           somsShutdown, somsSocket, somsSoclose, somsWritev,
  17272.           _set_serrno, _get_serrno, somsGetservbyname;
  17273.  
  17274.       //# Class modifiers
  17275.       callstyle=idl;
  17276.       metaclass = SOMMSingleInstance;
  17277.       majorversion=1; minorversion=1;
  17278.       dll="soms.dll";
  17279.       };
  17280.   #endif /* __SOMIDL__ */
  17281.   };
  17282.   #endif  /* somssock_idl */
  17283.  
  17284.  
  17285. ΓòÉΓòÉΓòÉ 12.2. IDL for a Sockets subclass ΓòÉΓòÉΓòÉ
  17286.  
  17287. Sockets subclasses inherit their entire interface from Sockets. All methods are 
  17288. overridden. 
  17289.  
  17290. For example, here is a listing of the TCPIPSockets IDL description. 
  17291.  
  17292. // 96F8647, 96F8648 (C) Copyright IBM Corp. 1992, 1993
  17293. // All Rights Reserved
  17294. // Licensed Materials - Property of IBM
  17295.  
  17296. #ifndef tcpsock_idl
  17297. #define tcpsock_idl
  17298.  
  17299. #include <somssock.idl>
  17300. #include <snglicls.idl>
  17301.  
  17302. interface TCPIPSockets : Sockets
  17303. {
  17304. #ifdef __SOMIDL__
  17305.     implementation
  17306.     {
  17307.     //# Class modifiers
  17308.     callstyle=idl;
  17309.     majorversion=1; minorversion=1;
  17310.     dllname="somst.dll";
  17311.     metaclass=SOMMSingleInstance;
  17312.     //# Method modifiers
  17313.     somsAccept: override;
  17314.     somsBind: override;
  17315.     somsConnect: override;
  17316.     somsGethostbyaddr: override;
  17317.     somsGethostbyname: override;
  17318.     somsGethostent: override;
  17319.     somsGethostid: override;
  17320.     somsGethostname: override;
  17321.     somsGetpeername: override;
  17322.     somsGetservbyname: override;
  17323.     somsGetsockname: override;
  17324.     somsGetsockopt: override;
  17325.     somsHtonl: override;
  17326.     somsHtons: override;
  17327.     somsIoctl: override;
  17328.     somsInet_addr: override;
  17329.     somsInet_lnaof: override;
  17330.     somsInet_makeaddr: override;
  17331.     somsInet_netof: override;
  17332.     somsInet_network: override;
  17333.     somsInet_ntoa: override;
  17334.     somsListen: override;
  17335.     somsNtohl: override;
  17336.     somsNtohs: override;
  17337.     somsReadv: override;
  17338.     somsRecv: override;
  17339.     somsRecvfrom: override;
  17340.     somsRecvmsg: override;
  17341.     somsSelect: override;
  17342.     somsSend: override;
  17343.     somsSendmsg: override;
  17344.     somsSendto: override;
  17345.     somsSetsockopt: override;
  17346.     somsShutdown: override;
  17347.     somsSocket: override;
  17348.     somsSoclose: override;
  17349.     somsWritev: override;
  17350.     _set_serrno: override;
  17351.    _get_serrno: override;
  17352.    };
  17353. #endif /* __SOMIDL__ */
  17354.  };
  17355. #endif  /* tcpsock_idl */
  17356.  
  17357.  
  17358. ΓòÉΓòÉΓòÉ 12.3. Implementation considerations ΓòÉΓòÉΓòÉ
  17359.  
  17360.      Only the AF_INET address family must be supported. That is, the DSOM, 
  17361.       Replication, and Event Manager frameworks all use Internet addresses and 
  17362.       port numbers to refer to specific sockets. 
  17363.  
  17364.      On OS/2, the SOMobjects run-time libraries were built using the C Set/2 
  17365.       32-bit compiler. If the underlying subclass implementation uses a 16-bit 
  17366.       subroutine library, conversion of the method call arguments may be 
  17367.       required. (This mapping of arguments is often referred to as "thunking.") 
  17368.  
  17369.      Sockets subclasses to be used in multi-threaded environments should be 
  17370.       made thread-safe. That is, it is possible that concurrent threads may 
  17371.       make calls on the (single) Sockets object, so data structures must be 
  17372.       protected within critical regions, as appropriate. 
  17373.  
  17374.      Valid values for the serrno attribute are defined in the file soms.h. The 
  17375.       subclass implementation should map local error numbers into the 
  17376.       appropriate corresponding Sockets error numbers. 
  17377.  
  17378.  
  17379. ΓòÉΓòÉΓòÉ 12.4. Example code ΓòÉΓòÉΓòÉ
  17380.  
  17381. The following code fragment shows an example of the implementation of the 
  17382. somsBind method of the TCPIPSockets subclass, for both AIX and OS/2. The sample 
  17383. illustrates that, for TCP/IP, the implementation is basically a one-to-one 
  17384. mapping of Sockets methods onto TCP/IP calls. For other transport protocols, 
  17385. the mapping from the socket abstraction to the protocol's API may be more 
  17386. difficult. 
  17387.  
  17388. For AIX, the mapping from Sockets method to TCP/IP call is trivial. 
  17389.  
  17390. SOM_Scope long  SOMLINK somsBind(TCPIPSockets somSelf,
  17391.                                  Environment *ev,
  17392.                                  long s, Sockets_sockaddr* name,
  17393.                                  long namelen)
  17394. {
  17395.     long rc;
  17396.  
  17397.     TCPIPSocketsMethodDebug("TCPIPSockets","somsBind");
  17398.  
  17399.     rc = (long) bind((int)s, name, (int)namelen);
  17400.  
  17401.     if (rc == -1)
  17402.        __set_serrno(somSelf, ev, errno);
  17403.  
  17404.     return rc;
  17405. }
  17406.  
  17407. On OS/2, however, the TCP/IP Release 1.2.1 library is a 16-bit library. 
  17408. Consequently, many of the method calls require conversion ("thunking") of 
  17409. 32-bit parameters into 16-bit parameters, before the actual TCP/IP calls can be 
  17410. invoked. For example, the function prototype for the somsBind method is defined 
  17411. as: 
  17412.  
  17413. SOM_Scope long  SOMLINK somsBind(TCPIPSockets somSelf,
  17414.                                  Environment *ev,
  17415.                                  long s, Sockets_sockaddr* name,
  17416.                                  long namelen);
  17417.  
  17418. whereas the file socket.h on OS/2 declares the bind function with the following 
  17419. prototype: 
  17420.  
  17421. short _Far16 _Cdecl bind(short /*s*/, void * _Seg16 /*name*/,
  17422.                          short /*len*/);
  17423.  
  17424. In this case, the pointer to the "name" structure, passed as a 32-bit address, 
  17425. cannot be used directly in the bind call: a 16-bit address must be passed 
  17426. instead. This can be accomplished by dereferencing the 32-bit pointer provided 
  17427. by the "name" parameter in the somsBind call, copying the caller's 
  17428. Sockets_sockaddr structure into a local structure ("name16"), and then passing 
  17429. the address of the local structure ("&name16") as a 16-bit address in the bind 
  17430. call. 
  17431.  
  17432. SOM_Scope long  SOMLINK somsBind(TCPIPSockets somSelf,
  17433.                                  Environment *ev,
  17434.                                  long s, Sockets_sockaddr* name,
  17435.                                  long namelen)
  17436. {
  17437.     long rc;
  17438.     Sockets_sockaddr name16;
  17439.  
  17440.     TCPIPSocketsMethodDebug("TCPIPSockets","somsBind");
  17441.  
  17442.     /* copy user's parameter into a local structure */
  17443.     memcpy ((char *)&name16, (char *)((sockaddr32 *)name), namelen);
  17444.     rc = (long) bind((short)s, (void *)&name16, (short)namelen);
  17445.  
  17446.     if (rc == -1)
  17447.        __set_serrno(somSelf, ev, tcperrno());
  17448.  
  17449.     return rc;
  17450. }
  17451.  
  17452.  
  17453. ΓòÉΓòÉΓòÉ 13. Glossary ΓòÉΓòÉΓòÉ
  17454.  
  17455. Note:  In the following definitions, words shown in italics are terms for which 
  17456. separate glossary entries are also defined. 
  17457.  
  17458.  
  17459. ΓòÉΓòÉΓòÉ 13.1. abstract class ΓòÉΓòÉΓòÉ
  17460.  
  17461. abstract class 
  17462.  
  17463. A class that is not designed to be instantiated, but serves as a base class for 
  17464. the definition of subclasses. Regardless of whether an abstract class inherits 
  17465. instance data and methods from parent classes, it will always introduce methods 
  17466. that must be overridden in a subclass, in order to produce a class whose 
  17467. objects are semantically valid. 
  17468.  
  17469.  
  17470. ΓòÉΓòÉΓòÉ 13.2. affinity group ΓòÉΓòÉΓòÉ
  17471.  
  17472. affinity group 
  17473.  
  17474. An array of class objects that were all registered with the SOMClassMgr object 
  17475. during the dynamic loading of a class. Any class is a member of at most one 
  17476. affinity group. 
  17477.  
  17478.  
  17479. ΓòÉΓòÉΓòÉ 13.3. ancestor class ΓòÉΓòÉΓòÉ
  17480.  
  17481. ancestor class 
  17482.  
  17483. A class from which another class inherits instance methods, attributes, and 
  17484. instance variables, either directly or indirectly. A direct descendant of an 
  17485. ancestor class is called a child class, derived class, or  subclass. A direct 
  17486. ancestor of a class is called a parent class, base class, or superclass. 
  17487.  
  17488.  
  17489. ΓòÉΓòÉΓòÉ 13.4. aggregate type ΓòÉΓòÉΓòÉ
  17490.  
  17491. aggregate type 
  17492.  
  17493. A user-defined data type that combines basic types (such as, char, short, 
  17494. float, and so on) into a more complex type (such as structs, arrays, strings, 
  17495. sequences, unions, or enums). 
  17496.  
  17497.  
  17498. ΓòÉΓòÉΓòÉ 13.5. apply stub ΓòÉΓòÉΓòÉ
  17499.  
  17500. apply stub 
  17501.  
  17502. A procedure corresponding to a particular method that accepts as arguments: the 
  17503. object on which the method is to be invoked, a pointer to a location in memory 
  17504. where the method's result should be stored, a pointer to the method's 
  17505. procedure, and the method's arguments in the form of a va_list. The apply stub 
  17506. extracts the arguments from the va_list, invokes the method with its arguments, 
  17507. and stores its result in the specified location. Apply stubs are registered 
  17508. with class objects when instance methods are defined, and are invoked using the 
  17509. somApply function. Typically, implementations that override somDispatch call 
  17510. somApply to invoke a method on a va_list of arguments. 
  17511.  
  17512.  
  17513. ΓòÉΓòÉΓòÉ 13.6. attribute ΓòÉΓòÉΓòÉ
  17514.  
  17515. attribute 
  17516.  
  17517. A specialized syntax for declaring "set" and "get" methods. Method names 
  17518. corresponding to attributes always begin with "_set_" or "_get_". An attribute 
  17519. name is declared in the body of the interface statement for a class. Method 
  17520. procedures for get/set methods are automatically defined by the SOM Compiler 
  17521. unless an attribute is declared as "noget/noset". Likewise, a corresponding 
  17522. instance variable is automatically defined unless an attribute is declared as 
  17523. "nodata". IDL also supports "readonly" attributes, which specify only a "get" 
  17524. method. (Contrast an attribute with an instance variable.) 
  17525.  
  17526.  
  17527. ΓòÉΓòÉΓòÉ 13.7. auxiliary class data structure: ΓòÉΓòÉΓòÉ
  17528.  
  17529. auxiliary class data structure: 
  17530.  
  17531. A structure provided by the SOM API to support efficient static access to 
  17532. class-specific information used in dealing with SOM objects. The structure's 
  17533. name is <className>CClassData. Its first component (parentMtab) is a list of 
  17534. parent-class method tables (used to support efficient parent method calls). Its 
  17535. second component (instanceDataToken) is the instance token for the class 
  17536. (generally used to locate the instance data introduced by method procedures 
  17537. that implement methods defined by the class). 
  17538.  
  17539.  
  17540. ΓòÉΓòÉΓòÉ 13.8. base class ΓòÉΓòÉΓòÉ
  17541.  
  17542. base class 
  17543.  
  17544. See parent class. 
  17545.  
  17546.  
  17547. ΓòÉΓòÉΓòÉ 13.9. behavior (of an object) ΓòÉΓòÉΓòÉ
  17548.  
  17549. behavior (of an object) 
  17550.  
  17551. The methods that an object responds to. These methods are those either 
  17552. introduced or inherited by the class of the object. See also state. 
  17553.  
  17554.  
  17555. ΓòÉΓòÉΓòÉ 13.10. bindings: ΓòÉΓòÉΓòÉ
  17556.  
  17557. bindings: 
  17558.  
  17559. Language-specific macros and procedures that make implementing and using SOM 
  17560. classes more convenient. These bindings offer a convenient interface to SOM 
  17561. that is tailored to a particular programming language. The SOM Compiler 
  17562. generates binding files for C and C ++. These binding files include an 
  17563. implementation template for the class and two header files, one to be included 
  17564. in the class's implementation file and the other in client programs. 
  17565.  
  17566.  
  17567. ΓòÉΓòÉΓòÉ 13.11. BOA (basic object adapter) class: ΓòÉΓòÉΓòÉ
  17568.  
  17569. BOA (basic object adapter) class: 
  17570.  
  17571. A CORBA interface (represented as an abstract class in DSOM), which defines 
  17572. generic object-adapter (OA) methods that a server can use to register itself 
  17573. and its objects with an ORB (object request broker). See also SOMOA (SOM object 
  17574. adapter) class. 
  17575.  
  17576.  
  17577. ΓòÉΓòÉΓòÉ 13.12. callback ΓòÉΓòÉΓòÉ
  17578.  
  17579. callback 
  17580.  
  17581. A user-provided procedure or method to the Event Management Framework that gets 
  17582. invoked when a registered event occurs. (See also event ). 
  17583.  
  17584.  
  17585. ΓòÉΓòÉΓòÉ 13.13. casted dispatching ΓòÉΓòÉΓòÉ
  17586.  
  17587. casted dispatching 
  17588.  
  17589. A form of method dispatching that uses casted method resolution; that is, it 
  17590. uses a designated ancestor class of the actual target object's class to 
  17591. determine what procedure to call to execute a specified method. 
  17592.  
  17593.  
  17594. ΓòÉΓòÉΓòÉ 13.14. casted method resolution ΓòÉΓòÉΓòÉ
  17595.  
  17596. casted method resolution 
  17597.  
  17598. A method resolution technique that uses a method procedure from the method 
  17599. table of an ancestor of the class of an object (rather than using a procedure 
  17600. from the method table of the object's own class). 
  17601.  
  17602.  
  17603. ΓòÉΓòÉΓòÉ 13.15. child class ΓòÉΓòÉΓòÉ
  17604.  
  17605. child class 
  17606.  
  17607. A class that inherits instance methods, attributes, and instance variables 
  17608. directly from another class, called the parent class, base class, or 
  17609. superclass, or indirectly from an ancestor class. A child class may also be 
  17610. called a derived class or subclass. 
  17611.  
  17612.  
  17613. ΓòÉΓòÉΓòÉ 13.16. class ΓòÉΓòÉΓòÉ
  17614.  
  17615. class 
  17616.  
  17617. A way of categorizing objects based on their behavior (the methods they 
  17618. support) and shape (memory layout). A class is a definition of a generic 
  17619. object. In SOM, a class is also a special kind of object that can manufacture 
  17620. other objects that all have a common shape and exhibit similar behavior. The 
  17621. specification of what comprises the shape and behavior of a set of objects is 
  17622. referred to as the "definition" of a class. New classes are defined in terms of 
  17623. existing classes through a technique known as inheritance. See also class 
  17624. object. 
  17625.  
  17626.  
  17627. ΓòÉΓòÉΓòÉ 13.17. class variable ΓòÉΓòÉΓòÉ
  17628.  
  17629. class variable 
  17630.  
  17631. Instance data of a class object. All instance data of an object is defined 
  17632. (through either introduction or inheritance) by the object's class. Thus, class 
  17633. variables are defined by metaclasses. 
  17634.  
  17635.  
  17636. ΓòÉΓòÉΓòÉ 13.18. class data structure ΓòÉΓòÉΓòÉ
  17637.  
  17638. class data structure 
  17639.  
  17640. A structure provided by the SOM API to support efficient static access to 
  17641. class-specific information used in dealing with SOM objects. The structure's 
  17642. name is <className>ClassData. Its first component (classObject) is a pointer to 
  17643. the corresponding class object. The remaining components (named after the 
  17644. instance methods and instance variables) are method tokens or data tokens, in 
  17645. order as specified by the class's implementation. Data tokens are only used to 
  17646. support data (public and private) introduced by classes declared using OIDL; 
  17647. IDL attributes are supported with method tokens. 
  17648.  
  17649.  
  17650. ΓòÉΓòÉΓòÉ 13.19. class manager ΓòÉΓòÉΓòÉ
  17651.  
  17652. class manager 
  17653.  
  17654. An object that acts as a run-time registry for all SOM class objects that exist 
  17655. within the current process and which assists in the dynamic loading and 
  17656. unloading of class libraries. A class implementor can define a customized class 
  17657. manager by subclassing SOMClassMgr class to replace the SOM-supplied 
  17658. SOMClassMgrObject. This is done to augment the functionality of the default 
  17659. class-management registry (for example, to coordinate the automatic quiescing 
  17660. and unloading of classes). 
  17661.  
  17662.  
  17663. ΓòÉΓòÉΓòÉ 13.20. class method ΓòÉΓòÉΓòÉ
  17664.  
  17665. class method 
  17666.  
  17667. (Also known as factory method or constructor.) A class method is a method that 
  17668. a class object responds to (as opposed to an instance method). A class method 
  17669. that class <X> responds to is provided by the metaclass of class <X>. Class 
  17670. methods are executed without requiring any instances of class <X> to exist, and 
  17671. are frequently used to create instances of the class. 
  17672.  
  17673.  
  17674. ΓòÉΓòÉΓòÉ 13.21. class object ΓòÉΓòÉΓòÉ
  17675.  
  17676. class object 
  17677.  
  17678. The run-time object representing a SOM class. In SOM, a class object can 
  17679. perform the same behavior common to all objects, inherited from SOMObject. 
  17680.  
  17681.  
  17682. ΓòÉΓòÉΓòÉ 13.22. client code ΓòÉΓòÉΓòÉ
  17683.  
  17684. client code 
  17685.  
  17686. (Or client program or client.) An application program, written in the 
  17687. programmer's preferred language, which invokes methods on o  bjects that are 
  17688. instances of SOM classes. In DSOM, this could be a program that invokes a 
  17689. method on a remote object. 
  17690.  
  17691.  
  17692. ΓòÉΓòÉΓòÉ 13.23. constructor ΓòÉΓòÉΓòÉ
  17693.  
  17694. constructor 
  17695.  
  17696. See class method. 
  17697.  
  17698.  
  17699. ΓòÉΓòÉΓòÉ 13.24. context expression ΓòÉΓòÉΓòÉ
  17700.  
  17701. context expression 
  17702.  
  17703. An optional expression in a method's IDL declaration, specifying identifiers 
  17704. whose value (if any) can be used during SOM's method resolution  process and/or 
  17705. by the target object as it executes the method procedure. If a context 
  17706. expression is specified, then a related Context parameter is required when the 
  17707. method is invoked. (This Context parameter is an implicit parameter in the IDL 
  17708. specification of the method, but it is an explicit parameter of the method's 
  17709. procedure.) No SOM-supplied methods require context parameters. 
  17710.  
  17711.  
  17712. ΓòÉΓòÉΓòÉ 13.25. CORBA ΓòÉΓòÉΓòÉ
  17713.  
  17714. CORBA 
  17715.  
  17716. The Common Object Request Broker Architecture established by the Object 
  17717. Management Group. IBM's Interface Definition Language used to describe the 
  17718. interface for SOM classes is fully compliant with CORBA standards. 
  17719.  
  17720.  
  17721. ΓòÉΓòÉΓòÉ 13.26. daemon ΓòÉΓòÉΓòÉ
  17722.  
  17723. daemon 
  17724.  
  17725. See DSOM daemon. 
  17726.  
  17727.  
  17728. ΓòÉΓòÉΓòÉ 13.27. data token ΓòÉΓòÉΓòÉ
  17729.  
  17730. data token 
  17731.  
  17732. A value that identifies a specific instance variable within an object whose 
  17733. class inherits the instance variable (as a result of being derived, directly or 
  17734. indirectly, from the class that introduces the instance variable). An object 
  17735. and a data token are passed to the SOM run-time procedure, somDataResolve, 
  17736. which returns is a pointer to the specific instance variable corresponding to 
  17737. the data token. (See also instance token.) 
  17738.  
  17739.  
  17740. ΓòÉΓòÉΓòÉ 13.28. derived class ΓòÉΓòÉΓòÉ
  17741.  
  17742. derived class 
  17743.  
  17744. See subclass and subclassing. 
  17745.  
  17746.  
  17747. ΓòÉΓòÉΓòÉ 13.29. derived metaclass ΓòÉΓòÉΓòÉ
  17748.  
  17749. derived metaclass 
  17750.  
  17751. (Or SOM-derived metaclass.) A metaclass  that SOM creates automatically (often 
  17752. even when the class implementor specifies an explicit metaclass) as needed to 
  17753. ensure that, for any code that executes without method-resolution error on an 
  17754. instance of a given class, the code will similarly execute without 
  17755. method-resolution error on instances of any subclass of the given class. SOM's 
  17756. ability to derive such metaclasses is a fundamental necessity in order to 
  17757. ensure binary compatibility for client programs despite any subsequent changes 
  17758. in class implementations. 
  17759.  
  17760.  
  17761. ΓòÉΓòÉΓòÉ 13.30. descriptor ΓòÉΓòÉΓòÉ
  17762.  
  17763. descriptor 
  17764.  
  17765. (Or method descriptor.) An ID representing the identifier of a method 
  17766. definition or an attribute definition in the Interface Repository. The IR 
  17767. definition contains information about the method's return type and the type of 
  17768. its arguments. 
  17769.  
  17770.  
  17771. ΓòÉΓòÉΓòÉ 13.31. directive ΓòÉΓòÉΓòÉ
  17772.  
  17773. directive 
  17774.  
  17775. A message (a pre-defined character constant) received by a replica from the 
  17776. Replication Framework. Indicates a potential failure situation. 
  17777.  
  17778.  
  17779. ΓòÉΓòÉΓòÉ 13.32. dirty object ΓòÉΓòÉΓòÉ
  17780.  
  17781. dirty object 
  17782.  
  17783. A persistent object that has been modified since it was last written to 
  17784. persistent storage. 
  17785.  
  17786.  
  17787. ΓòÉΓòÉΓòÉ 13.33. dispatch-function resolution ΓòÉΓòÉΓòÉ
  17788.  
  17789. dispatch-function resolution 
  17790.  
  17791. Dispatch-function resolution is the slowest, but most flexible, of the three 
  17792. method-resolution techniques SOM offers. Dispatch functions permit method 
  17793. resolution to be based on arbitrary rules associated with an object's class. 
  17794. Thus, a class implementor has complete freedom in determining how methods 
  17795. invoked on its instances are resolved. See also dispatch method and dynamic 
  17796. dispatching. 
  17797.  
  17798.  
  17799. ΓòÉΓòÉΓòÉ 13.34. dispatch method ΓòÉΓòÉΓòÉ
  17800.  
  17801. dispatch method 
  17802.  
  17803. A method (such as somDispatch or somClassDispatch) that is invoked (and passed 
  17804. an argument list and the ID of another method) in order to determine the 
  17805. appropriate method procedure to execute. The use of dispatch methods 
  17806. facilitates dispatch-function resolution in SOM applications and enables method 
  17807. invocation on remote objects in DSOM applications. See also dynamic 
  17808. dispatching. 
  17809.  
  17810.  
  17811. ΓòÉΓòÉΓòÉ 13.35. DLL ΓòÉΓòÉΓòÉ
  17812.  
  17813. DLL 
  17814.  
  17815. Abbreviation for dynamic link library. 
  17816.  
  17817.  
  17818. ΓòÉΓòÉΓòÉ 13.36. DSOM daemon (somdd) ΓòÉΓòÉΓòÉ
  17819.  
  17820. DSOM daemon (somdd) 
  17821.  
  17822. The DSOM process (somdd) that locates and activates servers. The daemon 
  17823. (actually known as the location services daemon) is primarily meant to provide 
  17824. a client with the necessary communications information to allow the client to 
  17825. connect with an implementation server. 
  17826.  
  17827.  
  17828. ΓòÉΓòÉΓòÉ 13.37. dynamic dispatching ΓòÉΓòÉΓòÉ
  17829.  
  17830. dynamic dispatching 
  17831.  
  17832. Method dispatching using dispatch-function resolution; the use of dynamic 
  17833. method resolution at run time. See also dispatch- function resolution and 
  17834. dynamic method. 
  17835.  
  17836.  
  17837. ΓòÉΓòÉΓòÉ 13.38. Dynamic Invocation Interface (DII) ΓòÉΓòÉΓòÉ
  17838.  
  17839. Dynamic Invocation Interface (DII) 
  17840.  
  17841. The CORBA-specified interface, implemented in DSOM, that is used to dynamically 
  17842. build requests on remote objects. Note that DSOM applications can also use the 
  17843. somDispatch method for dynamic method calls when the object is remote. See also 
  17844. dispatch method. 
  17845.  
  17846.  
  17847. ΓòÉΓòÉΓòÉ 13.39. dynamic link library ΓòÉΓòÉΓòÉ
  17848.  
  17849. dynamic link library 
  17850.  
  17851. A piece of code that can be loaded (activated) dynamically. This code is 
  17852. physically separate from its callers. DLLs can be loaded at load time or at run 
  17853. time. Widely used term on OS/2, Windows, and, to some extent, AIX. 
  17854.  
  17855.  
  17856. ΓòÉΓòÉΓòÉ 13.40. dynamic method ΓòÉΓòÉΓòÉ
  17857.  
  17858. dynamic method 
  17859.  
  17860. A method that is not declared in the IDL interface statement for a class of 
  17861. objects, but is added to the interface at run time, after which instances of 
  17862. the class (or of its subclasses) will respond to the registered dynamic method. 
  17863. Because dynamic methods are not declared, usage bindings for SOM classes cannot 
  17864. support their use; thus, offset method resolution is not available. Instead, 
  17865. name-lookup or dispatch-function method resolution must be used to invoke 
  17866. dynamic methods. (There are currently no known uses of dynamic methods by any 
  17867. SOM applications.) See also method and static method. 
  17868.  
  17869.  
  17870. ΓòÉΓòÉΓòÉ 13.41. encapsulation ΓòÉΓòÉΓòÉ
  17871.  
  17872. encapsulation 
  17873.  
  17874. An object-oriented programming feature whereby the implementation details of a 
  17875. class are hidden from client programs, which are only required to know the 
  17876. interface of a class (the signatures of its methods and the names of its 
  17877. attributes) in order to use the class's methods and attributes. 
  17878.  
  17879.  
  17880. ΓòÉΓòÉΓòÉ 13.42. encoder/decoder ΓòÉΓòÉΓòÉ
  17881.  
  17882. encoder/decoder 
  17883.  
  17884. In the Persistence Framework, a class that knows how to read/write the 
  17885. persistent object format of a persistent object. Every persistent object is 
  17886. associated with an Encoder/Decoder, and an encoder/decoder object is created 
  17887. for each attribute and instance variable. An Encoder/Decoder is supplied by the 
  17888. Persistence Framework by default, or an application can define its own. 
  17889.  
  17890.  
  17891. ΓòÉΓòÉΓòÉ 13.43. entry class ΓòÉΓòÉΓòÉ
  17892.  
  17893. entry class 
  17894.  
  17895. In the Emitter Framework, a class that represents some syntactic unit of an 
  17896. interface definition in the IDL source file. 
  17897.  
  17898.  
  17899. ΓòÉΓòÉΓòÉ 13.44. Environment parameter ΓòÉΓòÉΓòÉ
  17900.  
  17901. Environment parameter 
  17902.  
  17903. A CORBA-required parameter in all method procedures, it represents a memory 
  17904. location where exception information can be returned by the object of a method 
  17905. invocation. [Certain methods are exempt (when the class contains a modifier of 
  17906. callstyle=oidl), to maintain upward compatibility for client programs written 
  17907. using an earlier release.] 
  17908.  
  17909.  
  17910. ΓòÉΓòÉΓòÉ 13.45. emitter ΓòÉΓòÉΓòÉ
  17911.  
  17912. emitter 
  17913.  
  17914. Generically, a program that takes the output from one system and converts the 
  17915. information into a different form. Using the Emitter Framework, selected output 
  17916. from the SOM Compiler (describing each syntactic unit in an IDL source file) is 
  17917. transformed and formatted according to a user-defined template. Example emitter 
  17918. output, besides the implementation template and language bindings, might 
  17919. include reference documentation, class browser descriptions, or "pretty" 
  17920. printouts. 
  17921.  
  17922.  
  17923. ΓòÉΓòÉΓòÉ 13.46. event ΓòÉΓòÉΓòÉ
  17924.  
  17925. event 
  17926.  
  17927. The occurrence of a condition, or the beginning or ending of an activity that 
  17928. is of interest to an application. Examples are elapse of a time interval, 
  17929. sending or receiving of a message, and opening or closing a file. (See also 
  17930. event manager and callback.) 
  17931.  
  17932.  
  17933. ΓòÉΓòÉΓòÉ 13.47. event manager (EMan) ΓòÉΓòÉΓòÉ
  17934.  
  17935. event manager (EMan) 
  17936.  
  17937. The chief component of the Event Management Framework that registers interest 
  17938. in various events from calling modules and informs them through callbacks when 
  17939. those events occur. 
  17940.  
  17941.  
  17942. ΓòÉΓòÉΓòÉ 13.48. factory method ΓòÉΓòÉΓòÉ
  17943.  
  17944. factory method 
  17945.  
  17946. See class method. 
  17947.  
  17948.  
  17949. ΓòÉΓòÉΓòÉ 13.49. ID: ΓòÉΓòÉΓòÉ
  17950.  
  17951. ID: 
  17952.  
  17953. See somId. 
  17954.  
  17955.  
  17956. ΓòÉΓòÉΓòÉ 13.50. IDL source file ΓòÉΓòÉΓòÉ
  17957.  
  17958. IDL source file 
  17959.  
  17960. A user-written .idl file, expressed using the syntax of the Interface 
  17961. Definition Language (IDL), which describes the interface for a particular class 
  17962. (or classes, for a module). The IDL source file is processed by the SOM 
  17963. Compiler to generate the binding files specific to the programming languages of 
  17964. the class implementor and the client application. (This file may also be called 
  17965. the "IDL file," the "source file," or the "interface definition file.") 
  17966.  
  17967.  
  17968. ΓòÉΓòÉΓòÉ 13.51. implementation ΓòÉΓòÉΓòÉ
  17969.  
  17970. implementation 
  17971.  
  17972. (Or object implementation.) The specification of what instance variables 
  17973. implement an object's state and what procedures implement its methods (or 
  17974. behaviors). In DSOM, a remote object's implementation is also characterized by 
  17975. its server implementation (a program). 
  17976.  
  17977.  
  17978. ΓòÉΓòÉΓòÉ 13.52. Implementation Repository ΓòÉΓòÉΓòÉ
  17979.  
  17980. Implementation Repository 
  17981.  
  17982. A database used by DSOM to store the implementation definitions of DSOM 
  17983. servers. 
  17984.  
  17985.  
  17986. ΓòÉΓòÉΓòÉ 13.53. implementation statement ΓòÉΓòÉΓòÉ
  17987.  
  17988. implementation statement 
  17989.  
  17990. An optional declaration within the body of the interface  definition of a class 
  17991. in a SOM IDL source file, specifying information about how the class will be 
  17992. implemented (such as, version numbers for the class, overriding of inherited 
  17993. methods, or type of method resolution to be supported by particular methods). 
  17994. This statement is a SOM-unique statement; thus, it must be preceded by the term 
  17995. "#ifdef __SOMIDL__" and followed by "#endif". See also interface declaration. 
  17996.  
  17997.  
  17998. ΓòÉΓòÉΓòÉ 13.54. implementation template ΓòÉΓòÉΓòÉ
  17999.  
  18000. implementation template 
  18001.  
  18002. A template file containing stub procedures for  methods that a class introduces 
  18003. or overrides. The implementation template is one of the binding files generated 
  18004. by the SOM Compiler when it processes the IDL source file containing class 
  18005. interface declarations. The class implementor then customizes the 
  18006. implementation, by adding language-specific code to the method procedures. 
  18007.  
  18008.  
  18009. ΓòÉΓòÉΓòÉ 13.55. implicit method parameter ΓòÉΓòÉΓòÉ
  18010.  
  18011. implicit method parameter 
  18012.  
  18013. A method parameter that is not included in the IDL interface specification of a 
  18014. method, but which is a parameter of the method's procedure and which is 
  18015. required when the method is invoked from a client program. Implicit parameters 
  18016. include the required Environment parameter indicating where exception 
  18017. information can be returned, as well as a Context parameter, if needed. 
  18018.  
  18019.  
  18020. ΓòÉΓòÉΓòÉ 13.56. incremental update ΓòÉΓòÉΓòÉ
  18021.  
  18022. incremental update 
  18023.  
  18024. A revision to an implementation template file that results from reprocessing of 
  18025. the IDL source file by the SOM Compiler. The updated implementation file will 
  18026. contain new stub procedures, added comments, and revised method prototypes 
  18027. reflecting changes made to the method definitions in the IDL specification. 
  18028. Importantly, these updates do not disturb existing code that the class 
  18029. implementor has defined for the prior method procedures. 
  18030.  
  18031.  
  18032. ΓòÉΓòÉΓòÉ 13.57. inheritance ΓòÉΓòÉΓòÉ
  18033.  
  18034. inheritance 
  18035.  
  18036. The technique of defining one class (called a subclass, derived class, or child 
  18037. class) as incremental differences from another class (called the  parent class, 
  18038. base class, superclass, or ancestor class). From its parents, the subclass 
  18039. inherits variables and methods for its instances. The subclass can also provide 
  18040. additional instance variables and methods. Furthermore, the subclass can 
  18041. provide new procedures for implementing inherited methods. The subclass is then 
  18042. said to override the parent class's methods. An overriding method procedure can 
  18043. elect to call the parent class's method procedure. (Such a call is known as a 
  18044. parent method call.) 
  18045.  
  18046.  
  18047. ΓòÉΓòÉΓòÉ 13.58. inheritance hierarchy ΓòÉΓòÉΓòÉ
  18048.  
  18049. inheritance hierarchy 
  18050.  
  18051. The sequential relationship from a root class to a subclass, through which the 
  18052. subclass inherits instance methods, attributes, and  instance variables from 
  18053. all of its ancestors, either directly or indirectly. The root class of all SOM 
  18054. classes is SOMObject. 
  18055.  
  18056.  
  18057. ΓòÉΓòÉΓòÉ 13.59. instance ΓòÉΓòÉΓòÉ
  18058.  
  18059. instance 
  18060.  
  18061. (Or object instance or just object.) A specific object, as distinguished from a 
  18062. class of objects. See also object. 
  18063.  
  18064.  
  18065. ΓòÉΓòÉΓòÉ 13.60. instance method ΓòÉΓòÉΓòÉ
  18066.  
  18067. instance method 
  18068.  
  18069. A method valid for an object instance (as opposed to a class method, which is 
  18070. valid for a class object). An instance method that an object responds to is 
  18071. defined by its class or inherited from an ancestor class. 
  18072.  
  18073.  
  18074. ΓòÉΓòÉΓòÉ 13.61. instance token ΓòÉΓòÉΓòÉ
  18075.  
  18076. instance token 
  18077.  
  18078. A data token that identifies the first instance variable among those introduced 
  18079. by a given class. The somGetInstanceToken method invoked on a class object 
  18080. returns that class's instance token. 
  18081.  
  18082.  
  18083. ΓòÉΓòÉΓòÉ 13.62. instance variables ΓòÉΓòÉΓòÉ
  18084.  
  18085. instance variables 
  18086.  
  18087. (Or, instance data.) Variables declared for use within the method procedures of 
  18088. a class. An instance variable is declared within the body of the implementation 
  18089. statement in a SOM IDL source file. An instance variable is "private" to the 
  18090. class and should not be accessed by a client program. (Contrast an instance 
  18091. variable with an attribute.) 
  18092.  
  18093.  
  18094. ΓòÉΓòÉΓòÉ 13.63. interface ΓòÉΓòÉΓòÉ
  18095.  
  18096. interface 
  18097.  
  18098. The information that a client must know to use a class  namely, the names of 
  18099. its attributes and the signatures of its methods . The interface is described 
  18100. in a formal language (the Interface Definition Language, IDL) that is 
  18101. independent of the programming language used to implement the class's methods. 
  18102.  
  18103.  
  18104. ΓòÉΓòÉΓòÉ 13.64. interface declaration ΓòÉΓòÉΓòÉ
  18105.  
  18106. interface declaration 
  18107.  
  18108. (Or interface statement.) The statement in the IDL source file that specifies 
  18109. the name of a new class and the names of its parent class(es). The "body" of 
  18110. the interface declaration defines the signature of each new method and any 
  18111. attribute(s) associated with the class. In SOM IDL, the body may also include 
  18112. an implementation statement (where instance variables are declared or a 
  18113. modifier is specified, for example to overridea method). 
  18114.  
  18115.  
  18116. ΓòÉΓòÉΓòÉ 13.65. Interface Definition Language (IDL) ΓòÉΓòÉΓòÉ
  18117.  
  18118. Interface Definition Language (IDL) 
  18119.  
  18120. The formal language (independent of any programming language) by which the 
  18121. interface for a class of objects is defined in a .idl file, which the SOM 
  18122. Compiler then interprets to create an implementation template file and binding 
  18123. files. SOM's Interface Definition Language is fully compliant with standards 
  18124. established by the Object Management Group's Common Object Request Broker 
  18125. Architecture (CORBA). 
  18126.  
  18127.  
  18128. ΓòÉΓòÉΓòÉ 13.66. Interface Repository (IR) ΓòÉΓòÉΓòÉ
  18129.  
  18130. Interface Repository (IR) 
  18131.  
  18132. The database that SOM optionally creates to provide persistent storage of 
  18133. objects representing the major elements of interface definitions. Creation and 
  18134. maintenance of the IR is based on information supplied in the IDL source file. 
  18135. The SOM IR Framework supports all interfaces described in the CORBA standard. 
  18136.  
  18137.  
  18138. ΓòÉΓòÉΓòÉ 13.67. Interface Repository Framework ΓòÉΓòÉΓòÉ
  18139.  
  18140. Interface Repository Framework 
  18141.  
  18142. A set of classes that provide methods whereby executing programs can access the 
  18143. persistent objects of the Interface Repository to discover everything known 
  18144. about the programming interfaces of SOM classes. 
  18145.  
  18146.  
  18147. ΓòÉΓòÉΓòÉ 13.68. IR ΓòÉΓòÉΓòÉ
  18148.  
  18149. IR 
  18150.  
  18151. Abbreviation for Interface Repository. 
  18152.  
  18153.  
  18154. ΓòÉΓòÉΓòÉ 13.69. location services daemon (somdd) ΓòÉΓòÉΓòÉ
  18155.  
  18156. location services daemon (somdd) 
  18157.  
  18158. A process whose primary purpose is to give DSOM clients the communications 
  18159. information that they need to connect with an implementation server. 
  18160.  
  18161.  
  18162. ΓòÉΓòÉΓòÉ 13.70. macro ΓòÉΓòÉΓòÉ
  18163.  
  18164. macro 
  18165.  
  18166. An alias for executing a sequence of hidden instructions; in SOM, typically the 
  18167. means of executing a command known within a binding file created by the SOM 
  18168. Compiler. 
  18169.  
  18170.  
  18171. ΓòÉΓòÉΓòÉ 13.71. metaclass ΓòÉΓòÉΓòÉ
  18172.  
  18173. metaclass 
  18174.  
  18175. A class whose instances are classes. In SOM, any class descended from SOMClass 
  18176. is a metaclass. The methods a class inherits from its metaclass are sometimes 
  18177. called class methods (in Smalltalk) or factory methods (in Objective-C) or 
  18178. constructors. See also class method. 
  18179.  
  18180.  
  18181. ΓòÉΓòÉΓòÉ 13.72. metaclass incompatibility ΓòÉΓòÉΓòÉ
  18182.  
  18183. metaclass incompatibility 
  18184.  
  18185. A situation where a subclass does not include all of the class variables or 
  18186. respond to all of the class methods of its ancestor classes. This situation can 
  18187. easily arise in OOP systems that allow programmers to explicitly specify 
  18188. metaclasses, but is not allowed to occur in SOM. Instead, SOM automatically 
  18189. prevents this by creating and using derived metaclasses whenever necessary. 
  18190.  
  18191.  
  18192. ΓòÉΓòÉΓòÉ 13.73. method ΓòÉΓòÉΓòÉ
  18193.  
  18194. method 
  18195.  
  18196. A combination of a procedure and a name, such that many different procedures 
  18197. can be associated with the same name. In object-oriented programming, invoking 
  18198. a method on an object causes the object to execute a specific method procedure. 
  18199. The process of determining which method procedure to execute when a method is 
  18200. invoked on an object is called method resolution. (The CORBA standard uses the 
  18201. term "operation" for method invocation). SOM supports two different kinds of 
  18202. methods: static methods and dynamic methods. See also static method and dynamic 
  18203. method. 
  18204.  
  18205.  
  18206. ΓòÉΓòÉΓòÉ 13.74. method descriptor ΓòÉΓòÉΓòÉ
  18207.  
  18208. method descriptor 
  18209.  
  18210. See descriptor. 
  18211.  
  18212.  
  18213. ΓòÉΓòÉΓòÉ 13.75. method ID ΓòÉΓòÉΓòÉ
  18214.  
  18215. method ID 
  18216.  
  18217. A number representing a zero-terminated string by which SOM uniquely represents 
  18218. a method name. See also somId. 
  18219.  
  18220.  
  18221. ΓòÉΓòÉΓòÉ 13.76. method pointer ΓòÉΓòÉΓòÉ
  18222.  
  18223. method pointer 
  18224.  
  18225. A pointer type that identifies one method procedure on a single class. Method 
  18226. pointers are not ensured to be persistent among multiple processes. 
  18227.  
  18228.  
  18229. ΓòÉΓòÉΓòÉ 13.77. method procedure ΓòÉΓòÉΓòÉ
  18230.  
  18231. method procedure 
  18232.  
  18233. A function or procedure, written in an arbitrary programming language, that 
  18234. implements a method of a class. A method procedure is defined by the class 
  18235. implementor within the implementation template file generated by the SOM 
  18236. Compiler. 
  18237.  
  18238.  
  18239. ΓòÉΓòÉΓòÉ 13.78. method prototype ΓòÉΓòÉΓòÉ
  18240.  
  18241. method prototype 
  18242.  
  18243. A method declaration that includes the types of the arguments. Based on method 
  18244. definitions in an IDL source file, the SOM Compiler generates method prototypes 
  18245. in the implementation template. A class implementor uses the method prototype 
  18246. as a basis for writing the corresponding method procedurecode. The method 
  18247. prototype also shows all arguments and their types that are required to invoke 
  18248. the method from a client program. 
  18249.  
  18250.  
  18251. ΓòÉΓòÉΓòÉ 13.79. method resolution ΓòÉΓòÉΓòÉ
  18252.  
  18253. method resolution 
  18254.  
  18255. The process of selecting a particular method procedure, given a method name and 
  18256. an object instance. The process results in selecting the particular 
  18257. function/procedure that implements the abstract method in a way appropriate for 
  18258. the designated object. SOM supports a variety of method-resolution mechanisms, 
  18259. including offset method resolution, name-lookup resolution, and 
  18260. dispatch-function resolution. 
  18261.  
  18262.  
  18263. ΓòÉΓòÉΓòÉ 13.80. method table ΓòÉΓòÉΓòÉ
  18264.  
  18265. method table 
  18266.  
  18267. A table of pointers to the  method procedures that implement the methods that 
  18268. an object supports. See also method token. 
  18269.  
  18270.  
  18271. ΓòÉΓòÉΓòÉ 13.81. method token ΓòÉΓòÉΓòÉ
  18272.  
  18273. method token 
  18274.  
  18275. A value that identifies a specific method introduced by a class. A method token 
  18276. is used during method resolution to locate the method procedure that implements 
  18277. the identified method. The two basic method-resolution procedures are 
  18278. somResolve (which takes as arguments an object and a method token, and returns 
  18279. a pointer to a procedure that implements the identified method on the given 
  18280. object) and somClassResolve (which takes as arguments a class and a method 
  18281. token, and returns a pointer to a procedure that implements the identified 
  18282. method on an instance of the given class). 
  18283.  
  18284.  
  18285. ΓòÉΓòÉΓòÉ 13.82. modifier ΓòÉΓòÉΓòÉ
  18286.  
  18287. modifier 
  18288.  
  18289. Any of a set of statements that control how a class, an attribute, or a method 
  18290. will be implemented. Modifiers can be defined in the implementation statement 
  18291. of a SOM IDL source file. The implementation statement is a SOM-unique 
  18292. extension of the CORBA specification. [User-defined modifiers can also be 
  18293. specified for use by user-written emitters or to store information in the 
  18294. Interface Repository, which can then be accessed via methods provided by the 
  18295. Interface Repository Framework.] 
  18296.  
  18297.  
  18298. ΓòÉΓòÉΓòÉ 13.83. module ΓòÉΓòÉΓòÉ
  18299.  
  18300. module 
  18301.  
  18302. The organizational structure required within an IDL source file that contains 
  18303. interface declarations for two (or more) classes that are not a class-metaclass 
  18304. pair. Such interfaces must be grouped within a module declaration. 
  18305.  
  18306.  
  18307. ΓòÉΓòÉΓòÉ 13.84. multiple inheritance ΓòÉΓòÉΓòÉ
  18308.  
  18309. multiple inheritance 
  18310.  
  18311. The situation in which a class is derived from (and inherits interface and 
  18312. implementation from) multiple parent classes. 
  18313.  
  18314.  
  18315. ΓòÉΓòÉΓòÉ 13.85. name-lookup method resolution ΓòÉΓòÉΓòÉ
  18316.  
  18317. name-lookup method resolution 
  18318.  
  18319. Similar to the method resolution techniques employed by Objective-C and 
  18320. Smalltalk. It is significantly slower than offset resolution. Name-lookup 
  18321. resolution, unlike offset resolution, can be used when the name of the method 
  18322. to be invoked is not known until run time, or the method is added to the class 
  18323. interface at run time, or the name of the class introducing the method is not 
  18324. known until run time. 
  18325.  
  18326.  
  18327. ΓòÉΓòÉΓòÉ 13.86. naming scope: ΓòÉΓòÉΓòÉ
  18328.  
  18329. naming scope: 
  18330.  
  18331. See scope. 
  18332.  
  18333.  
  18334. ΓòÉΓòÉΓòÉ 13.87. object ΓòÉΓòÉΓòÉ
  18335.  
  18336. object 
  18337.  
  18338. (Or object instance  or just instance.) An entity that has state (its data 
  18339. values) and behavior (its methods). An object is one of the elements of data 
  18340. and function that programs create, manipulate, pass as arguments, and so forth. 
  18341. An object is a way to encapsulate state and behavior. Encapsulation permits 
  18342. many aspects of the implementation of an object to change without affecting 
  18343. client programs that depend on the object's behavior. In SOM, objects are 
  18344. created by other objects called classes. 
  18345.  
  18346.  
  18347. ΓòÉΓòÉΓòÉ 13.88. object adapter (OA) ΓòÉΓòÉΓòÉ
  18348.  
  18349. object adapter (OA) 
  18350.  
  18351. A CORBA term denoting the primary interface a server implementation uses to 
  18352. access ORB functions; in particular, it defines the mechanisms that a server 
  18353. uses to interact with DSOM, and vice versa. This includes server 
  18354. activation/deactivation, dispatching of methods, and authentication of the 
  18355. principal making a call. The basic object adapter described by CORBA is defined 
  18356. by the BOA (basic object adapter) abstract class; DSOM's primary object adapter 
  18357. implementation is provided by the SOMOA (SOM Object Adapter) class. 
  18358.  
  18359.  
  18360. ΓòÉΓòÉΓòÉ 13.89. object definition ΓòÉΓòÉΓòÉ
  18361.  
  18362. object definition 
  18363.  
  18364. See class. 
  18365.  
  18366.  
  18367. ΓòÉΓòÉΓòÉ 13.90. object implementation ΓòÉΓòÉΓòÉ
  18368.  
  18369. object implementation 
  18370.  
  18371. See implementation. 
  18372.  
  18373.  
  18374. ΓòÉΓòÉΓòÉ 13.91. object instance ΓòÉΓòÉΓòÉ
  18375.  
  18376. object instance 
  18377.  
  18378. See instance and object. 
  18379.  
  18380.  
  18381. ΓòÉΓòÉΓòÉ 13.92. object reference ΓòÉΓòÉΓòÉ
  18382.  
  18383. object reference 
  18384.  
  18385. A CORBA term denoting the information needed to reliably identify a particular 
  18386. object. This concept is implemented in DSOM with a proxy object in a client 
  18387. process, or a SOMDObject in a server process. See also proxy object and 
  18388. SOMDObject. 
  18389.  
  18390.  
  18391. ΓòÉΓòÉΓòÉ 13.93. object request broker (ORB) ΓòÉΓòÉΓòÉ
  18392.  
  18393. object request broker (ORB) 
  18394.  
  18395. See ORB. 
  18396.  
  18397.  
  18398. ΓòÉΓòÉΓòÉ 13.94. offset method resolution: ΓòÉΓòÉΓòÉ
  18399.  
  18400. offset method resolution: 
  18401.  
  18402. The default mechanism for performing method resolution in SOM, because it is 
  18403. the fastest (nearly as fast as an ordinary procedure call). It is roughly 
  18404. equivalent to the C ++ "virtual function" concept.  Using offset method 
  18405. resolution requires that the name of the method to be invoked must be known at 
  18406. compile time, the name of the class that introduces the method must be known at 
  18407. compile time (although not necessarily by the programmer), and the method to be 
  18408. invoked must be a static method. 
  18409.  
  18410.  
  18411. ΓòÉΓòÉΓòÉ 13.95. OIDL ΓòÉΓòÉΓòÉ
  18412.  
  18413. OIDL 
  18414.  
  18415. The original language used for declaring SOM classes. The acronym stands for 
  18416. Object Interface Definition Language. OIDL is still supported by SOM release 2, 
  18417. but it does not include the ability to specify multiple inheritance classes. 
  18418.  
  18419.  
  18420. ΓòÉΓòÉΓòÉ 13.96. one-copy serializable ΓòÉΓòÉΓòÉ
  18421.  
  18422. one-copy serializable 
  18423.  
  18424. The consistency property of the Replication Framework which states that the 
  18425. concurrent execution of methods on a replicated object is equivalent to the 
  18426. serial execution of those same methods on a nonreplicated object. 
  18427.  
  18428.  
  18429. ΓòÉΓòÉΓòÉ 13.97. OOP ΓòÉΓòÉΓòÉ
  18430.  
  18431. OOP 
  18432.  
  18433. An acronym for "object-oriented programming." 
  18434.  
  18435.  
  18436. ΓòÉΓòÉΓòÉ 13.98. operation ΓòÉΓòÉΓòÉ
  18437.  
  18438. operation 
  18439.  
  18440. See method. 
  18441.  
  18442.  
  18443. ΓòÉΓòÉΓòÉ 13.99. operation logging ΓòÉΓòÉΓòÉ
  18444.  
  18445. operation logging 
  18446.  
  18447. In the Replication Framework, a technique for maintaining consistency among 
  18448. replicas of a replicated object, whereby the execution of a method that updates 
  18449. the object is repeated at the site of each replica. 
  18450.  
  18451.  
  18452. ΓòÉΓòÉΓòÉ 13.100. ORB (object request broker) ΓòÉΓòÉΓòÉ
  18453.  
  18454. ORB (object request broker) 
  18455.  
  18456. A CORBA term designating the means by which objects transparently make requests 
  18457. (that is, invoke methods) and receive responses from objects, whether they are 
  18458. local or remote. With SOMobjects Developer Toolkit and Runtimes, this 
  18459. functionality is implemented in the DSOM Framework. Thus, the DSOM (Distributed 
  18460. SOM) system is an ORB. See also BOA (basic object adapter) class and SOMOA (SOM 
  18461. object adapter) class. 
  18462.  
  18463.  
  18464. ΓòÉΓòÉΓòÉ 13.101. overridden method ΓòÉΓòÉΓòÉ
  18465.  
  18466. overridden method 
  18467.  
  18468. A method defined by a parent class and reimplemented (redefined or overridden) 
  18469. in the current class. 
  18470.  
  18471.  
  18472. ΓòÉΓòÉΓòÉ 13.102. override ΓòÉΓòÉΓòÉ
  18473.  
  18474. override 
  18475.  
  18476. (Or overriding method.) The technique by which a class replaces (redefines) the 
  18477. implementation of a method that it inherits from one of its parent classes. An 
  18478. overriding method can elect to call the parent class's method procedure as part 
  18479. of its own implementation. (Such a call is known as a parent method call.) 
  18480.  
  18481.  
  18482. ΓòÉΓòÉΓòÉ 13.103. parent class ΓòÉΓòÉΓòÉ
  18483.  
  18484. parent class 
  18485.  
  18486. A class from which another class inherits instance methods, attributes, and 
  18487. instance variables. A parent class is sometimes called a base class or 
  18488. superclass. 
  18489.  
  18490.  
  18491. ΓòÉΓòÉΓòÉ 13.104. parent method call ΓòÉΓòÉΓòÉ
  18492.  
  18493. parent method call 
  18494.  
  18495. A technique where an overriding method calls the method procedure of its parent 
  18496. class as part of its own implementation. 
  18497.  
  18498.  
  18499. ΓòÉΓòÉΓòÉ 13.105. persistent object ΓòÉΓòÉΓòÉ
  18500.  
  18501. persistent object 
  18502.  
  18503. An object whose state can be preserved beyond the termination of the process 
  18504. that created it. Typically, such objects are stored in files. 
  18505.  
  18506.  
  18507. ΓòÉΓòÉΓòÉ 13.106. polymorphism ΓòÉΓòÉΓòÉ
  18508.  
  18509. polymorphism 
  18510.  
  18511. An object-oriented programming feature that may take on different meanings in 
  18512. different systems. Under various definitions of polymorphism, (a) a method or 
  18513. procedure call can be executed using arguments of a variety of types, or (b) 
  18514. the same variable can assume values of different types at different times, or 
  18515. (c) a method name can denote more than one method procedure.  The SOM system 
  18516. reflects the third definition (for example, when a SOM class overrides a parent 
  18517. class definition of a method to change its behavior). The term literally means 
  18518. "having many forms." 
  18519.  
  18520.  
  18521. ΓòÉΓòÉΓòÉ 13.107. principal ΓòÉΓòÉΓòÉ
  18522.  
  18523. principal 
  18524.  
  18525. The user on whose behalf a particular (remote) method call is being performed. 
  18526.  
  18527.  
  18528. ΓòÉΓòÉΓòÉ 13.108. procedure ΓòÉΓòÉΓòÉ
  18529.  
  18530. procedure 
  18531.  
  18532. A small section of code that executes a limited, well-understood task when 
  18533. called from another program. In SOM, a method procedure is often referred to as 
  18534. a procedure. See also method procedure. 
  18535.  
  18536.  
  18537. ΓòÉΓòÉΓòÉ 13.109. process ΓòÉΓòÉΓòÉ
  18538.  
  18539. process 
  18540.  
  18541. A series of instructions (a program or part of a program) that a computer 
  18542. executes in a multitasking environment. 
  18543.  
  18544.  
  18545. ΓòÉΓòÉΓòÉ 13.110. proxy object ΓòÉΓòÉΓòÉ
  18546.  
  18547. proxy object 
  18548.  
  18549. In DSOM, a SOM object in the client's address space that represents a remote 
  18550. object. The proxy object has the same interface  as the remote object, but each 
  18551. method invoked on the proxy is overridden by a dispatch method that forwards 
  18552. the invocation request to the remote object. Under DSOM, a proxy object is 
  18553. created dynamically and automatically in the client whenever a remote method 
  18554. returns a pointer to an object that happens to be remote. 
  18555.  
  18556.  
  18557. ΓòÉΓòÉΓòÉ 13.111. readers and writers ΓòÉΓòÉΓòÉ
  18558.  
  18559. readers and writers 
  18560.  
  18561. In the Replication Framework, different processes can access the same 
  18562. replicated object in different modes. A "reader" is a process that does not 
  18563. intend to update the object, but wants to continually watch the object as other 
  18564. processes update it. A "writer" is a process that wants to update the object, 
  18565. as well as continually watch the updates performed by others. 
  18566.  
  18567.  
  18568. ΓòÉΓòÉΓòÉ 13.112. receiver ΓòÉΓòÉΓòÉ
  18569.  
  18570. receiver 
  18571.  
  18572. See target object. 
  18573.  
  18574.  
  18575. ΓòÉΓòÉΓòÉ 13.113. redispatch stub ΓòÉΓòÉΓòÉ
  18576.  
  18577. redispatch stub 
  18578.  
  18579. A procedure, corresponding to a particular method, which has the same signature 
  18580. as the method's procedure but which invokes somDispatch to dispatch the method. 
  18581. The somOverrideMtab method can be used to replace the procedure pointers in a 
  18582. class's method table with the corresponding redispatch stubs. This is done when 
  18583. overriding somDispatch to customize method resolution so that all static method 
  18584. invocations will be routed through somDispatch for selection of an appropriate 
  18585. method procedure. (Dynamic methods have no entries in the method table, so they 
  18586. cannot be supported with redispatch functionality.) 
  18587.  
  18588.  
  18589. ΓòÉΓòÉΓòÉ 13.114. reference data ΓòÉΓòÉΓòÉ
  18590.  
  18591. reference data 
  18592.  
  18593. Application-specific data that a server uses to identify or describe an object 
  18594. in DSOM. The data, represented by a sequence of up to 1024 bytes, is registered 
  18595. with DSOM when a server creates an object reference. A server can later ask 
  18596. DSOM to return the reference data associated with an object reference. See also 
  18597. object reference. 
  18598.  
  18599.  
  18600. ΓòÉΓòÉΓòÉ 13.115. replica ΓòÉΓòÉΓòÉ
  18601.  
  18602. replica 
  18603.  
  18604. When an object is replicated among a set of processes (using the Replication 
  18605. Framework), each process is said to have a replica of the object. From the view 
  18606. point of any application model, the replicas together represent a single 
  18607. object. 
  18608.  
  18609.  
  18610. ΓòÉΓòÉΓòÉ 13.116. replicated object ΓòÉΓòÉΓòÉ
  18611.  
  18612. replicated object 
  18613.  
  18614. An object for which replicas (copies) exist.  See replica. 
  18615.  
  18616.  
  18617. ΓòÉΓòÉΓòÉ 13.117. run-time environment ΓòÉΓòÉΓòÉ
  18618.  
  18619. run-time environment 
  18620.  
  18621. The data structures, objects, and global variables that are created, 
  18622. maintained, and used by the functions, procedures, and methods in the SOM 
  18623. run-time library. 
  18624.  
  18625.  
  18626. ΓòÉΓòÉΓòÉ 13.118. scope ΓòÉΓòÉΓòÉ
  18627.  
  18628. scope 
  18629.  
  18630. (Or naming scope.) That portion of a program within which an identifier name 
  18631. has "visibility" and denotes a unique variable. In SOM, an IDL source file 
  18632. forms a scope. An identifier can only be defined once within a scope; 
  18633. identifiers can be redefined within a nested scope. In a .idl file, modules, 
  18634. interface statements, structures, unions, methods, and exceptions form nested 
  18635. scopes. 
  18636.  
  18637.  
  18638. ΓòÉΓòÉΓòÉ 13.119. serializable ΓòÉΓòÉΓòÉ
  18639.  
  18640. serializable 
  18641.  
  18642. See one-copy serializable. 
  18643.  
  18644.  
  18645. ΓòÉΓòÉΓòÉ 13.120. server ΓòÉΓòÉΓòÉ
  18646.  
  18647. server 
  18648.  
  18649. (Or server implementation.) In DSOM, a process, running in a distributed 
  18650. environment, that executes the implementation of an  object. DSOM provides a 
  18651. default server implementation that can dynamically load SOM class libraries, 
  18652. create SOM objects, and make those objects accessible to clients. Developers 
  18653. can also write application-specific servers for use with DSOM. 
  18654.  
  18655.  
  18656. ΓòÉΓòÉΓòÉ 13.121. server object ΓòÉΓòÉΓòÉ
  18657.  
  18658. server object 
  18659.  
  18660. In DSOM, every server has an object that defines methods for managing objects 
  18661. in that server. These methods include object creation, object destruction, and 
  18662. maintaining mappings between object references and the objects they reference. 
  18663. A server object must be an instance of the class SOMDServer (or one of its 
  18664. subclasses). See also object reference and SOMDObject. 
  18665.  
  18666.  
  18667. ΓòÉΓòÉΓòÉ 13.122. shadowing ΓòÉΓòÉΓòÉ
  18668.  
  18669. shadowing 
  18670.  
  18671. In the Emitter Framework, a technique that is required when any of the entry 
  18672. classes are subclassed. Shadowing causes instances of the new subclass(es) 
  18673. (rather than instances of the original entry classes) to be used as input for 
  18674. building the object graph, without requiring a recompile of emitter framework 
  18675. code. Shadowing is accomplished by using the macro SOM_SubstituteClass. 
  18676.  
  18677.  
  18678. ΓòÉΓòÉΓòÉ 13.123. signature ΓòÉΓòÉΓòÉ
  18679.  
  18680. signature 
  18681.  
  18682. The collection of types associated with a method (the type of its return value, 
  18683. if any, as well as the number, order, and type of each of its arguments). 
  18684.  
  18685.  
  18686. ΓòÉΓòÉΓòÉ 13.124. sister class object ΓòÉΓòÉΓòÉ
  18687.  
  18688. sister class object 
  18689.  
  18690. A duplicate of a class object that is created in order to save a copy of the 
  18691. class's original method table before replacing the method table to customize 
  18692. method resolution. The sister class object is created so that some original 
  18693. method procedures can be called by the replacement method procedures. 
  18694.  
  18695.  
  18696. ΓòÉΓòÉΓòÉ 13.125. Sockets class ΓòÉΓòÉΓòÉ
  18697.  
  18698. Sockets class 
  18699.  
  18700. A class that provides a common communications interface to Distributed SOM, the 
  18701. Replication Framework, and the Event Management Framework. The Sockets class 
  18702. provides the base interfaces (patterned after TCP/IP sockets); the subclasses 
  18703. TCPIPSockets, NBSockets, and IPXSockets provide actual implementations for 
  18704. TCP/IP, Netbios, and Netware IPX/SPX, respectively. 
  18705.  
  18706.  
  18707. ΓòÉΓòÉΓòÉ 13.126. SOM Compiler ΓòÉΓòÉΓòÉ
  18708.  
  18709. SOM Compiler 
  18710.  
  18711. A tool provided by the SOM Toolkit that takes as input the interface definition 
  18712. file for a class (the .idl file) and produces a set of binding files that make 
  18713. it more convenient to implement and use SOM classes. 
  18714.  
  18715.  
  18716. ΓòÉΓòÉΓòÉ 13.127. SOMClass ΓòÉΓòÉΓòÉ
  18717.  
  18718. SOMClass 
  18719.  
  18720. One of the three primitive class objects of the SOM run-time environment. 
  18721. SOMClass is the root (meta)class from which all subsequent metaclasses are 
  18722. derived. SOMClass defines the essential behavior common to all SOM class 
  18723. objects. 
  18724.  
  18725.  
  18726. ΓòÉΓòÉΓòÉ 13.128. SOMClassMgr ΓòÉΓòÉΓòÉ
  18727.  
  18728. SOMClassMgr 
  18729.  
  18730. One of the three primitive class objects of the SOM run-time environment. 
  18731. During SOM initialization, a single instance (object) of SOMClassMgr is 
  18732. created, called SOMClassMgrObject. This object maintains a directory of all SOM 
  18733. classes that exist within the current process, and it assists with dynamic 
  18734. loading and unloading of class libraries. 
  18735.  
  18736.  
  18737. ΓòÉΓòÉΓòÉ 13.129. SOM-derived metaclass: ΓòÉΓòÉΓòÉ
  18738.  
  18739. SOM-derived metaclass: 
  18740.  
  18741. See derived metaclass. 
  18742.  
  18743.  
  18744. ΓòÉΓòÉΓòÉ 13.130. SOMDObject ΓòÉΓòÉΓòÉ
  18745.  
  18746. SOMDObject 
  18747.  
  18748. The class that implements the notion of a CORBA "object reference" in DSOM. An 
  18749. instance of SOMDObject contains information about an object's server 
  18750. implementation and interface, as well as a user-supplied identifier. 
  18751.  
  18752.  
  18753. ΓòÉΓòÉΓòÉ 13.131. somId ΓòÉΓòÉΓòÉ
  18754.  
  18755. somId 
  18756.  
  18757. A pointer to a number that uniquely represents a zero-terminated string. Such 
  18758. pointers are declared as type somId. In SOM, somId's are used to represent 
  18759. method names, class names, and so forth. 
  18760.  
  18761.  
  18762. ΓòÉΓòÉΓòÉ 13.132. SOMObject ΓòÉΓòÉΓòÉ
  18763.  
  18764. SOMObject 
  18765.  
  18766. One of the three primitive class objects of the SOM run-time environment. 
  18767. SOMObject is the root class for all SOM (sub)classes. SOMObject defines the 
  18768. essential behavior common to all SOM objects. 
  18769.  
  18770.  
  18771. ΓòÉΓòÉΓòÉ 13.133. SOMOA (SOM object adapter) class ΓòÉΓòÉΓòÉ
  18772.  
  18773. SOMOA (SOM object adapter) class 
  18774.  
  18775. In DSOM, a class that dispatches methods on a server's objects, using the SOM 
  18776. Compiler and run-time support. The SOMOA class implements methods defined in 
  18777. the abstract BOA class (its base class). See also BOA class. 
  18778.  
  18779.  
  18780. ΓòÉΓòÉΓòÉ 13.134. somSelf ΓòÉΓòÉΓòÉ
  18781.  
  18782. somSelf 
  18783.  
  18784. Within method procedures  in the implementation file for a class, a parameter 
  18785. pointing to the target object that is an instance of the class being 
  18786. implemented.  it is local to the method procedure. 
  18787.  
  18788.  
  18789. ΓòÉΓòÉΓòÉ 13.135. somThis ΓòÉΓòÉΓòÉ
  18790.  
  18791. somThis 
  18792.  
  18793. Within method procedures, a local variable that points to a data structure 
  18794. containing the instance variables introduced by the class. If no instance 
  18795. variables are specified in the SOM IDL source file, then the somThis assignment 
  18796. statement is commented out by the SOM Compiler. 
  18797.  
  18798.  
  18799. ΓòÉΓòÉΓòÉ 13.136. state (of an object) ΓòÉΓòÉΓòÉ
  18800.  
  18801. state (of an object) 
  18802.  
  18803. The data (attributes, instance variables and their values) associated with an 
  18804. object. See also behavior. 
  18805.  
  18806.  
  18807. ΓòÉΓòÉΓòÉ 13.137. static method ΓòÉΓòÉΓòÉ
  18808.  
  18809. static method 
  18810.  
  18811. Any method that can be accessed through offset method resolution.  Any method 
  18812. declared in the IDL specification of a class is a static method. See also 
  18813. method and dynamic method. 
  18814.  
  18815.  
  18816. ΓòÉΓòÉΓòÉ 13.138. stub procedures ΓòÉΓòÉΓòÉ
  18817.  
  18818. stub procedures 
  18819.  
  18820. Method procedures in the implementation template generated by the SOM Compiler. 
  18821. They are procedures whose bodies are largely vacuous, to be filled in by the 
  18822. implementor. 
  18823.  
  18824.  
  18825. ΓòÉΓòÉΓòÉ 13.139. subclass ΓòÉΓòÉΓòÉ
  18826.  
  18827. subclass 
  18828.  
  18829. A class that inherits instance methods, attributes, and instance variables 
  18830. directly from another class, called the parent class, base class, superclass, 
  18831. or indirectly from an ancestor class. A subclass may also be called a child 
  18832. class or derived class. 
  18833.  
  18834.  
  18835. ΓòÉΓòÉΓòÉ 13.140. subclassing ΓòÉΓòÉΓòÉ
  18836.  
  18837. subclassing 
  18838.  
  18839. The process whereby a new class, as it is created (or derived), inherits 
  18840. instance methods, attributes, and instance variables from one or more 
  18841. previously defined ancestor classes. The immediate parent class(es) of a new 
  18842. class must be specified in the class's interface declaration. see also 
  18843. inheritance. 
  18844.  
  18845.  
  18846. ΓòÉΓòÉΓòÉ 13.141. superclass ΓòÉΓòÉΓòÉ
  18847.  
  18848. superclass 
  18849.  
  18850. See parent class. 
  18851.  
  18852.  
  18853. ΓòÉΓòÉΓòÉ 13.142. symbol ΓòÉΓòÉΓòÉ
  18854.  
  18855. symbol 
  18856.  
  18857. In the Emitter Framework, any of a (standard or user-defined) set of names 
  18858. (such as, className) that are used as placeholders when building a text 
  18859. template to pattern the desired emitter output. When a template is emitted, the 
  18860. symbols are replaced with their corresponding values from the emitter's symbol 
  18861. table. Other symbols (such as, classSN) have values that are used by 
  18862. section-emitting methods to identify major sections of the template (which are 
  18863. correspondingly labeled as "classS" or by a user-defined name). 
  18864.  
  18865.  
  18866. ΓòÉΓòÉΓòÉ 13.143. target object ΓòÉΓòÉΓòÉ
  18867.  
  18868. target object 
  18869.  
  18870. (Or receiver.) The object responding to a method call. The target object is 
  18871. always the first formal parameter of a method procedure. For SOM's C-language 
  18872. bindings, the target object is the first argument provided to the method 
  18873. invocation macro, _methodName. 
  18874.  
  18875.  
  18876. ΓòÉΓòÉΓòÉ 13.144. usage bindings ΓòÉΓòÉΓòÉ
  18877.  
  18878. usage bindings 
  18879.  
  18880. The language-specific binding files for a class that are generated by the SOM 
  18881. Compiler for inclusion in client programs using the class. 
  18882.  
  18883.  
  18884. ΓòÉΓòÉΓòÉ 13.145. value logging ΓòÉΓòÉΓòÉ
  18885.  
  18886. value logging 
  18887.  
  18888. In the Replication Framework, a technique for maintaining consistency among 
  18889. replicas of a replicated object, whereby the new value of the object is 
  18890. distributed after the execution of a method that updates the object. 
  18891.  
  18892.  
  18893. ΓòÉΓòÉΓòÉ 13.146. view-data paradigm ΓòÉΓòÉΓòÉ
  18894.  
  18895. view-data paradigm 
  18896.  
  18897. A Replication Framework construct similar to the Model-View-Controller paradigm 
  18898. in SmallTalk. The "view" object contains only presentation-specific 
  18899. information, while the "data" object contains the state of the application. The 
  18900. "view" and "data" are connected by means of an "observation" protocol that lets 
  18901. the "view" be notified whenever the "data" changes. 
  18902.  
  18903.  
  18904. ΓòÉΓòÉΓòÉ 13.147. writers ΓòÉΓòÉΓòÉ
  18905.  
  18906. writers 
  18907.  
  18908. See readers and writers. 
  18909.  
  18910.  
  18911. ΓòÉΓòÉΓòÉ 14. Bibliography ΓòÉΓòÉΓòÉ
  18912.  
  18913. This bibliography lists the publications that make up the IBM VisualAge for C++ 
  18914. library and related publications. The list of related publications is not 
  18915. exhaustive but should be adequate for most VisualAge for C++ users. 
  18916.  
  18917.  
  18918. ΓòÉΓòÉΓòÉ 14.1. The IBM VisualAge for C++ Library ΓòÉΓòÉΓòÉ
  18919.  
  18920. The following books are part of the IBM VisualAge for C++ library. 
  18921.  
  18922.      Installation Guide and Product Overview, S33H-5030 
  18923.  
  18924.      User's Guide, S33H-5031 
  18925.  
  18926.      Programming Guide, S33H-5032 
  18927.  
  18928.      Visual Builder User's Guide, S33H-5034 
  18929.  
  18930.      Visual Builder Parts Reference, S33H-5035 
  18931.  
  18932.      Building VisualAge for C++ Parts for Fun and Profit, S33H-5036 
  18933.  
  18934.      Open Class Library User's Guide, S33H-5033 
  18935.  
  18936.      Open Class Library Reference, S33H-5039 
  18937.  
  18938.      Language Reference, S33H-5037 
  18939.  
  18940.      C Library Reference, S33H-5038 
  18941.  
  18942.      SOM Programming Guide, S33H-5043 
  18943.  
  18944.      SOM Programming Reference, S33H-5044 
  18945.  
  18946.  
  18947. ΓòÉΓòÉΓòÉ 14.2. C and C++ Related Publications ΓòÉΓòÉΓòÉ
  18948.  
  18949.      Portability Guide for IBM C, SC09-1405 
  18950.  
  18951.      American National Standard for Information Systems / International 
  18952.       Standards Organization - Programming Language C (ANSI/ISO 
  18953.       9899-1990[1992]) 
  18954.  
  18955.  
  18956. ΓòÉΓòÉΓòÉ 14.2.1. Non-IBM Publications ΓòÉΓòÉΓòÉ
  18957.  
  18958. Many books have been written about the C++ language and related programming 
  18959. topics. The authors use varying approaches and emphasis. The following is a 
  18960. sample of some non-IBM C++ publications that are generally available.  This 
  18961. sample is not an exhaustive list.  IBM does not specifically recommend any of 
  18962. these books, and other C++ books may be available in your locality. 
  18963.  
  18964.      The Annotated C++ Reference Manual by Margaret A. Ellis and Bjarne 
  18965.       Stroustrup, Addison-Wesley Publishing Company. 
  18966.  
  18967.      C++ Primer by Stanley B. Lippman, Addison-Wesley Publishing Company. 
  18968.  
  18969.      Object-Oriented Design with Applications by Grady Booch, 
  18970.       Benjamin/Cummings. 
  18971.  
  18972.      Object-Oriented Programming Using SOM and DSOM by Christina Lau, Van 
  18973.       Nostrand Reinhold. 
  18974.