home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / VSCPPv4.zip / VACPP / IBMCPP / HELP / SOMGUIDE.INF (.txt) < prev    next >
OS/2 Help File  |  1995-03-14  |  590KB  |  21,215 lines

  1.  
  2. ΓòÉΓòÉΓòÉ 1. Notices ΓòÉΓòÉΓòÉ
  3.  
  4. Reference material for the classes, methods, functions, and macros provided by 
  5. the System Object Model and its accompanying frameworks. 
  6.  
  7. Note:  Before using this information and the product it supports, be sure to 
  8. read the trademark information under Trademarks. 
  9.  
  10. Second Edition (October 1994) 
  11.  
  12. The following paragraph does not apply to the United Kingdom or any country 
  13. where such provisions are inconsistent with local law: INTERNATIONAL BUSINESS 
  14. MACHINES CORPORATION PROVIDES THE PUBLICATION "AS IS" WITHOUT WARRANT OF ANY 
  15. KIND, EITHER EXPRESS OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 
  16. WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Some states 
  17. do not allow disclaimer of express or implied warranties in certain 
  18. transactions; therefore, this statement may not apply to you. 
  19.  
  20. This publication could include technical inaccuracies or typographical errors. 
  21. Changes are periodically made to the information herein; these changes will be 
  22. incorporated in new editions of the publication. IBM may make improvements 
  23. and/or changes in the product(s) and/or the program(s) described in this 
  24. publication at any time. 
  25.  
  26. It is possible that this publication may contain reference to, or information 
  27. about, IBM products (machines and programs), programming, or services that are 
  28. not announced in your country. Such references or information must not be 
  29. construed to mean that IBM intends to announce such IBM products, programming, 
  30. or services in your country. 
  31.  
  32. Requests for technical information about IBM products should be made to your 
  33. IBM Authorized Dealer or your IBM Marketing Representative. 
  34.  
  35. IBM may have patents or pending patent applications covering subject matter in 
  36. this document. The furnishing of this document does not give you any license to 
  37. these patents. You can send license inquiries, in writing, to the IBM Director 
  38. of Commercial Relations, IBM Corporation, Purchase, NY 10577. 
  39.  
  40. COPYRIGHT LICENSE: This publication contains printed sample application 
  41. programs in source language, which illustrate OS/2 or AIX programming 
  42. techniques. You may copy and distribute these sample programs in any form 
  43. without payment to IBM, for the purposes of developing, using, marketing or 
  44. distributing application programs conforming to the OS/2 or AIX application 
  45. programming interface. 
  46.  
  47. Each copy of any portion of these sample programs or any derivative work, which 
  48. is distributed to others, must include a copyright notice as follows: "(C) 
  49. (your company name) (year) All Rights Reserved." 
  50.  
  51. However, the following copyright notice protects this documentation under the 
  52. Copyright laws of the United States and other countries which prohibit such 
  53. actions as, but not limited to, copying, distributing, modifying, and making 
  54. derivative works. 
  55.  
  56.  
  57. ΓòÉΓòÉΓòÉ 1.1. Trademarks ΓòÉΓòÉΓòÉ
  58.  
  59. The following terms are trademarks of the International Business Machines 
  60. Corporation in the United States and/or other countries: 
  61.  
  62.       AIX 
  63.       Operating System/2 
  64.       OS/2 
  65.       OS/2 Workplace Shell 
  66.       RISC System 6000 
  67.       SOMobjects 
  68.       System Object Model 
  69.  
  70.  For convenience, the acronym "SOM" is used in this publication to reference 
  71.  the technology of the System Object Model, and the term "SOM Compiler" is used 
  72.  to reference the compiler of the System Object Model. 
  73.  
  74.  Each of the following terms used in this publication is a trademark of another 
  75.  company: 
  76.  
  77.  C++         AT&T, Inc. 
  78.  EXCEL       Microsoft Corporation 
  79.  Intel       Intel Corporation 
  80.  IPX         Novell Corporation 
  81.  Lotus 1-2-3 Lotus Development Corporation 
  82.  NetWare     Novell Corporation 
  83.  Objective-C The Stepstone Corporation 
  84.  Smalltalk   Digitalk Inc. 
  85.  Windows     Microsoft Corporation 
  86.  
  87.  The term "ANSI C" used throughout this publication refers to American National 
  88.  Standard X3.159-1989. 
  89.  
  90.  The term "CORBA" used throughout this publication refers to the Common Object 
  91.  Request Broker Architecture standards promulgated by the Object Management 
  92.  Group, Inc. 
  93.  
  94.  
  95. ΓòÉΓòÉΓòÉ 2. About This Book ΓòÉΓòÉΓòÉ
  96.  
  97. This book accompanies the SOMobjects Base Toolkit, which consists of the base 
  98. (or core) capabilities in the System Object Model (SOM) of the SOMobjects 
  99. Developer Toolkit.  The base system is a rich subset of the full-capability 
  100. SOMobjects Developer Toolkit. Because the current manual is a subset of 
  101. chapters from the full SOMobjects Developer Toolkit Users Guide, references 
  102. herein to the "SOMobjects Developer Toolkit" should be interpreted as 
  103. capabilities of the SOMobjects Base Toolkit. 
  104.  
  105. This manual explains how programmers using c, C++, and other languages can: 
  106.  
  107.    o  Implement class libraries that exploit the SOM library-packaging 
  108.       technology, 
  109.  
  110.    o  Develop client programs that use class libraries that were built using 
  111.       SOM, and 
  112.  
  113.    o  Develop applications that use the frameworks supplied with the SOMobjects 
  114.       Toolkit, class libraries that facilitate development of object-oriented 
  115.       applications. 
  116.  
  117.  In addition to this book, refer to the SOMobjects Base Toolkit Programmers 
  118.  Reference Manual during application development for specific information about 
  119.  the classes, methods, functions, and macros supplied with the SOMobjects 
  120.  Toolkit. 
  121.  
  122.  For purchasers of the full-capability SOMobjects systems, the SOMobjects 
  123.  Developer Toolkit: Emitter Framework Guide and Reference contains 
  124.  documentation of the Emitter Framework of the SOMobjects Developer Toolkit. In 
  125.  addition, the SOMobjects Developer Toolkit: Collection Classes Reference 
  126.  Manual describes the collection classes and methods provided with the 
  127.  SOMobjects Developer Toolkit. 
  128.  
  129.  
  130. ΓòÉΓòÉΓòÉ 2.1. How This Book Is Organized ΓòÉΓòÉΓòÉ
  131.  
  132. This book contains nine chapters, three appendices, a glossary, and an index. 
  133.  
  134.    o  The first part (chapters 1 and 2) introduces the reader to the SOMobjects 
  135.       Toolkit, gives an overview of the major elements of SOM, and provides a 
  136.       Tutorial containing several evolutionary examples. 
  137.  
  138.    o  The second part (chapter 3) describes how to develop client programs in 
  139.       C, C++, or other languages to use classes that were implemented using 
  140.       SOM, including how to create instances of a class and call methods on 
  141.       them. 
  142.  
  143.    o  The third part (chapters 4 and 5) describes the SOM run-time environment, 
  144.       gives the syntax of the SOM Interface Definition Language, provides 
  145.       directions for running the SOM Compiler, and contains advanced 
  146.       information about SOM's object model and how to customize SOM for 
  147.       particular applications. 
  148.  
  149.    o  The fourth part (chapters 6 through 9) contains information about the 
  150.       frameworks composing the SOMobjects Toolkit: Distributed SOM (DSOM), the 
  151.       Interface Repository Framework, and the Event Management Framework. This 
  152.       part also describes the utility metaclasses provided with the SOMobjects 
  153.       Toolkit. 
  154.  
  155.    o  The appendices describe error codes, and provide the grammar for SOM IDL. 
  156.       The final appendix describes how to subclass a "Sockets" class that 
  157.       facilitates inter-process communications required by some of the 
  158.       frameworks. 
  159.  
  160.    o  The Glossary provides brief definitions of terminology related to SOM and 
  161.       the SOMobjects Toolkit. Finally, an extensive Index enables the reader to 
  162.       locate specific information quickly. 
  163.  
  164.  
  165. ΓòÉΓòÉΓòÉ 2.2. Who Should Read This Book ΓòÉΓòÉΓòÉ
  166.  
  167. This book is for the professional programmer using C, C++, or another language 
  168. who wishes to 
  169.  
  170.    o  Use SOM to build object-oriented class libraries, or 
  171.  
  172.    o  Write application programs using class libraries that others have 
  173.       implemented using SOM, 
  174.  
  175.  even if the programming language does not directly support object-oriented 
  176.  programming. 
  177.  
  178.  The discussions in this book are expressed in the commonly used terminology of 
  179.  object-oriented programming. A number of important terms are everyday English 
  180.  words that take on specialized meanings. These terms appear in the Glossary at 
  181.  the back of this book. You may find it worth consulting the Glossary if the 
  182.  unusual significance attached to an otherwise ordinary word puzzles you. 
  183.  
  184.  This book assumes that you are an experienced programmer and that you have a 
  185.  general familiarity with the basic notions of object-oriented programming. 
  186.  Practical experience using an object-oriented programming language is helpful, 
  187.  but not essential. 
  188.  
  189.  If you would like a good introduction to object-oriented programming or a 
  190.  general survey of the many aspects of the topic, you might enjoy reading one 
  191.  of the following books: 
  192.  
  193.    o  Booch, G, Object-Oriented Design with Applications, Benjamin/Cummings 
  194.       1991, ISBN 0-8053-0091-0. 
  195.  
  196.    o  Budd, T, An Introduction to Object-Oriented Programming, Addison-Wesley 
  197.       1991, ISBN 0-201-54709-0. 
  198.  
  199.    o  Cox, B, and Novobilski, A, Object-Oriented Programming, An Evolutionary 
  200.       Approach 2nd Edition, Addison-Wesley 1991, ISBN 0-201-54834-8. 
  201.  
  202.  
  203. ΓòÉΓòÉΓòÉ 3. Introduction to the SOMobjects Developer Toolkit ΓòÉΓòÉΓòÉ
  204.  
  205.  
  206. ΓòÉΓòÉΓòÉ 3.1. Background ΓòÉΓòÉΓòÉ
  207.  
  208. Object-oriented programming (or OOP) is an important new programming technology 
  209. that offers expanded opportunities for software reuse and extensibility. 
  210. Object-oriented programming shifts the emphasis of software development away 
  211. from functional decomposition and toward the recognition of units (called 
  212. objects) that encapsulate both code and data.  As a result, programs become 
  213. easier to maintain and enhance. Object-oriented programs are typically more 
  214. impervious to the "ripple effects" of subsequent design changes than their 
  215. non-object-oriented counterparts. This, in turn, leads to improvements in 
  216. programmer productivity. 
  217.  
  218. Despite its promise, penetration of object-oriented technology to major 
  219. commercial software products has progressed slowly because of certain 
  220. obstacles.  This is particularly true of products that offer only a binary 
  221. programming interface to their internal object classes (Example: products that 
  222. do not allow access to source code). 
  223.  
  224. The first obstacle that developers must confront is the choice of an 
  225. object-oriented programming language. 
  226.  
  227. So-called"pure" object-oriented language (such as Smalltalk) presume a complete 
  228. run-time environment (sometimes known as a virtual machine), because their 
  229. semantics represent a major departure from traditional, procedure-oriented 
  230. system architectures.  So long as the developer works within the supplied 
  231. environment, everything works smoothly and consistently.  When the need arises 
  232. to interact with foreign environment, however (for example, to make an external 
  233. procedure call), the pure-object paradigm ends, and objects must be reduced to 
  234. data structures for external manipulation.  Unfortunately, data structures do 
  235. not retain the advantage that objects offer with regard to encapsulation and 
  236. code reuse. 
  237.  
  238. "Hybrid" languages such as C++**. on the other hand, require less run-time 
  239. support, but sometimes result in tight bindings between programs that implement 
  240. objects (called "class libraries") and their clients (the programs that use 
  241. them). That is, implementation detail is often unavoidably compiled into the 
  242. client programs.  Tight binding between class libraries and their clients means 
  243. that client programs often must be recompiled whenever simple changes are made 
  244. in the library.  Furthermore, no binary standard exists for C++ objects, so the 
  245. C++ class libraries produced by one C++ compiler cannot (in general) be used 
  246. from C++ programs built with a different C++ compiler. 
  247.  
  248. The second obstacle developers of object-oriented software must confront is 
  249. that, because different object-oriented languages and toolkits embrace 
  250. incompatible models of what objects are and how they work, software developed 
  251. using a particular language or toolkit is naturally limited in scope.  Classes 
  252. implemented in one language cannot be readily used from another.  A C++ 
  253. programmer, for example, cannot easily use classes developed in Smalltalk, nor 
  254. can a Smalltalk programmer make effective use of C++ classes. Object-oriented 
  255. language and toolkit boundaries become, in effect, barriers to 
  256. interoperability. 
  257.  
  258. Ironically, no such barrier exists for ordinary procedure libraries. Software 
  259. developers routinely construct procedure libraries that can be shared across a 
  260. variety of languages, by adhering to standard linkage conventions. 
  261. Object-oriented class libraries are inherently different in that no binary 
  262. standards or conventions exist to derive a new class from an existing one,  or 
  263. even to invoke a method in a standard way.  Procedure libraries also have the 
  264. benefit that their implementations can be freely changed without requiring 
  265. client programs to be recompiled, unlike the situation for C++ class libraries. 
  266.  
  267. For developers who need to provide binary class libraries, these are serious 
  268. obstacles. In an era of open systems and heterogeneous networking, a 
  269. single-language solution is frequently not broad enough.  Certainly, mandating 
  270. a specific compiler from a specific vendor in order to use a class library 
  271. might be grounds not to include the class library with an operating system or 
  272. other general-purpose product. 
  273.  
  274. The System Objects Model (SOM) is IBM's solution to these problems. 
  275.  
  276.  
  277. ΓòÉΓòÉΓòÉ 3.2. Introducing SOM and the SOMobjects Toolkit ΓòÉΓòÉΓòÉ
  278.  
  279. The System Object Model (SOM) is a new object-oriented programming technology 
  280. for building, packaging, and manipulating binary class libraries. 
  281.  
  282.    o  With SOM, class implementers describe the interface for a class of 
  283.       objects (names of the methods it supports, the return types, parameter 
  284.       types, and so forth) in a standard language called the Interface 
  285.       Definition Language, or IDL. 
  286.  
  287.    o  They then implement methods in their preferred programming language 
  288.       (which may be either an object-oriented programming language or a 
  289.       procedural language such as C). 
  290.  
  291.  This means that programmers can begin using SOM quickly, and also extends the 
  292.  advantages of OOP to programmers who use non-object-oriented programming 
  293.  languages. 
  294.  
  295.  A principal benefit of using SOM is that SOM accommodates changes in 
  296.  implementation details and even in certain facets of a class ' interface, 
  297.  without breaking the binary interface to a class library and without requiring 
  298.  recompilation of client programs.  As a rule of thumb , if changes to a SOM 
  299.  class do not require source-code changes in client programs, then those client 
  300.  programs will not need to be recompiled. This is not true of many 
  301.  object-oriented languages, and it is one of the chief benefits of using SOM. 
  302.  For instance, SOM classes can undergo structural changes such as the 
  303.  following, yet retain full backward, binary compatibility: 
  304.  
  305.    o  Adding new methods, 
  306.  
  307.    o  Changing the size of an object by adding or deleting instance variables, 
  308.  
  309.    o  Inserting new parent (base) classes above a class in the inheritance 
  310.       hierarchy, and 
  311.  
  312.    o  Relocating methods upward in the class hierarchy. 
  313.  
  314.  In short, implementers can make the typical kinds of changes to an 
  315.  implementation and its interfaces that evolving software systems experience 
  316.  over time. 
  317.  
  318.  Unlike the object models found in formal object-oriented programming 
  319.  languages, SOM is language-neutral.  It preserves the key OOP characteristics 
  320.  of encapsulation, inheritance, and polymorphism, without requiring that the 
  321.  user of a SOM class and the implementer of a SOM class use the same 
  322.  programming language.  SOM is said to be language-neutral for four reasons: 
  323.  
  324.    1. All SOM interactions consist of standard procedure calls. On systems that 
  325.       have a standard linkage convention for system calls, SOM interactions 
  326.       conform to those conventions. Thus, most programming languages that can 
  327.       make external procedure calls can use SOM. 
  328.  
  329.    2. The form of the SOM Application Programming Interface, or API (the way 
  330.       that programmers invoke methods, create objects, and so on) can vary 
  331.       widely from language to language, as a benefit of the SOM bindings. 
  332.       Bindings are a set of macros and procedure calls that make implementing 
  333.       and using SOM classes more convenient by tailoring the interface to a 
  334.       particular programming language. 
  335.  
  336.    3. SOM supports several mechanisms for method resolution that can be readily 
  337.       mapped into the semantics of a wide range of object-oriented programming 
  338.       languages. Thus, SOM class libraries can be shared across object-oriented 
  339.       languages that have differing object models.  A SOM object can 
  340.       potentially be accessed with three different forms of method resolution: 
  341.  
  342.         o  Offset resolution: roughly equivalent to the C++ "virtual function" 
  343.            concept. Offset resolution implies a static scheme for typing 
  344.            objects, with polymorphism based strictly on class derivation.  It 
  345.            offers the best performance characteristics for SOM method 
  346.            resolution.  Methods accessible through offset resolution are called 
  347.            static methods, because they are considered a fixed aspect of an 
  348.            object's interface. 
  349.  
  350.         o  Name-lookup resolution: similar to that employed by Objective-C and 
  351.            Smalltalk.  Name resolution supports untyped (sometimes called 
  352.            "dynamically" typed) access to objects, with polymorphism based on 
  353.            the actual protocols that objects honor. Name resolution offers the 
  354.            opportunity to write code to manipulate objects with little or no 
  355.            awareness of the type or shape of the object when the code is 
  356.            compiled. 
  357.  
  358.         o  Dispatch-function resolution: a unique feature of SOM that permits 
  359.            method resolution based on arbitrary rules known only in the domain 
  360.            of the receiving object. Languages that require special entry or 
  361.            exit sequences or local objects that represent distributed object 
  362.            domains are good candidates for using dispatch-function resolution. 
  363.            This technique offers the highest degree of encapsulation for the 
  364.            implementation of an object, with some cost in performance. 
  365.  
  366.    4. SOM conforms fully with the Object Management Group's (OMG)**. OMG is an 
  367.       industry consortium founded to advance the use of object technology in 
  368.       distributed, heterogeneous environments. Common Object Request Broker 
  369.       Architecture (CORBA) standards. In particular, 
  370.  
  371.         o  Interface to SOM classes are described in CORBA's Interface 
  372.            Definition Language, IDL, and the entire SOMobjects Toolkit supports 
  373.            all CORBA-defined data types. 
  374.  
  375.         o  The SOM bindings for the C language are compatible with the C 
  376.            bindings prescribed by CORBA. 
  377.  
  378.         o  All information about the interface to a SOM class is available at 
  379.            run time through a CORBA-defined "Interface Repository." 
  380.  
  381.  SOM is not intended to replace existing object-oriented languages. Rather, it 
  382.  is intended to complement them so that application programs written in 
  383.  different programming languages can share common SOM class libraries. For 
  384.  example, SOM can be used with C++ to do the following: 
  385.  
  386.    o  Provide upwardly compatible class libraries, so that when a new version 
  387.       of a SOM class is released, client code needn't be recompiled, so long as 
  388.       no changes to the client's source code are required. 
  389.  
  390.    o  Allow other language users (and other C++ compiler users) to use SOM 
  391.       classes implemented in C++. 
  392.  
  393.    o  Allow C++ programs to use SOM classes implemented using other languages. 
  394.  
  395.    o  Allow other language users to implement SOM classes derived from SOM 
  396.       classes implemented in C++. 
  397.  
  398.    o  Allow C++ programmers to implement SOM classes derived from SOM classes 
  399.       implemented using other languages. 
  400.  
  401.    o  Allow encapsulation (implementation hiding) so that SOM class libraries 
  402.       can be shared without exposing private instance variables and methods. 
  403.  
  404.    o  Allow dynamic (run-time) method resolution in addition to static 
  405.       (compile-time) method resolution (on SOM objects). 
  406.  
  407.    o  Allow information about classes to be obtained and updated at run time. 
  408.       (C++ classes are compile-time structures that have no properties at run 
  409.       time.) 
  410.  
  411.  
  412. ΓòÉΓòÉΓòÉ 3.2.1. The SOM Compiler ΓòÉΓòÉΓòÉ
  413.  
  414. The SOMobjects Toolkit contains a tool, called the SOM Compiler, that helps 
  415. implementers build classes in which interface and implementation are decoupled. 
  416. The SOM Compiler reads the IDL definition of a class interface and generates: 
  417.  
  418.    o  an implementation skeleton for the class, 
  419.  
  420.    o  bindings for implementers, and 
  421.  
  422.    o  bindings for client programs. 
  423.  
  424.  Bindings are  language-specific macros and procedures  that make implementing 
  425.  and using SOM classes more convenient. These bindings offer a convenient 
  426.  interface to SOM that is tailored to a particular programming language.  For 
  427.  instance, C programmers can invoke methods in the same way they make ordinary 
  428.  procedure calls. The C++ bindings "wrap" SOM objects as C++ objects, so that 
  429.  C++ programmers can invoke methods on SOM objects in the same way they invoke 
  430.  methods on C++ objects. In addition, SOM objects receive full C++ 
  431.  typechecking, just as C++ objects do.  Currently, the SOM Compiler can 
  432.  generate both C and C++ language bindings for a class. The C and C++ bindings 
  433.  will work with a variety of commercial products available from IBM and others. 
  434.  Vendors of other programming languages may also offer SOM bindings.  Check 
  435.  with your language vendor about possible SOM support. 
  436.  
  437.  
  438. ΓòÉΓòÉΓòÉ 3.2.2. The SOM run-time library ΓòÉΓòÉΓòÉ
  439.  
  440. In addition to the SOM Compiler, SOM includes a run-time library.  This library 
  441. provides, among other things, a set of classes, methods, and procedures used to 
  442. create object and invoke methods on them.  The library allows any programming 
  443. language to use SOM classes (classes developed using SOM) if that language can: 
  444.  
  445.    o  Call external procedures, 
  446.  
  447.    o  Store a pointer to a procedure and subsequently invoke that procedure, 
  448.       and 
  449.  
  450.    o  Map IDL types onto the programming language's native types. 
  451.  
  452.  Thus, the user of a SOM class and the implementer of a SOM class needn't use 
  453.  the same programming language, and neither is required to use an 
  454.  object-oriented language.  The independence of client language and 
  455.  implementation language also extends to subclassing: a SOM class can be 
  456.  derived from other SOM classes, and the subclass may or may not be implemented 
  457.  in the same language as the parent class(es). Moreover, SOM's run-time 
  458.  environment allows applications to access information about classes 
  459.  dynamically (at run time). 
  460.  
  461.  
  462. ΓòÉΓòÉΓòÉ 3.2.3. Frameworks provided in the SOMobjects Toolkit ΓòÉΓòÉΓòÉ
  463.  
  464. In addition to SOM itself (the SOM compiler and the SOM run-time library), the 
  465. SOMobjects Developer Toolkit also provides a set of frameworks (class 
  466. libraries) that can be used in developing object-oriented applications.  These 
  467. include Distributed SOM, the Interface Repository Framework, and the Emitter 
  468. Framework, and the Metaclass Framework, described below. 
  469.  
  470. Note:  SOMobjects Base Toolkit, the core version of SOMobject shipped with this 
  471.        documentation, contains only Distributed SOM, the Interface Repository, 
  472.        and the Metaclass frameworks. The complete SOMobjects Developer Toolkit 
  473.        can be ordered from IBM by calling 1-800-342-6672 in the U.S. or 
  474.        1-800-465-7999 in Canada. The part number is 10H9767 for the CD-ROM 
  475.        containing SOMobjects for the AIX, OS/2, and Windows platforms 
  476.        (including online documentation). SOMobjects manuals are available 
  477.        individually. 
  478.  
  479.  
  480.  Distributed SOM 
  481.  
  482.  Distributed SOM  (or DSOM) allows application programs to access SOM objects 
  483.  across address spaces.. That is, application programs can access objects in 
  484.  other processes, even on different machines.  DSOM provides this transparent 
  485.  access to remote objects through its Object Request Broker (ORB): the location 
  486.  and implementation of the object are hidden from the client, and the client 
  487.  accesses the object as if local.  The current release of DSOM supports 
  488.  distribution of objects among processes within a workstation, and across a 
  489.  local area network consisting of OS/2 system, AIX systems, or a mix of both. 
  490.  Future releases may support larger enterprise-wide networks. 
  491.  Interface Repository Framework 
  492.  
  493.  The Interface Repository is a database, optionally created and maintained by 
  494.  the SOM Compiler, that holds all the information contained in the IDL 
  495.  description of a class of objects. The Interface Repository Framework consists 
  496.  of the 11 classes defined in the CORBA standard for accessing the Interface 
  497.  Repository. Thus, the interface Repository Framework provides run-time access 
  498.  to all information contained in the IDL description of a class of objects. 
  499.  Type information is available as TypeCodes--a CORBA-defined way of encoding 
  500.  the complete description of any data type that can be constructed in IDL. 
  501.  
  502.  
  503. ΓòÉΓòÉΓòÉ 3.2.4. Metaclass Framework ΓòÉΓòÉΓòÉ
  504.  
  505. Finally, the Metaclass Framework is a collection of SOM metaclasses that 
  506. provide functionality that may be useful to SOM class designers for modifying 
  507. the default semantics of method invocation and object creation.  These 
  508. metaclasses are described in Chapter 8, "The Metaclass Framework." 
  509.  
  510.  
  511. ΓòÉΓòÉΓòÉ 3.3. What's New in SOMobjects Version 2.1 ΓòÉΓòÉΓòÉ
  512.  
  513. Version 2.1 of the SOMobjects Developer Toolkit provides enhanced capabilities 
  514. and improved performance for both SOM and DSOM. In addition, the Toolkit now 
  515. includes support for DirectToSOM (DTS) C++ compilers. New metaclasses in the 
  516. Metaclass Framework allow class implementors to define classes that 
  517. automatically possess certain convenience facilities. Also, TCP/IP support is 
  518. available for Windows users, and OS/2 users can choose 32-bit TCP/IP. 
  519.  
  520. In particular, SOMobjects Version 2.1 offers the following additions over 
  521. Version 2.0: 
  522.  
  523.  
  524. ΓòÉΓòÉΓòÉ 3.3.1. General enhancements ΓòÉΓòÉΓòÉ
  525.  
  526.    o  C++ programmers can use DirectToSOM (DTS) C++ compilers (available from 
  527.       independent software vendors) as an alternative to the SOMobjects 
  528.       Toolkit's C++ bindings. (A DTS C++ compiler uses SOM classes to implement 
  529.       C++ objects.) The support provided by SOMobjects for DTS C++ consists of 
  530.       various enhancements to the SOM API (useful to SOM programmers in 
  531.       general), and a new emitter that produces DTS C++ header files 
  532.       corresponding to SOM IDL. DTS C++ programs include these ".hh" header 
  533.       files, which are emitted as described under "Generating binding files" in 
  534.       Chapter 4, "SOM IDL and the SOM Compiler." 
  535.  
  536.    o  With this release, TCP/IP support is now available for SOMobjects For 
  537.       Windows. Also, for OS/2 users only, SOMobjects now supports the 32-bit 
  538.       TCP/IP version 2.0, which offers greater performance over the 16-bit 
  539.       TCP/IP version 1.2.1. These are described in your SOMobjects 
  540.       Installation/Configuration Guide. 
  541.  
  542.       SOMobjects enhancements 
  543.  
  544.    o  A new default process whereby SOMobjects initializes and destroys objects 
  545.       more efficiently (using the somDefaultInit and somDestruct methods) See 
  546.       "Initializing and Uninitializing Objects" in Chapter 5, "Implementing 
  547.       Classes in SOM." 
  548.  
  549.    o  A new kind of method, nonstatic, that is similar to a C++ nonstatic 
  550.       member function. It is normally invoked using offset resolution but can 
  551.       use any form of SOMobjects method resolution. See "The four kinds of SOM 
  552.       methods" in Chapter 5, "Implementing Classes in SOM" and the nonstatic 
  553.       modifier under "Modifier statements" in Chapter 4, "SOM IDL and the SOM 
  554.       Compiler." 
  555.  
  556.    o  A new kind of data, staticdata, that is similar to C++ static data 
  557.       members. A staticdata variable is not stored in an object; rather, the 
  558.       ClassData structure of the implementing class contains a pointer to the 
  559.       variable. See the staticdatamodifier under "Modifier statements" in 
  560.       Chapter 4, "SOM IDL and the SOM Compiler." 
  561.  
  562.    o  Two new modifiers, somallocate and somdeallocate, used to indicate that a 
  563.       user-written procedure should be executed to allocate/deallocate memory 
  564.       for class instances when the somAllocate or somDeallocate method is 
  565.       invoked. See these modifiers under "Modifier statements" in Chapter 4, 
  566.       "SOM IDL and the SOM Compiler." 
  567.  
  568.    o  The ability to "cast" objects. See the methods somCastObj and 
  569.       somResetObj. 
  570.  
  571.    o  New support for loading/unloading class libraries. (This was introduced 
  572.       in SOMobjects For Windows and is now applicable on OS/2 as well.) See the 
  573.       SOM_ClassLibrary macro in the SOMobjects Base Toolkit Programmers 
  574.       Reference Manual. 
  575.  
  576.       DSOM enhancements 
  577.  
  578.    o  A new command-line tool, dsom, for managing DSOM servers (starting, 
  579.       restarting, stopping, querying, and so forth). See "The dsom server 
  580.       manager utility" in Chapter 6, "Distributed SOM." In addition, a 
  581.       corresponding programmatic interface is provided by methods of the new 
  582.       SOMDServerMgr class. See that class and its methods in the SOMobjects 
  583.       Base Toolkit Programmers Reference Manual. 
  584.  
  585.    o  A new command-line tool, somdchk, that performs environment validation. 
  586.       See "Verifying the DSOM environment with somdchk" in Chapter 6, 
  587.       "Distribute SOM." 
  588.  
  589.    o  New SOM IDL modifiers for memory management of parameters: 
  590.       memory_management= corba, caller_owns_parameters, caller_owns_result, 
  591.       object_owns_parameters, and object_owns_result. The individual modifiers 
  592.       are described under "Modifier statements" in Chapter 4, "SOM IDL and the 
  593.       SOM Compiler." See "Memory management" in Chapter 6, "Distributed SOM," 
  594.       for a complete discussion of the subject. This memory-management support 
  595.       also includes the new method somdReleaseResources and the functions 
  596.       somdExceptionFree and SOMD_NoORBfree, described in the SOMobject Base 
  597.       Toolkit Programmers Reference Manual. 
  598.  
  599.    o  A graphical user interface to the DSOM `regimpl' utility on OS/2, called 
  600.       pregimpl. See "Registration steps using `pregimpl' or `wregimpl'," in 
  601.       Chapter 6, "Distributed SOM." 
  602.  
  603.    o  Support for the CORBA constant OBJECT_NIL. In addition, the is_nil method 
  604.       of SOMDObject can now be used for local objects as well as NULL pointers. 
  605.  
  606.    o  Support for passing self-referential structs and unions (those valid in 
  607.       IDL) in remote method calls. 
  608.  
  609.    o  Support for local/remote transparency in DSOM's object-destruction 
  610.       methods. See "Destroying remote objects." 
  611.  
  612.    o  Ability for users to define customized base proxy classes. See 
  613.       "Customizing the default base proxy class." 
  614.  
  615.    o  Ability for users to specify an upper limit on the number of threads that 
  616.       a server can spawn, via the SOMDNUMTHREADS environment variable. See this 
  617.       variable under "Preparing the environment." 
  618.  
  619.    o  Improved error handling and performance improvements. 
  620.  
  621.    o  More sample programs distributed with the SOMobjects Toolkit. 
  622.  
  623.       Metaclass Framework 
  624.  
  625.    o  SOMMBeforeAfter -- a metaclass that enables the programming of 
  626.       "before/after" metaclasses, whose instances execute a particular method 
  627.       before and after each method invocation. See Chapter 8, "The Metaclass 
  628.       Framework," for information about the new Metaclass Framework. Individual 
  629.       metaclasses, along with related classes and methods, are documented in 
  630.       the SOMobjects Base Toolkit Programmers Reference Manual. 
  631.  
  632.    o  SOMMTraced -- a utility metaclass to do tracing. 
  633.  
  634.  
  635. ΓòÉΓòÉΓòÉ 3.3.2. New restrictions and deprecated methods ΓòÉΓòÉΓòÉ
  636.  
  637. While implementing the Metaclass Framework, IBM learned that metaclasses must 
  638. be programmed so that the capabilities they implement will be preserved when 
  639. various metaclasses are combined (using multiple inheritance) into a 
  640. SOM-derived metaclass. To assure this result, the Metaclass Framework 
  641. metaclasses have been programmed using a "Cooperative Metaclass." However, IBM 
  642. is not yet ready to include the Cooperative metaclass among the officially 
  643. supported features of SOMobjects. 
  644.  
  645. To prevent user-defined metaclasses from interfering with the operation of the 
  646. Cooperative Metaclass and consequently with the Metaclass Framework, SOMobjects 
  647. programmers are strongly urged to observe the following restriction when 
  648. programming new metaclasses: 
  649.  
  650.    o  User-defined metaclasses can introduce new class methods and class 
  651.       variables, but should not override any of the methods introduced by the 
  652.       SOMClass class. 
  653.  
  654.  SOMobjects users whose metaclass programming requirements cannot be met within 
  655.  the above restrictions will be given access to the Cooperative Metaclass and 
  656.  its documentation. Note, however, that metaclasses developed using the 
  657.  Cooperative Metaclass may require reprogramming when an officially supported 
  658.  Cooperative Metaclass is later introduced. 
  659.  
  660.  In addition, use of a number of (public) methods introduced by SOMClass is now 
  661.  deprecated because they are useful only from overridden SOMClass methods. 
  662.  These methods are listed under the heading "Deprecated methods" in the 
  663.  documentation for SOMClass within the SOMobjects Base Toolkit Programmers 
  664.  Reference Manual, until such time as SOMobjects is ready to officially provide 
  665.  a framework within which their use will not interfere with the internal 
  666.  operation of SOMobjects itself. 
  667.  
  668.  
  669. ΓòÉΓòÉΓòÉ 3.4. Overview of this book ΓòÉΓòÉΓòÉ
  670.  
  671. This book is a subset of the SOMobjects Developer Toolkit Users Guide for the 
  672. full-capability SOMobjects Developer Toolkit.  The omitted chapters describe 
  673. capabilities not included with the SOMobjects Base Toolkit.  Chapters that are 
  674. included appear in their entirety, as written for the full-capability 
  675. SOMobjects systems, except for some references to chapters/capabilities not 
  676. included in the SOMobjects Base Toolkit.  Because the current manual is a 
  677. subset, references herein to the "SOMobjects Developers Toolkit" should be 
  678. interpreted as referencing capabilities of the SOMobjects Base Toolkit. 
  679.  
  680. Chapter 2 contains a Tutorial with five examples that illustrate techniques for 
  681. implementing classes in SOM.  All readers should cover this tutorial. 
  682.  
  683. Chapter 3 describes how an application program creates instances of a SOM 
  684. class, how it invokes methods, and so on.  For readers interested only in using 
  685. SOM classes, rather than building them, chapters 2 and 3 may provide all of the 
  686. information they need to begin using SOM classes. 
  687.  
  688. Chapter 4 contains explanations and examples for all valid SOM IDL syntax 
  689. components, it then presents the SOM Compiler, including all compiler options 
  690. and related environment variables.  All class implementors will need to 
  691. reference this chapter. 
  692.  
  693. Chapter 5 provides more comprehensive information about the SOM system itself, 
  694. including operation of the SOM run-time environment, inheritance, and method 
  695. resolution.  This chapter also describes how to create language-neutral class 
  696. libraries using SOM.  In addition, it contains some advanced topics for 
  697. customizing SOM to better suit the needs of a particular application. All class 
  698. implementors will need to reference this chapter. 
  699.  
  700. Chapter 6 describes Distributed SOM and how to use it to access objects across 
  701. address spaces, even on different machines. Chapter 6 describes how to 
  702. customize DSOM. Note that SOMobjects Base Toolkit supports only Workstation 
  703. DSOM (distributed among processes on a single machine), whereas SOMobjects 
  704. Developer Toolkit also supports Workgroup DSOM (distribution among a network of 
  705. machines). 
  706.  
  707. Chapter 7 describes the Interface Repository Framework of classes supplied with 
  708. the SOMobjects Toolkit. 
  709.  
  710. Chapter 8 describes the Metaclass Framework and some utility metaclasses that 
  711. SOM provides to assist users in deriving new classes with special abilities to 
  712. execute "before" and "after" operations when a method call occurs, as well as 
  713. other capabilities for modifying the default semantics of method invocation and 
  714. object creation. 
  715.  
  716. Chapter 9 describes the Event Manager Framework which allows grouping of all 
  717. application events and waiting on multiple events in one place.  The Event 
  718. Manager is used by DSOM. 
  719.  
  720. Appendix A contains lists of the error codes and messages that can be issued by 
  721. the SOM kernel or by the various frameworks. 
  722.  
  723. Appendix B contains the SOM IDL language grammar. 
  724.  
  725. Appendix C describes how to subclass a "Sockets" class that facilitates 
  726. inter-process communications required by the DSOM, Replication, and Event 
  727. Management Frameworks. 
  728.  
  729.  A Glossary and a thorough Index conclude this manual. 
  730.  
  731.  
  732. ΓòÉΓòÉΓòÉ 4. Tutorial for Implementing SOM Classes ΓòÉΓòÉΓòÉ
  733.  
  734. This tutorial contains five examples showing how SOM classes can be implemented 
  735. to achieve various functionality. Obviously, for any person who wishes to 
  736. become a class implementor, this tutorial is essential. However, even for those 
  737. programmers who expect only to use SOM classes that were implemented by others, 
  738. the tutorial is also necessary, as it presents several concepts that will help 
  739. clarify the process of using SOM classes. 
  740.  
  741.  
  742. ΓòÉΓòÉΓòÉ 4.1. Basic Concepts of the System Object Model (SOM) ΓòÉΓòÉΓòÉ
  743.  
  744. The System Object Model (SOM), provided by the SOMobjects Developer Toolkit, is 
  745. a set of libraries, utilities, and conventions used to create binary class 
  746. libraries that can be used by application programs written in various 
  747. object-oriented programming languages, such as C++ and Smalltalk, or in 
  748. traditional procedural languages, such as C and Cobol. The following paragraphs 
  749. introduce some of the basic terminology used when creating classes in SOM: 
  750.  
  751.    o  An object is an OOP entity that has behavior (its methods or operations) 
  752.       and state (its data values).  In SOM, an object is a run-time entity with 
  753.       a specific set of methods and instance variables.  The methods are used 
  754.       by a client programmer to make the object exhibit behavior (that is, to 
  755.       do something), and the instance variables are used by the object to store 
  756.       its state.  (The state of an object can change over time, which allows 
  757.       the object's behavior to change.)  When a method is invoked on an object, 
  758.       the object is said to be the receiver or target of the method call. 
  759.  
  760.    o  An object's implementation is determined by the procedures that execute 
  761.       its methods, and by the type and layout of its instance variables.  The 
  762.       procedures and instance variables that implement an object are normally 
  763.       encapsulated  (hidden from the caller), so a program can use the object's 
  764.       methods without knowing anything about how those methods are implemented. 
  765.       Instead, a user is given access to the object's methods through its 
  766.       interface (a description of the methods in terms of the data elements 
  767.       required as input and the type of value each method returns). 
  768.  
  769.    o  An interface through which an object may be manipulated is represented by 
  770.       an object type.  That is, by declaring a type for an object variable, a 
  771.       programmer specifies the interface that is intended to be used to access 
  772.       that object.  SOM IDL (the SOM Interface Definition Language) is used to 
  773.       define object interfaces.  The interface names used in these IDL 
  774.       definitions are also the type names used by programmers when typing SOM 
  775.       object variables. 
  776.  
  777.    o  In SOM, as in most approaches to object-oriented programming, a class 
  778.       defines the implementation of objects. That is, the implementation of any 
  779.       SOM object (as well as its interface) is defined by some specific SOM 
  780.       class. A class definition begins with an IDL specification of the 
  781.       interface to its objects, and the name of this interface is used as the 
  782.       class name as well. Each object of a given class may also be called an 
  783.       instance of the class, or an instantiation of the class. 
  784.  
  785.    o  Inheritance, or class derivation, is a technique for developing new 
  786.       classes from existing classes. The original class is called the base 
  787.       class, or the parent class, or sometimes the direct ancestor class. The 
  788.       derived class is called a child class or a subclass.  The primary 
  789.       advantage of inheritance is that a derived class inherits all of its 
  790.       parent's methods and instance variables.  Also through inheritance, a new 
  791.       class can override (or redefine) methods of its parent, in order to 
  792.       provide enhanced functionality as needed.  In addition, a derived class 
  793.       can introduce new methods of its own. If a class results from several 
  794.       generations of successive class derivation, that class "knows" all of its 
  795.       ancestors's methods (whether overridden or not), and an object (or 
  796.       instance) of that class can execute any of those methods. 
  797.  
  798.    o  SOM classes can also take advantage of multiple inheritance, which means 
  799.       that a new class is jointly derived from two or more parent classes.  In 
  800.       this case, the derived class inherits methods from all of its parents 
  801.       (and all of its ancestors), giving it greatly expanded capabilities.  In 
  802.       the event that different parents have methods of the same name that 
  803.       execute differently, SOM provides ways for avoiding conflicts. 
  804.  
  805.    o  In the SOM run time, classes are themselves objects.  That is, classes 
  806.       have their own methods and interfaces, and are themselves defined by 
  807.       other classes. For this reason, a class is often called a class object. 
  808.       Likewise, the terms class methods and class variables are used to 
  809.       distinguish between the methods/variables of a class object vs. those of 
  810.       its instances.  (Note that the type of an object is not the same as the 
  811.       type of its class, which as a "class object" has its own type.) 
  812.  
  813.    o  A class that defines the implementation of class objects is called a 
  814.       metaclass.  Just as an instance of a class is an object, so an instance 
  815.       of a metaclass is a class object.  Moreover, just as an ordinary class 
  816.       defines methods that its objects respond to, so a metaclass defines 
  817.       methods that a class object responds to.  For example, such methods might 
  818.       involve operations that execute when a class (that is, a class object) is 
  819.       creating an instance of itself (an object).  Just as classes are derived 
  820.       from parent classes, so metaclasses can be derived from parent 
  821.       metaclasses, in order to define new functionality for class objects. 
  822.  
  823.    o  The SOM system contains three primitive classes that are the basis for 
  824.       all subsequent classes: 
  825.  
  826.            SOMObject      the root ancestor class for all SOM classes, 
  827.  
  828.            SOMClass       the root ancestor class for all SOM metaclasses, and 
  829.  
  830.            SOMClassMgr    the class of the SOMClassMgrObject, an object created 
  831.                           automatically during SOM initialization, to maintain 
  832.                           a registry of existing classes and to assist in 
  833.                           dynamic class loading/unloading. 
  834.  
  835.          SOMClass is defined as a subclass (or child) of SOMObject and inherits 
  836.          all generic object methods; this is why instances of a metaclass are 
  837.          class objects  (rather than simply classes) in the SOM run time. 
  838.  
  839.  SOM classes are designed to be language neutral. That is, SOM classes can be 
  840.  implemented in one programming language and used in programs of another 
  841.  language. To achieve language neutrality, the interface for a class of objects 
  842.  must be defined separately from its implementation. That is, defining 
  843.  interface and implementation requires two completely separate steps (plus an 
  844.  intervening compile), as follows: 
  845.  
  846.    o  An interface is the information that a program must know in order to use 
  847.       an object of a particular class. This interface is described in an 
  848.       interface definition (which is also the class definition), using a formal 
  849.       language whose syntax is independent of the programming language used to 
  850.       implement the class's methods. For SOM classes, this is the SOM Interface 
  851.       Definition Language (SOM IDL). The interface is defined in a file known 
  852.       as the IDL source file (or, using its extension, this is often called the 
  853.       .idl file). 
  854.  
  855.       An interface definition is specified within the interface declaration (or 
  856.       interface statement) of the .idl file, which includes: 
  857.  
  858.            (a)   the interface name (or class name) and the name(s) of the 
  859.                  class's parent(s), and 
  860.  
  861.            (b)   the names of the class's attributes and the signatures of its 
  862.                  new methods. (Recall that the complete set of available 
  863.                  methods also includes all inherited methods.) 
  864.  
  865.          Each method signature includes the method name, and the type and order 
  866.          of its arguments, as well as the type of its return value (if any). 
  867.          Attributes are instance variables for which "set" and "get" methods 
  868.          will automatically be defined, for use by the application program. 
  869.          (By contrast, instance variables that are not attributes are hidden 
  870.          from the user.) 
  871.  
  872.    o  Once the IDL source file is complete, the SOM Compiler is used to analyze 
  873.       the .idl file and create the implementation template file, within which 
  874.       the class implementation will be defined. Before issuing the SOM Compiler 
  875.       command, sc, the class implementor can set an environment variable that 
  876.       determines which emitters (output-generating programs) the SOM Compiler 
  877.       will call and, consequently, which programming language and operating 
  878.       system the resulting binding files will relate to. (Alternatively, this 
  879.       emitter information can be placed on the command line for sc.)  In 
  880.       addition to the implementation template file itself, the binding files 
  881.       include two language-specific header files that will be #included in the 
  882.       implementation template file and in application program files. The header 
  883.       files define many useful SOM macros, functions, and procedures that can 
  884.       be invoked from the files that include the header files. 
  885.  
  886.    o  The implementation of a class is done by the class implementor in the 
  887.       implementation template file (often called just the implementation file 
  888.       or the template file).  As produced by the SOM Compiler, the template 
  889.       file contains stub procedures  for each method of the class.  These are 
  890.       incomplete method procedures that the class implementor uses as a basis 
  891.       for implementing the class by writing the corresponding code in the 
  892.       programming language of choice. 
  893.  
  894.  In summary, the process of implementing a SOM class includes using the SOM IDL 
  895.  syntax to create an IDL source file that specifies the interface to a class of 
  896.  objects--that is, the methods and attributes that a program can use to 
  897.  manipulate an object of that class. The SOM Compiler is then run to produce an 
  898.  implementation template file and two binding (header) files that are specific 
  899.  to the designated programming language and operating system. Finally, the 
  900.  class implementor writes language-specific code in the template file to 
  901.  implement the method procedures. 
  902.  
  903.  At this point, the next step is to write the application (or client) 
  904.  program(s) that use the objects and methods of the newly implemented class. 
  905.  (Observe, here, that a programmer could write an application program using a 
  906.  class implemented entirely by someone else.)  If not done previously, the SOM 
  907.  compiler is run to generate usage bindings for the new class, as appropriate 
  908.  for the language used by the client program (which may be different from the 
  909.  language in which the class was implemented). After the client program is 
  910.  finished, the programmer compiles and links it using a language-specific 
  911.  compiler, and then executes the program. (Notice again, the client program can 
  912.  invoke methods on objects of the SOM class without knowing how those methods 
  913.  are implemented.) 
  914.  
  915.  
  916. ΓòÉΓòÉΓòÉ 4.1.1. Development of the Tutorial examples ΓòÉΓòÉΓòÉ
  917.  
  918.    o  Example 1--Implementing a simple class with one method 
  919.  
  920.       Prints a default message when the "sayHello" method is invoked on an 
  921.       object of the "Hello" class. 
  922.  
  923.    o  Example 2--Adding an attribute to the Hello class 
  924.  
  925.       Defines a "msg" attribute for the "sayHello" method to use. The client 
  926.       program "sets" a message; then the "sayHello" method "gets" the message 
  927.       and prints it. (There is no defined message when an object of the "Hello" 
  928.       class is first created.) 
  929.  
  930.    o  Example 3--Overriding an inherited method 
  931.  
  932.       Overrides the SOMobjects method somPrintSelf so that invoking this method 
  933.       on an object of the "Hello" class will not only display the class name 
  934.       and the object's location, but will also include the object's message 
  935.       attribute. 
  936.  
  937.    o  Example 4--Initializing a SOM object. 
  938.  
  939.       Overrides the default initialization method,  somDefaultInit, to 
  940.       illustrate how an object's instance variables can be initialized when the 
  941.       object is created. 
  942.  
  943.    o  Example 5--Using multiple inheritance 
  944.  
  945.       Extends the "Hello" class to provide it with multiple inheritance (from 
  946.       the "Disk;" and "Printer" classes.) The "Hello" interface defines an enum 
  947.       and an "output" attribute that takes its value from the enum (either 
  948.       "screen", "printer", or "disk"). The client program "sets" the form of 
  949.       "output" before invoking the "sayHello" method to send a "msg"(defined as 
  950.       in Example 4). 
  951.  
  952.  
  953. ΓòÉΓòÉΓòÉ 4.2. Basic Steps for Implementing SOM Classes ΓòÉΓòÉΓòÉ
  954.  
  955. Implementing and using SOM classes in C or C++ involves the following steps, 
  956. which are explicitly illustrated in the examples of this tutorial: 
  957.  
  958.    1. Define the interface to objects of the new class (that is, the interface 
  959.       declaration), by creating a .idl file. 
  960.  
  961.    2. Run the SOM Compiler on the .idl file (by issuing the sc command on AIX 
  962.       or OS/2, or by issuing the somc command on Windows) to produce the 
  963.       following binding files: 
  964.  
  965.         o  Template implementation file  a .c file for C programmers, or  a .C 
  966.            file (on AIX) or a .cpp file (on OS/2 or Windows) for C++ 
  967.            programmers; 
  968.  
  969.         o  Header file to be included in the implementation file  a .ih file 
  970.            for C programmers, or  a .xih file for C++ programmers; and 
  971.  
  972.         o  Header file to be included in client programs that use the class  a 
  973.            .h file for C clients, or  a .xh file for C++ clients. 
  974.  
  975.           To specify whether the SOM Compiler should produce C or C++ bindings, 
  976.           set the value of the SMEMIT environment variable or use the "-s" 
  977.           option of the sc or somc command, as described in Section 4.3, "The 
  978.           SOM Compiler." By default, the SOM Compiler produces C bindings. 
  979.  
  980.    3. Customize the implementation, by adding code to the template 
  981.       implementation file. 
  982.  
  983.    4. Create a client program that uses the class. 
  984.  
  985.    5. Compile and link the client code with the class implementation, using a C 
  986.       or C++ compiler. 
  987.  
  988.    6. Execute the client program. 
  989.  
  990.  The following examples illustrate appropriate syntax for defining interface 
  991.  declarations in a .idl file, including designating the methods that the 
  992.  class's instances will perform.  In addition, example template implementation 
  993.  files contain typical code that the SOM Compiler produces. Explanations 
  994.  accompanying each example discuss topics that are significant to the 
  995.  particular example; full explanations of the SOM IDL syntax are contained in 
  996.  Chapter 4, "SOM IDL and the SOM Compiler." Customization of each 
  997.  implementation file (step 3) is illustrated in C and C++. 
  998.  
  999.  Note 
  1000.  
  1001.    o  The Tutorial assumes you will work through the examples in order. If you 
  1002.       do not do so, the code that the SOM Compiler generates from your revised 
  1003.       .idl file may vary slightly from what you see in the Tutorial. 
  1004.  
  1005.    o  When the SOMobjects Toolkit is installed, a choice is made between 
  1006.       "somcorba" and "somstars" for the style of C bindings the SOM Compiler 
  1007.       will generate.  The Tutorial examples use the "somcorba" style, where an 
  1008.       interface name used as a type indicates a pointer to an object, as 
  1009.       required by strict CORBA bindings.  Consequently, as the examples show, a 
  1010.       "*" does not explicitly appear for types that are pointers to objects. 
  1011.       If your system was installed for "somstars" C bindings, you can set the 
  1012.       environment variable SMADDSTAR=1 or use the SOM Compiler option 
  1013.       "-maddstar" to request bindings that use explicit pointer stars. For more 
  1014.       information, see "Declaring object variables" in Chapter 3, "Using SOM 
  1015.       Classes in Client Programs" and "Object types" in Chapter 4, "SOM IDL and 
  1016.       the SOM Compiler." 
  1017.  
  1018.  
  1019. ΓòÉΓòÉΓòÉ 4.2.1. Example 1--Implementing a Simple Class with One Method ΓòÉΓòÉΓòÉ
  1020.  
  1021. Example 1 defines a class "Hello" which introduces one new method, "sayHello". 
  1022. When invoked from a client program, the "sayHello" method will print the fixed 
  1023. string "Hello, World!"  The example follows the six steps described in the 
  1024. preceding topic, "Basic Steps for Implementing SOM Classes." 
  1025.  
  1026.    1. Define the interface to class "Hello", which inherits methods from the 
  1027.       root class SOMObject and introduces one new method, "sayHello". Define 
  1028.       these IDL specifications in the file "hello.idl". 
  1029.  
  1030.       The "interface" statement introduces the name of a new class and any 
  1031.       parents (base classes) it may have (here, the root class SOMObject).  The 
  1032.       body of the interface declaration introduces the method "sayHello." 
  1033.       Observe that method declarations in IDL have syntax similar to C and C++ 
  1034.       function prototypes: 
  1035.  
  1036.             #include <somobj.idl>  //# Get the parent class definition.
  1037.  
  1038.             interface Hello : SOMObject
  1039.             /*  This is a simple class that demonstrates how to define the
  1040.              *  interface to a new class of objects in SOM IDL.
  1041.              */
  1042.             {
  1043.                 void sayHello();
  1044.                 // This method outputs the string "Hello, World!".
  1045.                    /* On Windows, use: string sayHello();
  1046.                     * This method returns the string "Hello, World!". */
  1047.             };
  1048.  
  1049.       Note that the method "sayHello" has no (explicit) arguments and returns 
  1050.       no value (except on Windows, which returns a string). The characters "//" 
  1051.       start a line comment, which finishes at the end of the line.  The 
  1052.       characters "/*" start a block comment which finishes with the "*/". Block 
  1053.       comments do not nest. The two comment styles can be used interchangeably. 
  1054.       Throw-away comments are also permitted in a .idl file; they are ignored 
  1055.       by the SOM Compiler.  Throw-away comments start with the characters "//#" 
  1056.       and terminate at the end of the line. 
  1057.  
  1058.       Note:  For simplicity, this IDL fragment does not include a releaseorder 
  1059.              modifier; consequently, the SOM Compiler will issue a warning for 
  1060.              the method "sayHello". For directions on using the releaseorder 
  1061.              modifier to remove this warning, see the topic "Modifier 
  1062.              statements" in Chapter 4, "Implementing Classes in SOM". 
  1063.  
  1064.    2. Run the SOM Compiler to produce binding files and an implementation 
  1065.       template (that is, issue the sc command): 
  1066.  
  1067.             > sc -s"c;h;ih" hello.idl      (for C bindings on AIX or OS/2)
  1068.             > sc -s"xc;xh;xih" hello.idl   (for C++ bindings on AIX or OS/2)
  1069.  
  1070.       When set to generate C binding files, the SOM Compiler generates the 
  1071.       following implementation template file, named "hello.c". The template 
  1072.       implementation file contains stub procedures for each new method.  These 
  1073.       are procedures whose bodies are largely vacuous, to be filled in by the 
  1074.       implementor. (Unimportant details have been removed for this tutorial.) 
  1075.  
  1076.             #include <hello.ih>
  1077.             /*
  1078.              *  This method outputs the string "Hello, World!".
  1079.              */
  1080.  
  1081.             SOM_Scope  void   SOMLINK  sayHello(Hello somSelf, Environment *ev)
  1082.             {
  1083.                 /* HelloData *somThis = HelloGetData(somSelf); */
  1084.                 HelloMethodDebug("Hello", "sayHello");
  1085.             }
  1086.  
  1087.       The terms SOM_Scope and SOMLINK appear in the prototype for all stub 
  1088.       procedures, but they are defined by SOM and are not of interest to the 
  1089.       developer. In the method procedure for the "sayHello" method, "somSelf" 
  1090.       is a pointer to the target object (here, an instance of the class 
  1091.       "Hello") that will respond to the method. A "somSelf" parameter appears 
  1092.       in the procedure prototype for every method, since SOM requires every 
  1093.       method to act on some object. 
  1094.  
  1095.       The target object is always the first parameter of a method's procedure, 
  1096.       although it should not be included in the method's IDL specification. The 
  1097.       second parameter (which also is not included in the method's IDL 
  1098.       specification) is the parameter (Environment *ev).  This parameter can be 
  1099.       used by the method to return exception information if the method 
  1100.       encounters an error.  (Contrast the prototype for the "sayHello" method 
  1101.       in steps 1 and 2 above.) 
  1102.  
  1103.       The remaining lines of the template above are not pertinent at this 
  1104.       point.  (For those interested, they are discussed in section 5.4 of 
  1105.       Chapter 5, "Implementing SOM Classes.")  The file is now ready for 
  1106.       customization with the C code needed to implement method "sayHello". 
  1107.  
  1108.       When set to generate C++ binding files, the SOM Compiler generates an 
  1109.       implementation template file, "hello.C" (on AIX) or "hello.cpp (on OS/2), 
  1110.       similar to the one above.  (Chapter 5 discusses the implementation 
  1111.       template in more detail.) 
  1112.  
  1113.       Recall that, in addition to generating a template implementation file, 
  1114.       the SOM Compiler also generates implementation bindings (in a header file 
  1115.       to be included in the implementation file) and usage bindings (in a 
  1116.       header file to be included in client programs).  These files are named 
  1117.       "hello.ih" and "hello.h" for C bindings, and are "hello.xih" and 
  1118.       "hello.xh" for C++ bindings. Notice that the "hello.c" file shown above 
  1119.       includes the "hello.ih" implementation binding file. 
  1120.  
  1121.    3. Customize the implementation, by adding code to the template 
  1122.       implementation file. 
  1123.  
  1124.       Modify the body of the "sayHello" method procedure in the "hello.c" (or, 
  1125.       for C++,"hello.C" on AIX, "hello.cpp" on OS/2) implementation file so 
  1126.       that the "sayHello" method prints "Hello, World!": 
  1127.  
  1128.             SOM_Scope void   SOMLINK sayHello(Hello somSelf, Environment *ev)
  1129.             {
  1130.                 /* HelloData *somThis = HelloGetData(somSelf); */
  1131.                 HelloMethodDebug("Hello","sayHello");
  1132.  
  1133.                 printf("Hello, World!\n");
  1134.             }
  1135.  
  1136.    4. Create a client program that uses the class. 
  1137.  
  1138.       Write a program "main" that creates an instance (object) of the "Hello" 
  1139.       class and invokes the method "sayHello" on that object. 
  1140.  
  1141.       A C programmer would write the following program in "main.c", using the 
  1142.       bindings defined in the "hello.h" header file: 
  1143.  
  1144.             #include <hello.h>
  1145.  
  1146.             int main(int argc, char *argv[])
  1147.             {
  1148.                 /* Declare a variable to point to an instance of Hello */
  1149.                 Hello obj;
  1150.  
  1151.                 /* Create an instance of the Hello class */
  1152.                 obj = HelloNew();
  1153.  
  1154.                 /* Execute the "sayHello" method */
  1155.                 _sayHello(obj, somGetGlobalEnvironment());
  1156.  
  1157.                 /* Free the instance: */
  1158.                 _somFree(obj);
  1159.                 return (0);
  1160.             }
  1161.  
  1162.       Notice the statement obj = HelloNew();  The "hello.h" header file 
  1163.       automatically contains the SOM-defined macro <className>New(), which is 
  1164.       used to create an instance of the <className> class (here, the "Hello" 
  1165.       class). 
  1166.  
  1167.       Also notice that, in C, a method is invoked on an object by using the 
  1168.       form: 
  1169.  
  1170.             _<methodName>(<objectName>, <environment_argument>, <other_method_arguments>)
  1171.  
  1172.       as used above in the statement _sayHello(obj, somGetGlobalEnvironment()). 
  1173.       As shown in this example, the SOM-provided somGetGlobalEnvironment 
  1174.       function can be used to supply the (Environment *) argument of the 
  1175.       method. 
  1176.  
  1177.       Finally, the code uses the method somFree, which SOM also provides, to 
  1178.       free the object created by HelloNew().  Notice that  somFree does not 
  1179.       require an (Environment *) argument. This is because the method 
  1180.       procedures for some of the classes in the SOMobjects Toolkit (including 
  1181.       SOMObject, SOMClass, and SOMClassMgr) do not have an Environment 
  1182.       parameter, to ensure compatibility with the previous release of SOM.  The 
  1183.       documentation for each SOM-kernel method in the SOMobjects Developer 
  1184.       Toolkit: Programmers Reference Manual indicates whether an Environment 
  1185.       parameter is used. 
  1186.  
  1187.       A C++ programmer would write the following program in "main.C" (on AIX) 
  1188.       or "main.cpp" (on OS/2), using the bindings defined in the "hello.xh" 
  1189.       header file: 
  1190.  
  1191.             #include <hello.xh>
  1192.  
  1193.             int main(int argc, char *argv[])
  1194.             {
  1195.                 /* Declare a variable to point to an instance of Hello */
  1196.                 Hello *obj;
  1197.  
  1198.                 /* Create an instance of the Hello class */
  1199.                 obj = new Hello;
  1200.  
  1201.                 /* Execute the "sayHello" method */
  1202.                 obj->sayHello(somGetGlobalEnvironment());
  1203.  
  1204.                 obj->somFree();
  1205.                 return (0);
  1206.             }
  1207.  
  1208.       Notice that the only argument passed to the "sayHello" method by a C++ 
  1209.       client program is the Environment pointer.  (Contrast this with the 
  1210.       invocation of "sayHello" in the C client program, above. 
  1211.  
  1212.    5. Compile and link the client code with the class implementation. 
  1213.  
  1214.       Note: On AIX or OS/2, the environment variable SOMBASE represents the 
  1215.       directory in which SOM has been installed. 
  1216.  
  1217.       Under AIX, for C programmers: 
  1218.  
  1219.             > xlc -I. -I$SOMBASE/include -o hello main.c hello.c  -L$SOMBASE/lib -l somtk
  1220.  
  1221.       Under AIX, for C++ programmers: 
  1222.  
  1223.             > xlc -I. -I$SOMBASE/include -o hello main.C hello.C  -L$SOMBASE/lib -lsomtk
  1224.  
  1225.       Under OS/2, for C programmers: 
  1226.  
  1227.             > set LIB=%SOMBASE%\lib;%LIB%
  1228.             > icc -I. -I%SOMBASE%\include -Fe hello main.c hello.c  somtk.lib
  1229.  
  1230.       Under OS/2, for C++ programmers: 
  1231.  
  1232.             > set LIB=%SOMBASE%\lib;%LIB%
  1233.             > icc -I. -I\%SOMBASE%\include -Fe hello main.cpp hello.cpp  somtk.lib
  1234.  
  1235.    6. Execute the client program. 
  1236.  
  1237.             > hello
  1238.             Hello, World!
  1239.       Example 2 will extend the "Hello" class to introduce an "attribute". 
  1240.  
  1241.  The following list contains the file extensions for SOM files: 
  1242.  
  1243.    o   IDL source file: 
  1244.  
  1245.            .idl      for all users 
  1246.  
  1247.    o   Implementation template file 
  1248.  
  1249.            .c        for C, all systems 
  1250.            .C        for C++, on AIX 
  1251.            .cpp      for C++, on OS/2 or Windows 
  1252.  
  1253.    o   Header file for implementation file: 
  1254.  
  1255.            .ih       for C 
  1256.            .xih      for C++ 
  1257.  
  1258.    o   Header file for program file: 
  1259.  
  1260.            .h        for C 
  1261.            .xh       for C++ 
  1262.  
  1263.  
  1264. ΓòÉΓòÉΓòÉ 4.2.2. Example 2--Adding an Attribute to the Hello class ΓòÉΓòÉΓòÉ
  1265.  
  1266. Example 1 introduced a class "Hello" which has a method "sayHello" that prints 
  1267. the fixed string "Hello, World!"  Example 2 extends the "Hello" class so that 
  1268. clients can customize the output from the method "sayHello". 
  1269.  
  1270.    1. Modify the interface declaration for the class definition in "hello.idl." 
  1271.  
  1272.       Class "Hello" is extended by adding an attribute that we call "msg". 
  1273.       Declaring an attribute is equivalent to defining "get" and "set" methods. 
  1274.       For example, specifying: 
  1275.  
  1276.                attribute string msg;
  1277.  
  1278.       is equivalent to defining the two methods: 
  1279.  
  1280.                string _get_msg();
  1281.                void  _set_msg(in string msg);
  1282.  
  1283.       Thus, for convenience, an attribute can be used (rather than an instance 
  1284.       variable) in order to use the automatically defined "get" and "set" 
  1285.       methods without having to write their method procedures. The new 
  1286.       interface specification for "Hello" that results from adding attribute 
  1287.       "msg" to the "Hello" class is as follows (with some comment lines 
  1288.       omitted): 
  1289.  
  1290.                #include <somobj.idl>
  1291.  
  1292.                interface Hello : SOMObject
  1293.                {
  1294.                  void  sayHello();
  1295.  
  1296.                  attribute string msg;
  1297.                       //# This is equivalent to defining the methods:
  1298.                       //#     string _get_msg();
  1299.                       //#      void  _set_msg(string msg);
  1300.                };
  1301.  
  1302.    2. Re-run the SOM Compiler on the updated idl file, as in example 1.  This 
  1303.       produces new header files and updates the existing implementation file, 
  1304.       if needed, to reflect changes made to the .idl file.  In this example, 
  1305.       the implementation file is not modified by the SOM Compiler. 
  1306.  
  1307.    3. Customize the implementation. 
  1308.  
  1309.       Customize the implementation file by modifying the print statement in the 
  1310.       "sayHello" method procedure. This example prints the contents of the 
  1311.       "msg" attribute (which must be initialized in the client program) by 
  1312.       invoking the "_get_msg" method. Notice that, because the "_get_msg" 
  1313.       method name begins with an underscore, the method is invoked with two 
  1314.       leading underscores (for C only). 
  1315.  
  1316.                SOM_Scope void   SOMLINK sayHello(Hello somSelf, Environment  *ev)
  1317.                {
  1318.                    /* HelloData *somThis = HelloGetData(somSelf); */
  1319.                    HelloMethodDebug("Hello", "sayHello");
  1320.  
  1321.                    printf("%s\n", __get_msg(somSelf, ev));
  1322.  
  1323.                    /* for  C++, use   somSelf->_get_msg(ev);  */
  1324.                }
  1325.  
  1326.       This implementation assumes that "_set_msg" has been invoked to 
  1327.       initialize the "msg" attribute before the "_get_msg" method is invoked by 
  1328.       the "sayHello" method.  This initialization can be done within the client 
  1329.       program. 
  1330.  
  1331.    4. Update the client program. 
  1332.  
  1333.       Modify the client program so that the "_set_msg" method is invoked to 
  1334.       initialize the "msg" attribute before the "sayHello" method is invoked. 
  1335.       Notice that, because the "_set_msg" method name begins with an 
  1336.       underscore, the C client program invokes the method with two  leading 
  1337.       underscores. 
  1338.  
  1339.       For C programmers: 
  1340.  
  1341.                #include <hello.h>
  1342.  
  1343.                int main(int argc, char *argv[])
  1344.                {
  1345.                    Hello obj;
  1346.  
  1347.                    obj = HelloNew();
  1348.                    /* Set the msg text */
  1349.                    __set_msg(obj, somGetGlobalEnvironment(), "Hello World Again");
  1350.  
  1351.                    /* Execute the "sayHello" method */
  1352.                    _sayHello(obj, somGetGlobalEnvironment());
  1353.  
  1354.                    _somFree(obj);
  1355.                    return (0);
  1356.                }
  1357.  
  1358.       For C++ programmers: 
  1359.  
  1360.                #include <hello.xh>
  1361.  
  1362.                int main(int argc, char *argv[])
  1363.                {
  1364.                    Hello *obj;
  1365.                    obj = new Hello;
  1366.  
  1367.                    /* Set the msg text */
  1368.                    obj->_set_msg(somGetGlobalEnvironment(), "Hello World Again");
  1369.  
  1370.                    /* Execute the "sayHello" method */
  1371.                    obj->sayHello(somGetGlobalEnvironment());
  1372.  
  1373.                    obj->somFree();
  1374.                    return (0);
  1375.                }
  1376.  
  1377.    5. Compile and link the client program, as before. 
  1378.  
  1379.    6. Execute the client program: 
  1380.  
  1381.                > hello
  1382.                Hello World Again
  1383.  
  1384.       The next example extends the "Hello" class to override (redefine) one of 
  1385.       the methods it inherits from its parent class, SOMObject. 
  1386.  
  1387.  
  1388. ΓòÉΓòÉΓòÉ 4.2.3. Attributes vs instance variables ΓòÉΓòÉΓòÉ
  1389.  
  1390. As an alternative to defining "numberObjs" as an attribute, it could be defined 
  1391. as an instance variable, with a "get_numberObjs" method also defined for 
  1392. retrieving its value.  Instance variables are declared in an implementation 
  1393. statement, as shown below: 
  1394.  
  1395.    interface Hello
  1396.    {
  1397.    string get_msg() ;
  1398.    void set_msg(in string msg);
  1399.  
  1400.    #ifdef __SOMIDL__
  1401.    implementation
  1402.    {
  1403.        string message;
  1404.    };
  1405.    #endif
  1406.    };
  1407.  
  1408. As demonstrated in this example, one disadvantage to using an instance variable 
  1409. is that the "get_msg" and "set_msg" methods must be defined in the 
  1410. implementation file by the class implementor. For attributes, by contrast, 
  1411. default implementations of the "get" and "set" methods are generated 
  1412. automatically by the SOM Compiler in the .ih and .xih header files. 
  1413.  
  1414. Note: For some attributes (particularly those involving structures, strings, 
  1415. and pointers) the default implementation generated by the SOM Compiler for the 
  1416. "set" method may not be suitable. This happens because the SOM Compiler only 
  1417. performs a "shallow copy," which typically is not useful for distributed 
  1418. objects with these types of attributes.  In such cases, it is possible to write 
  1419. your own implementations, as you do for any other method, by specifying the 
  1420. "noset/noget" modifiers for the attribute. (See the subtopic "Modifier 
  1421. statements" in Chapter 4 "SOM IDL and the SOM Compiler.") 
  1422.  
  1423. Regardless of whether you let the SOM Compiler generate your implementations or 
  1424. not, if access to instance data is required, either from a subclass or a client 
  1425. program, then this access should be facilitated by using an attribute. 
  1426. Otherwise, instance data can be defined in the "implementation" statement as 
  1427. above (using the same syntax as used to declare variables in C or C++), with 
  1428. appropriate methods defined to access it. For more information about 
  1429. "implementation" statements, see the topic "Implementation statements" in 
  1430. Chapter 4. 
  1431.  
  1432. As an example where instance variables would be used (rather than attributes), 
  1433. consider a class "Date" that provides a method for returning the current date. 
  1434. Suppose the date is represented by three instance variables--"mm", "dd", and 
  1435. "yy". Rather than making "mm", "dd", and "yy" attributes (and allowing clients 
  1436. to access them directly), "Date" defines "mm", "dd", and "yy" as instance 
  1437. variables in the "implementation" statement, and defines a method "get_date" 
  1438. that converts "mm", "dd", and "yy" into a string of the form "mm/dd/yy": 
  1439.  
  1440.    interface Date
  1441.    {
  1442.            string get_date() ;
  1443.  
  1444.    #ifdef __SOMIDL__
  1445.    implementation
  1446.    {
  1447.        long mm,dd,yy;
  1448.    };
  1449.    #endif
  1450.    };
  1451.  
  1452. To access instance variables that a class introduces from within the class 
  1453. implementation file, two forms of notation are available: 
  1454.  
  1455. somThis->variableName 
  1456.  
  1457. or 
  1458.  
  1459. _variableName 
  1460.  
  1461. For example, the implementation for "get_date" would 
  1462.  
  1463.       access the "mm" instance variable as somThis->mm or _mm, 
  1464.       access "dd"  as somThis->dd or _dd, and 
  1465.       access "yy" as somThis->yy or _yy. 
  1466.  
  1467.  In C++ programs, the _variableName  form is available only if the programmer 
  1468.  first defines the macro VARIABLE_MACROS (that is, enter #define 
  1469.  VARIABLE_MACROS) in the implementation file prior to including the .xih file 
  1470.  for the class. 
  1471.  
  1472.  
  1473. ΓòÉΓòÉΓòÉ 4.2.4. Example 3--Overriding an Inherited Method ΓòÉΓòÉΓòÉ
  1474.  
  1475. An important aspect of OOP programming is the ability of a subclass to replace 
  1476. an inherited method implementation with a new implementation especially 
  1477. appropriate to its instances.  This is called overriding  a method.  Sometimes, 
  1478. a class may introduce methods that every descendant class is expected to 
  1479. override.  For example, SOMobject  introduces the somPrintSelf method, and a 
  1480. good SOM programmer will generally override this method when implementing a new 
  1481. class. 
  1482.  
  1483. The purpose of somPrintSelf is to print a brief description of an object.  The 
  1484. method can be useful when debugging an application that deals with a number of 
  1485. objects of the same class--assuming the class designer has overridden 
  1486. somPrintSelf with a message that is useful in distinguishing different objects 
  1487. of the class.  For example, the implementation of somPrintSelf provided by 
  1488. SOMobjects simply prints the class of the object and its address in memory. 
  1489. SOMclass overrides this method so that, when somPrintSelf is invoked on a class 
  1490. object, the name of the class will print. 
  1491.  
  1492. This example illustrates how somPrintSelf might be overridden for the "Hello" 
  1493. class.  An important identifying characteristic of "Hello" objects is the 
  1494. message they hold; thus, the following steps illustrate how somPrintSelf could 
  1495. be overridden in "Hello" to provide this information. 
  1496.  
  1497.    1. Modify the interface declaration in "hello.idl." 
  1498.  
  1499.       To override the somPrintSelf method in "Hello", additionalinformation 
  1500.       must be provided in "hello.idl" in the form of an implementation 
  1501.       statement, which gives extra information about the class, its methods and 
  1502.       attributes, and any instance variables.  (The previous examples omitted 
  1503.       the optional "implementation" statement, because it was not needed.) 
  1504.  
  1505.       In the current example, the "implementation" statement introduces the 
  1506.       modifiers  for the "Hello" class, as follows. 
  1507.  
  1508.                #include <somobj.idl>
  1509.  
  1510.                interface Hello : SOMObject
  1511.                {
  1512.                  void sayHello();
  1513.  
  1514.                  attribute string msg;
  1515.  
  1516.                  #ifdef __SOMIDL__
  1517.                  implementation
  1518.                  {
  1519.                          //# Method Modifiers:
  1520.                          somPrintSelf: override;
  1521.                          // Override the inherited implementation of somPrintSelf.
  1522.                  };
  1523.                  #endif
  1524.  
  1525.                  };
  1526.  
  1527.       Here, "somPrintSelf:" introduces a list of modifiers  for the (inherited) 
  1528.       somPrintSelf method in the class "Hello".  Modifiers are like C/C ++ 
  1529.       #pragma commands and give specific implementation details to the 
  1530.       compiler. This example uses only one modifier, "override". Because of the 
  1531.       "override" modifier, when somPrintSelf is invoked on an instance of class 
  1532.       "Hello", Hello's implementation of somPrintSelf (in the implementation 
  1533.       file) will be called, instead of the implementation inherited from the 
  1534.       parent class, SOMObject. 
  1535.  
  1536.       The "#ifdef__SOMIDL__" and "#endif" are standard C and C++ preprocessor 
  1537.       commands that cause the "implementation" statement to be read only when 
  1538.       using the SOM IDL compiler (and not some other IDL compiler). 
  1539.  
  1540.    2. Re-run the SOM Compiler on the updated .idl file, as before.  The SOM 
  1541.       Compiler extends the existing implementation file from Example 2 to 
  1542.       include new stub procedures as needed (in this case, for somPrintSelf). 
  1543.       Below is a shortened version of the C language implementation file as 
  1544.       updated by the SOM Compiler; C++ implementation files are similarly 
  1545.       revised.  Notice that the code previously added to the "sayHello" method 
  1546.       is not disturbed when the SOM Compiler updates the implementation file. 
  1547.  
  1548.                #include <hello.ih>
  1549.  
  1550.                SOM_Scope void   SOMLINK sayHello(Hello somSelf, Environment  *ev)
  1551.                {
  1552.                    /* HelloData *somThis = HelloGetData(somSelf); */
  1553.                    HelloMethodDebug("Hello","sayHello");
  1554.  
  1555.                    printf("%s\n", __get_msg(somSelf, ev));
  1556.                }
  1557.  
  1558.                SOM_Scope void   SOMLINK  somPrintSelf(Hello somSelf)
  1559.                {
  1560.                    HelloData *somThis = HelloGetData(somSelf);
  1561.                    HelloMethodDebug("hello","somPrintSelf");
  1562.  
  1563.                      Hello_parent_SOMObject_somPrintSelf(somSelf);
  1564.                }
  1565.  
  1566.       Note that the SOM Compiler added code allowing the "Hello" class to 
  1567.       redefine somPrintSelf.  The SOM Compiler provides a default 
  1568.       implementation for overriding the somPrintSelf method.  This default 
  1569.       implementation simply calls the "parent method" [the procedure that the 
  1570.       parent class of "Hello" (SOMObject) uses to implement the somPrintSelf 
  1571.       method]. This parent method call is accomplished by the macro 
  1572.       Hello_parent_SOMObject_somPrintSelf defined in "hello.ih." 
  1573.  
  1574.       Notice that the stub procedure for overriding the somPrintSelf method 
  1575.       does not include an Environment parameter. This is because somPrintSelf 
  1576.       is introduced by SOMObject, which does not include the Environment 
  1577.       parameter in any of its methods (to ensure backward compatibility). The 
  1578.       signature for a method cannot change after it has been introduced. 
  1579.  
  1580.    3. Customize the implementation. 
  1581.  
  1582.       Within the new somPrintSelf method procedure, display a brief description 
  1583.       of the object, appropriate to "Hello" objects.  Note that the parent 
  1584.       method call is not needed, so it has been deleted.  Also, direct access 
  1585.       to instance data introduced by the "Hello" class is not required, so the 
  1586.       assignment to "somThis" has been commented out (see the first line of the 
  1587.       procedure). 
  1588.  
  1589.                SOM_Scope void   SOMLINK somPrintSelf(Hello somSelf)
  1590.                {
  1591.                    HelloData *somThis = HelloGetData(somSelf);
  1592.                    HelloMethodDebug("Hello","somPrintSelf");
  1593.  
  1594.                  somPrintf("--a %s object at location %x with msg:s\n",
  1595.                                _somGetClassName(somSelf),
  1596.                                somSelf,
  1597.                                __get_msg(somSelf,0));
  1598.                }
  1599.  
  1600.    4. Update the client program to illustrate the change (also notice the new 
  1601.       message text): 
  1602.  
  1603.       For C programmers: 
  1604.  
  1605.                #include <hello.h>
  1606.  
  1607.                int main(int argc, char *argv[])
  1608.                {
  1609.                    Hello obj;
  1610.                    Environment *ev = somGetGlobalEnvironment();
  1611.  
  1612.                    obj = HelloNew();
  1613.  
  1614.                    /* Set the msg text */
  1615.                    __set_msg(obj, ev, "Hi There");
  1616.  
  1617.                    /* Execute the "somPrintSelf" method */
  1618.                    _somPrintSelf(obj);
  1619.  
  1620.                         _somFree(obj);
  1621.                         return (0);
  1622.                }
  1623.  
  1624.       For C++ programmers: 
  1625.  
  1626.                #include <hello.xh>
  1627.  
  1628.                int main(int argc, char *argv[])
  1629.                {
  1630.                    Hello *obj;
  1631.                    Environment *ev = somGetGlobalEnvironment();
  1632.  
  1633.                    obj = new Hello;
  1634.  
  1635.                    /* Set the msg text */
  1636.                    __setmsg(obj, ev, "Hi There");
  1637.  
  1638.                   /* Execute the "somPrintSelf" method */
  1639.                      obj->somPrintSelf();
  1640.  
  1641.                    obj->somFree();
  1642.                    return (0);
  1643.                }
  1644.  
  1645.    5. Compile and link the client program, as before. 
  1646.  
  1647.    6. Execute the client program, which now outputs the message: 
  1648.  
  1649.                > hello
  1650.                 -- a Hello object at location 20062838 with msg: Hi There
  1651.  
  1652.  
  1653. ΓòÉΓòÉΓòÉ 4.2.5. Example 4--Initializing a SOM Object ΓòÉΓòÉΓòÉ
  1654.  
  1655. The previous example showed how to override the method somPrintSelf, introduced 
  1656. by SOMObject. As mentioned in that example, somPrintSelf should generally b 
  1657. overridden when implementing a new class. Another method introduced by 
  1658. SOMObject  that should generally be overridden is somDefaultInit. The purpose 
  1659. of somDefaultInit is to provide a "default" initializer  for the instance 
  1660. variables introduced by a class. 
  1661.  
  1662. This example shows how to override somDefaultInit to give each "Hello" object's 
  1663. message an initial value when the object is first created. To learn more about 
  1664. initializers than shown in this example (including how to introduce new 
  1665. initializers that take arbitrary arguments, and how to explicitly invoke 
  1666. initializers) read Section 5.5, "Initializing and Uninitializing Objects," in 
  1667. Chapter 5, "Implementing Classes in SOM." 
  1668.  
  1669. The overall process of overriding somDefaultInit is similar to that of the 
  1670. previous example. First, the IDL for "Hello" is modified. In addition to an 
  1671. override  modifier, an init modifier is used to indicate that a stub procedure 
  1672. for an initialization method is desired (the stub procedures for initializers 
  1673. are different from those of normal methods). 
  1674.  
  1675.    1. Modify the interface declaration in "hello.idl." 
  1676.  
  1677.             #include <somobj.idl>
  1678.  
  1679.             interface Hello : SOMObject
  1680.             {
  1681.               void sayHello();
  1682.  
  1683.               attribute string msg;
  1684.  
  1685.             #ifdef __SOMIDL__
  1686.             implementation
  1687.             {
  1688.                 //# Method Modifiers:
  1689.                 somPrintSelf: override;
  1690.                 somDefaultInit: override, init;
  1691.             };
  1692.             #endif
  1693.  
  1694.             };
  1695.  
  1696.    2. Re-run the SOM Compiler on the updated hello.idl file, as before. SOM 
  1697.       Compiler extends the existing implementation file. Below is the 
  1698.       initializer stub procedure that the SOM Compiler adds to the C language 
  1699.       implementation file; C++ implementation files would be similarly revised: 
  1700.  
  1701.             SOM_Scope void SOMLINK
  1702.                       somDefaultInit(Hello somSelf, somInitCtrl *ctrl)
  1703.             {
  1704.               HelloData *somThis; /* set by BeginInitializer */
  1705.               somInitCtrl globalCtrl;
  1706.               somBooleanVector myMask;
  1707.               HelloMethodDebug("Hello", "somDefaultInit");
  1708.               Hello_BeginInitializer_somDefaultInit;
  1709.  
  1710.               Hello_Init_SOMObject_somDefaultInit(somSelf, ctrl);
  1711.               /*
  1712.                * local Hello initialization code added by programmer
  1713.                */
  1714.             }
  1715.  
  1716.    3. Customize the implementation. 
  1717.  
  1718.       Here, the "msg" instance variable is set in the implementation template 
  1719.       (rather than in the client program, as before). Thus, the "msg" is 
  1720.       defined as part of the "Hello" object's initialization. 
  1721.  
  1722.             SOM_Scope void SOMLINK
  1723.                            somDefaultInit(Hello somSelf, somInitCtrl *ctrl)
  1724.             {
  1725.               HelloData *somThis; /* set by BeginInitializer */
  1726.               somInitCtrl globalCtrl;
  1727.               somBooleanVector myMask;
  1728.               HelloMethodDebug("Hello", "somDefaultInit");
  1729.               Hello_BeginInitializer_somDefaultInit;
  1730.  
  1731.               Hello_Init_SOMObject_somDefaultInit(somSelf, ctrl);
  1732.               /*
  1733.                * local Hello initialization code added by programmer
  1734.                */
  1735.               __set_msg(somSelf, "Initial Message");
  1736.             }
  1737.  
  1738.    4. Update the client program to illustrate default initialization. 
  1739.  
  1740.             #include <hello.h>
  1741.             main()
  1742.             {
  1743.                 Hello h = HelloNew();
  1744.  
  1745.                 /* Execute the "somPrintSelf" method */
  1746.                 _somPrintSelf(h);
  1747.             }
  1748.  
  1749.    5. Compile and link the client program, as before. 
  1750.  
  1751.    6. Execute the client program. 
  1752.  
  1753.   > hello
  1754.   -- a Hello object at 200633A8 with msg: Initial Message
  1755.  
  1756.  
  1757. ΓòÉΓòÉΓòÉ 4.2.6. Example 5--Using Multiple Inheritance ΓòÉΓòÉΓòÉ
  1758.  
  1759. The "Hello" class is useful for writing messages to the screen.  So that 
  1760. clients can also write messages to printers and disk files, this example 
  1761. references two additional classes: "Printer" and "Disk".  The "Printer" class 
  1762. will manage messages to a printer, and the "Disk" class will manage messages 
  1763. sent to files. These classes can be defined as follows: 
  1764.  
  1765.    #include <somobj.idl>
  1766.  
  1767.    interface Printer : SOMObject
  1768.    {
  1769.        void stringToPrinter(in string s) ;
  1770.         // This method writes a string to a printer.
  1771.    };
  1772.  
  1773.    #include <somobj.idl>
  1774.  
  1775.    interface Disk : SOMObject
  1776.    {
  1777.         void stringToDisk(in string s) ;
  1778.         // This method writes a string to disk.
  1779.    };
  1780.  
  1781. This example assumes the "Printer" and "Disk" classes are defined separately 
  1782. (in "print.idl" and "disk.idl", for example), are implemented in separate 
  1783. files, and are linked with the other example code.  Given the implementations 
  1784. of the "Printer" and "Disk" interfaces, the "Hello" class can use them by 
  1785. inheriting from them, as illustrated next. 
  1786.  
  1787.    1. Modify the interface declaration in "hello.idl". 
  1788.  
  1789.                #include <disk.idl>
  1790.                #include <printer.idl>
  1791.  
  1792.                interface Hello : Disk, Printer
  1793.                {
  1794.                    void sayHello();
  1795.  
  1796.                    attribute string msg;
  1797.  
  1798.                    enum outputTypes {screen, printer, disk};
  1799.                    // Declare an enumeration for the different forms of output
  1800.  
  1801.                    attribute outputTypes output;
  1802.                    // The current form of output
  1803.  
  1804.                #ifdef __SOMIDL__
  1805.  
  1806.                  implementation {
  1807.                  somDefaultInit: override, init;
  1808.                  };
  1809.                #endif //#  __SOMIDL__
  1810.                };
  1811.  
  1812.       Notice that SOMObject is not listed as a parent of "Hello" above, because 
  1813.       SOMObject is a parent of "Disk" (and of "Printer"). 
  1814.  
  1815.       The IDL specification above declares an enumeration "outputTypes" for the 
  1816.       different forms of output, and an attribute "output" whose value will 
  1817.       depend on where the client wants the output of the "sayHello" method to 
  1818.       go. 
  1819.  
  1820.       Note: SOM IDL allows the use of structures, unions (though with a syntax 
  1821.       different from C or C++), enumerations, constants, and typedefs, both 
  1822.       inside and outside the body of an interface statement. Declarations that 
  1823.       appear inside an interface body will be emitted in the header file (that 
  1824.       is, in "hello.h" or "hello.xh").  Declarations that appear outside of an 
  1825.       interface body do not appear in the header file (unless required by a 
  1826.       special #pragma directive; see the SOM Compiler options in Chapter 4). 
  1827.  
  1828.       SOM IDL also supports all of the C and C++ preprocessor directives, 
  1829.       including conditional compilation, macro processing, and file inclusion. 
  1830.  
  1831.    2. Re-run the SOM Compiler on the updated idl file.. 
  1832.  
  1833.       Unfortunately, when this is done, the implementation for somDefaultInit 
  1834.       is not correctly updated to reflect the addition of two new parents to 
  1835.       "Hello."  This is because the implementation file emitter never changes 
  1836.       the bodies of existing method procedures.  As a result, method procedures 
  1837.       for initializer methods are not given new parent calls when the parents 
  1838.       of a class are changed.  One way to deal with this (when the parents of a 
  1839.       class are changed) is to temporarily rename the method procedure for 
  1840.       initializer methods, and then run the implementation emitter. Once this 
  1841.       is done, the code in the renamed methods can be merged into the new 
  1842.       templates, which will include all the appropriate parent method calls. 
  1843.       When this is done here, the new implementation for somDefaultInit would 
  1844.       appear as: 
  1845.  
  1846.  
  1847.                   SOM_Scope void SOMLINK
  1848.                                  somDefaultInit(Hello somSelf, somInitCtrl *ctrl)
  1849.              {
  1850.                HelloData *somThis; /* set by BeginInitializer */
  1851.                somInitCtrl globalCtrl;
  1852.                somBooleanVector myMask;
  1853.                HelloMethodDebug("Hello", "somDefaultInit");
  1854.                Hello_BeginInitializer_somDefaultINit;
  1855.  
  1856.                 Hello_Init_Disk_somDefaultInit(somSelf, ctrl);
  1857.                 Hello_Init_Printer_somDefaultInit(somSelf, ctrl);
  1858.                /*
  1859.                 * local Hello initialization code added by programmer
  1860.                /*
  1861.                __set_msg(somSelf, "Initial Message");
  1862.             }
  1863.  
  1864.    3. Continue to customize the implementation file, hello.c, as follows. 
  1865.       Notice that the "sayHello" method (last discussed in Example 2) is now 
  1866.       modified to allow alternate ways of outputing a "msg". 
  1867.  
  1868.             SOM_Scope void  SOMLINK sayHello(Hello somSelf, Environment *ev)
  1869.             {
  1870.                 /* HelloData *somThis = HelloGetData(somSelf) ; */
  1871.                 HelloMethodDebug("Hello","sayHello") ;
  1872.                 switch (__get_output(somSelf, ev) ) {
  1873.                         /*  for C++, use:  somSelf->_get_output(ev) */
  1874.                 case Hello_screen:
  1875.                     printf("%s\n", __get_msg(somSelf, ev) );
  1876.                         /*  for C++, use:  somSelf->_get_msg(ev) */
  1877.                     break;
  1878.                 case Hello_printer:
  1879.                     _stringToPrinter(somSelf, ev, __get_msg(somSelf, ev) );
  1880.                         /* for C++, use:
  1881.                          * somSelf->stringToPrinter(ev, somSelf->_get_msg(ev) );
  1882.                          */
  1883.                     break;
  1884.                 case Hello_disk:
  1885.                     _stringToDisk(somSelf, ev, __get_msg(somSelf, ev) );
  1886.                         /*  for C++, use:
  1887.                          *   somSelf->stringToDisk(ev, somSelf->_get_msg(ev) );
  1888.                          */
  1889.                break;
  1890.                 }
  1891.             }
  1892.  
  1893.       The "switch" statement invokes the appropriate method depending on the 
  1894.       value of the "output" attribute.  Notice how the "case" statements 
  1895.       utilize the enumeration values of "outputTypes" declared in "hello.idl" 
  1896.       by prefacing the enumeration names with the class name (Hello_screen, 
  1897.       Hello_printer, and Hello_disk). 
  1898.  
  1899.    4. Update the client program, as illustrated next: 
  1900.  
  1901.                #include <hello.h>
  1902.                        /* for C++, use "hello.xh" and <stdio.h> */
  1903.  
  1904.                int main(int argc, char *argv[])
  1905.                {
  1906.                    Hello a = HelloNew();
  1907.                    Environment *ev = somGetGlobalEnvironment();
  1908.  
  1909.                    /*Invoke "sayHello" on an object and use each output */
  1910.                    _sayHello(a, ev) ; /* for c++, use:a->sayHello(ev);*/
  1911.                     __set_output(a, ev, Hello_printer);
  1912.                                              /* C++: a->_set_output(ev,Hello_printer);*/
  1913.                    _sayHello(a, ev);
  1914.                    __set_output(a, ev, Hello_disk);
  1915.                               /* C++:a->_set_output(ev,Hello-disk);       */
  1916.                    _sayHello(a, ev) ;
  1917.  
  1918.                    _somFree(a) ;  /* for C++, use: a->somFree(); */
  1919.                     return (0);
  1920.                }
  1921.  
  1922.    5. Compile and link the client program as before, except also include the 
  1923.       implementation files for the "Printer" and "Disk" classes in the 
  1924.       compilation. 
  1925.  
  1926.    6. Execute the client program.  Observe that the message that prints is the 
  1927.       "msg" defined in Example 4 as part of the somDefaultInit initialization 
  1928.       of the "Hello" object. 
  1929.  
  1930.        Initial Message
  1931.  
  1932.        Initial Message               -- goes to a Printer
  1933.  
  1934.        Initial Message               -- goes to Disk
  1935.  
  1936.  This tutorial has described features of SOM IDL that will be useful to C and 
  1937.  C++ programmers.  SOM IDL also provides features such as full type checking, 
  1938.  constructs for declaring private methods, and constructs for defining methods 
  1939.  that receive and return pointers to structures.  Chapter 4, "SOM IDL and the 
  1940.  SOM Compiler" gives complete description of the SOM IDL syntax and also 
  1941.  describes how to use the SOM Compiler.  In addition, Chapter 5, "Implementing 
  1942.  Classes in SOM," provides helpful information for completing the 
  1943.  implementation template, for using initializer (somDefaultInit or user-defined 
  1944.  initialization methods), for defining SOM class libraries, and for customizing 
  1945.  various aspects of SOMobjects execution. 
  1946.  
  1947.  
  1948. ΓòÉΓòÉΓòÉ 5. Using SOM Classes in Client Programs ΓòÉΓòÉΓòÉ
  1949.  
  1950. This chapter discusses how to use SOM classes that have already been fully 
  1951. implemented. That is, these topics describe the steps that a programmer uses to 
  1952. instantiate an object and invoke some method(s) on it from within an 
  1953. application program. 
  1954.  
  1955. Who should read this chapter? 
  1956.  
  1957.    o  Programmers who wish to use SOM classes that were originally developed by 
  1958.       someone else will need to know the information in this chapter. These 
  1959.       programmers often may not need the information from any subsequent 
  1960.       chapters. 
  1961.  
  1962.    o  By contrast, class implementers who are creating their own SOM classes 
  1963.       should continue with Chapter 4, "SOM IDL and the SOM Compiler," and 
  1964.       Chapter 5, "Implementing Classes in SOM "for complete information on the 
  1965.       SOM Interface Definition Language (SOM IDL) syntax and other details of 
  1966.       class implementation. 
  1967.  
  1968.  Programs that use a class are referred to as client programs. A client program 
  1969.  can be written in  C, in C++, or in another language. As noted, this chapter 
  1970.  describes how client programs can use SOM classes (classes defined using SOM, 
  1971.  as described in Chapter 2, "Tutorial for Implementing SOM Classes" and in 
  1972.  Chapter 4, "SOM IDL and the SOM Compiler"and Chapter 5 "Implementing Classes 
  1973.  in SOM"). Using a SOM class involves creating instances of a class, invoking 
  1974.  methods on objects, and so forth. All of the methods, functions, and macros 
  1975.  described here can also be used by class implementers within the 
  1976.  implementation file for a class. 
  1977.  
  1978.  Note: "Using a SOM class," as described in this chapter, does not include 
  1979.  subclassing the class in a client program. In particular, the C++ compatible 
  1980.  SOM classes made available in the .xh binding file can not be subclassed in 
  1981.  C++ to create new C++ or SOM classes. 
  1982.  
  1983.  Some of the macros and functions described here are supplied as part of SOM's 
  1984.  C and C++ usage bindings. These bindings are functions and macros defined in 
  1985.  header files to be included in client programs. The usage bindings make it 
  1986.  more convenient for C and C++ programmers to create and use instances of SOM 
  1987.  classes. SOM classes can be also used without the C or C++ bindings, however. 
  1988.  For example, users of other programming languages can use SOM classes, and C 
  1989.  and C++ programmers can use a SOM class without using its language bindings. 
  1990.  The language bindings simply offer a more convenient programmer's interface to 
  1991.  SOM. Vendors of other languages may also offer SOM bindings; check with your 
  1992.  language vendor for possible SOM support. 
  1993.  
  1994.  To use the C or C++ bindings for a class, a client program must include a 
  1995.  header file for the class (using the #include preprocessor directive). For a C 
  1996.  language client program, the file <classFileStem>.h must be included. For a 
  1997.  C++ language client program, the file <classFileStem>.xh must be included. The 
  1998.  SOM Compiler generates these header files from an IDL interface definition. 
  1999.  The header files contain definitions of the macros and functions that make up 
  2000.  the C or C++ bindings for the class. Whether the header files include bindings 
  2001.  for the class's private methods and attributes (in addition to the public 
  2002.  methods and attributes) depends on the IDL interface definition available to 
  2003.  the user, and on how the SOM Compiler was invoked when generating bindings. 
  2004.  
  2005.  Usage binding headers automatically include any other bindings upon which they 
  2006.  may rely. Client programs not using the C or C++ bindings for any particular 
  2007.  class of SOM object (for example, a client program that does not know at 
  2008.  compile time what classes it will be using) should simply include the 
  2009.  SOM-supplied bindings for  SOMObject, provided in the header file "somobj.h" 
  2010.  (for C programs) or"somobj.xh" (for C++ programs). 
  2011.  
  2012.  For each task that a user of a SOM class might want to perform, this chapter 
  2013.  shows how the task would be accomplished by: 
  2014.  
  2015.    o  a C programmer using the C bindings, 
  2016.    o  a C++ programmer using the C++ bindings, or 
  2017.    o  a programmer not using SOM's C or C++ language bindings. 
  2018.  
  2019.  If neither of the first two approaches is applicable, the third approach can 
  2020.  always be used. 
  2021.  
  2022.  
  2023. ΓòÉΓòÉΓòÉ 5.1. An Example Client Program ΓòÉΓòÉΓòÉ
  2024.  
  2025. Following is a C program that uses the class "Hello" (as defined in the 
  2026. Tutorial in Chapter 2). The "Hello" class provides one attribute, "msg", of 
  2027. type string, and one method, "sayHello". The "sayHello" method simply displays 
  2028. the value of the "msg" attribute of the object on which the method is invoked. 
  2029.  
  2030.    #include <hello.h>  /* include the header file for Hello */
  2031.  
  2032.    int main(int argc, char *argv[])
  2033.    {
  2034.        /* declare a variable (obj) that is a
  2035.         * pointer to an instance of the Hello class: */
  2036.        Hello obj;
  2037.  
  2038.        /* create an instance of the Hello class
  2039.         * and store a pointer to it in obj: */
  2040.        obj = HelloNew();
  2041.  
  2042.        /* invoke method _set_msg on obj with the argument
  2043.         * "Hello World Again". This method sets the value of
  2044.         * obj's 'msg' attribute to the specified string.
  2045.         */
  2046.         __set_msg(obj, somGetGlobalEnvironment(), "Hello World Again");
  2047.  
  2048.         /* invoke method sayHello on obj. This method prints
  2049.          * the value of obj's 'msg' attribute.  */
  2050.         _sayHello(obj, somGetGlobalEnvironment());
  2051.  
  2052.         _somFree(obj);
  2053.         return(0);
  2054.    }
  2055.  
  2056. The C++ version of the foregoing client program is shown below: 
  2057.  
  2058.    #include <hello.xh>  /* include the header file for Hello */
  2059.  
  2060.    int main(int argc, char *argv[])
  2061.    {
  2062.        /* declare a variable (obj) that is a
  2063.         * pointer to an instance of the Hello class: */
  2064.        Hello *obj;
  2065.  
  2066.        /* create an instance of the Hello class
  2067.         * and store a pointer to it in obj: */
  2068.        obj = new Hello;
  2069.  
  2070.       /* invoke method _set_msg on obj with the argument
  2071.        * "Hello World Again". This method sets the value of
  2072.        * obj's 'msg' attribute to the specified string.  */
  2073.       obj->_set_msg(somGetGlobalEnvironment(), "Hello World Again");
  2074.  
  2075.       /* invoke method sayHello on obj. This method prints
  2076.        * the value of obj's 'msg' attribute.  */
  2077.       obj->sayHello(somGetGlobalEnvironment());
  2078.  
  2079.       obj->somFree();
  2080.       return(0);
  2081.    }
  2082.  
  2083. These client programs both produce the output: 
  2084.  
  2085. Hello World Again
  2086.  
  2087.  
  2088. ΓòÉΓòÉΓòÉ 5.2. Using SOM Classes the Basics ΓòÉΓòÉΓòÉ
  2089.  
  2090.  
  2091. ΓòÉΓòÉΓòÉ 5.2.1. Declaring object variables ΓòÉΓòÉΓòÉ
  2092.  
  2093. When declaring an object variable, an object interface name defined in IDL is 
  2094. used as the type of the variable. The exact syntax is slightly different for C 
  2095. vs. C++ programmers. Specifically, 
  2096.  
  2097.  <interfaceName>  obj ;   in C programs or 
  2098.  <interfaceName> *obj ;   in C++ programs 
  2099.  
  2100.  declares "obj" to be a pointer to an object that has type <interfaceName>. In 
  2101.  SOM, objects of this type are instances of the SOM class named 
  2102.  <interfaceName>, or of any SOM class derived from this class. Thus, for 
  2103.  example, 
  2104.  
  2105.  Animal obj;              in C programs or 
  2106.  Animal *obj;             in C++ programs 
  2107.  
  2108.  declares "obj" as pointer to an object of type "Animal" that can be used to 
  2109.  reference an instance of the SOM class "Animal" or any SOM class derived from 
  2110.  "Animal". Note that the type of an object need not be the same as its class; 
  2111.  an object of type "Animal" might not be an instance of the "Animal" class 
  2112.  (rather, it might be an instance of some subclass of "Animal" -- the "Cat" 
  2113.  class, perhaps). 
  2114.  
  2115.  All SOM objects are of type SOMObject, even though they may not be instances 
  2116.  of the SOMObject class. Thus, if it is not known at compile time what type of 
  2117.  object the variable will point to, the following declaration can be used: 
  2118.  
  2119.  SOMObject obj;           in C programs or 
  2120.  SOMObject *obj;          in C++ programs. 
  2121.  
  2122.  Because the sizes of SOM objects are not known at compile time, instances of 
  2123.  SOM classes must always be dynamically allocated. Thus, a variable declaration 
  2124.  must always define a pointer to an object. 
  2125.  
  2126.  Note: In the C usage bindings, as within an IDL specification, an interface 
  2127.  name used as a type implicitly indicates a pointer to an object that has that 
  2128.  interface (this is required by the CORBA specification). The C usage bindings 
  2129.  for SOM classes therefore hide the pointer with a C typedef for 
  2130.  <interfaceName>. But this is not appropriate in the C++  usage bindings, which 
  2131.  define a C++ class for <interfaceName>. Thus, it is not correct in C++ to use 
  2132.  a declaration of the form: 
  2133.  
  2134.  <interfaceName>  obj ;   not valid in C++ programs 
  2135.  
  2136.  Note: If a C programmer also prefers to use explicit pointers to 
  2137.  <interfaceName> types, then the SOM Compiler option -maddstar can be used when 
  2138.  the C binding files are generated, and the explicit " *" will then be required 
  2139.  in declarations of object variables. (This option is required for 
  2140.  compatibility with existing SOM OIDL code. For information on using the 
  2141.  -maddstar option, see "Running the SOM Compiler" in Chapter 4, "SOM IDL and 
  2142.  the SOM Compiler.") 
  2143.  
  2144.  Users of other programming languages must also define object variables to be 
  2145.  pointers to the data structure used to represent SOM objects. The way this is 
  2146.  done is programming-language dependent. The header file "somtypes.h" defines 
  2147.  the structure of SOM objects for the C language. 
  2148.  
  2149.  
  2150. ΓòÉΓòÉΓòÉ 5.2.2. Creating instances of a class ΓòÉΓòÉΓòÉ
  2151.  
  2152. For C programmers with usage bindings, SOM provides the <className>New and the 
  2153. <className>Renew macros for creating instances of a class. 
  2154.  
  2155. These macros are illustrated with the following two examples, each of which 
  2156. creates a single instance of class "Hello": 
  2157.  
  2158.    obj = HelloNew();
  2159.    obj = HelloRenew(buffer);
  2160.  
  2161. Using <className>New 
  2162.  
  2163. After verifying that the <className> class object exists, the <className>New 
  2164. macro invokes the somNew method on the class object.  This allocates enough 
  2165. space for a new instance of <className>, creates a new instance of the class, 
  2166. initializes this new object by invoking somDefaultInit on it, and then returns 
  2167. a pointer to it.  The <className>New macro automatically creates the the class 
  2168. object for <className>, as well as its ancestor classes and metaclass, if these 
  2169. objects have not already been created. 
  2170.  
  2171. After a client program has finished using an object created using the 
  2172. <className >New macro, the object should be freed by invoking the method 
  2173. somFree on it: 
  2174.  
  2175.    _somFree(obj);
  2176.  
  2177. After uninitializing the object by invoking somDestruct on it, somFree calls 
  2178. the class object for storage deallocation. This is important because storage 
  2179. for an object created using the <className>New macro is allocated by the class 
  2180. of the object. Thus, only the class of the object can know how to reclaim the 
  2181. object's storage. object for storage deallocation. 
  2182. Using <className>Renew 
  2183.  
  2184. After verifying that the <className> class object exists, the <className>Renew 
  2185. macro invokes the somRenew method on the class object.  <className>Renew is 
  2186. only used when the space for the object has been allocated previously. (Perhaps 
  2187. the space holds an old uninitialized object that is not needed anymore.) This 
  2188. macro converts the given space into a new, initialized instance of <className> 
  2189. and returns a pointer to it.  The programmer is responsible for ensuring that 
  2190. the argument of <className>Renew  points to a block of storage large enough to 
  2191. hold an instance of class <className>. The SOM method somGetInstanceSize can be 
  2192. invoked on the class to determine the amount of memory required. Like 
  2193. <className>New, the <className>Renew macro automatically creates any required 
  2194. class objects that have not already been created. 
  2195.  
  2196. Hint: When creating a large number of class instances, it may be more efficient 
  2197. to allocate at once enough memory to hold all the instances, and then invoke 
  2198. <className>Renew once for each object to be created, rather than performing 
  2199. separate memory allocations. 
  2200. Using <className>NewClass 
  2201.  
  2202. The C and C++ usage bindings for a SOM class also provide static linkage to a 
  2203. <className>NewClass function that can be used to create the class object.  This 
  2204. can be useful if the class object is needed before its instances are created. 
  2205.  
  2206. For example, the following C code uses the function HelloNewClass to create the 
  2207. "Hello" class object. The arguments to this function are defined by the usage 
  2208. bindings, and indicate the version of the class implementation that is assumed 
  2209. by the bindings. (For more detail on creation of classes, see the later 
  2210. section, "Creating a class object.") Once the class object has been created, 
  2211. the example invokes the method somGetInstanceSize  on this class to determine 
  2212. the size of a "Hello" object, uses SOMMalloc to allocate storage, and then uses 
  2213. the HelloRenew macro to create ten instances of the "Hello" class: 
  2214.  
  2215.    #include <hello.h>
  2216.    main()
  2217.    {
  2218.    SOMClass helloCls; /*  A pointer for the Hello class object */
  2219.    Hello objA[10];    /*  an array of Hello instances */
  2220.    unsigned char *buffer;
  2221.    int i;
  2222.    int size;
  2223.  
  2224.    /* create the Hello class object:  */
  2225.    helloCls =  HelloNewClass(Hello_MajorVersion, Hello_MinorVersion);
  2226.  
  2227.    /* get the amount of space needed for a Hello instance:
  2228.     * (somGetInstanceSize is a method provided by SOM.) */
  2229.    size =  _somGetInstanceSize(helloCls);
  2230.    size = ((size+3)/4)*4;  /* round up to doubleword multiple */
  2231.  
  2232.    /* allocate the total space needed for ten instances: */
  2233.    buffer =  SOMMalloc(10*size);
  2234.  
  2235.    /* convert the space into ten separate Hello instances: */
  2236.    for (i=0; i<10; i++)
  2237.        objA[i] = HelloRenew(buffer+i*size);
  2238.    ...
  2239.    ...
  2240.    /* Uninitialize the objects and free them */
  2241.    for (i=0; i<10; i++)
  2242.      _somDestruct(objA[i],0,0);
  2243.    SOMFree(buffer);
  2244.    }
  2245.  
  2246. When an object created with the <className>Renew macro is no longer needed, its 
  2247. storage must be freed using the dual to whatever method was originally used to 
  2248. allocate the storage. Two method pairs are typical: 
  2249.  
  2250.    o  For example, if an object was originally initialized using the 
  2251.       <className>New macro, then, as discussed previously, the client should 
  2252.       use the somFree  method on it. 
  2253.  
  2254.    o  On the other hand, if the program uses the SOMMalloc function to allocate 
  2255.       memory, as illustrated in the example above, then the SOMFree function 
  2256.       must be called to free the objects' storage (because SOMFree is the dual 
  2257.       to SOMMalloc). Before this is done, the objects in the region to be freed 
  2258.       should be deinitialized by invoking the somDestruct method on them. This 
  2259.       allows each object to free any memory that may have been allocated 
  2260.       without the programmer's knowledge. (The somFree method also calls the 
  2261.       somDestruct method.) 
  2262.  
  2263.  Note:  In the somDestruct method call above, the first zero indicates that 
  2264.         memory should not be freed by the class of the object (that is, the 
  2265.         programmer will do it explicitly).  The second zero indicates that the 
  2266.         class of the object is responsible for overall control of object 
  2267.         uninitialization.  For further discussion, see Section 5.5, 
  2268.         "Initializing and Uninitializing Objects," in Chapter 5, "Implementing 
  2269.         Classes in SOM." 
  2270.  
  2271.  For C++ programmers with usage bindings, instances of a class <className> can 
  2272.  be created with a new operator provided by the usage bindings of each SOM 
  2273.  class.  The new operator automatically creates the class object for 
  2274.  <className>, as well as its ancestor classes and metaclass,  if they do not 
  2275.  yet exist.  After verifying the existence of the desired class object, the new 
  2276.  operator then invokes the somNewNoInit  method on the class.  This allocates 
  2277.  memory and creates a new instance of the class,  but it does not initialize 
  2278.  the new object. Initialization of the new object is then performed using one 
  2279.  of the C++ constructors defined by the usage bindings.  (For further 
  2280.  discussion, see Section 5.5 "Initializing and Uninitializing Objects," in 
  2281.  Chapter 5, "Implementing Classes in SOM.") Two variations of the new operator 
  2282.  require no arguments. When either is used, the C++ usage bindings provide a 
  2283.  default constructor that invokes the somDefaultInit method on the new object. 
  2284.  Thus, a new object initialized by somDefaultInit would be created using either 
  2285.  of the forms: 
  2286.  
  2287.  new <className>  new <classname>() 
  2288.  
  2289.  For example: 
  2290.  
  2291.      obj = new Hello;
  2292.      obj1 = new Hello();
  2293.  
  2294.  SOM objects created using the new operator should be freed using the delete 
  2295.  operator, just as for normal C++ objects: 
  2296.  
  2297.     delete obj;
  2298.  
  2299.  When previously allocated space will be used to hold a new object, C++ 
  2300.  programmers should use the somRenew method, described below. C++ bindings do 
  2301.  not provide a macro for this purpose. 
  2302.  
  2303.  somNew and somRenew: C and C++ programmers, as well programmers using other 
  2304.  languages, can create instances of a class using the SOM methods somNew and 
  2305.  somRenew, invoked on the class object. As discussed and illustrated above for 
  2306.  the C bindings, the class object must first be created using the 
  2307.  <className>NewClass procedure (or, perhaps, using the somFindClass method--see 
  2308.  the section "Using class objects," to follow later in this chapter). 
  2309.  
  2310.  The somNew method invoked on the class object creates a new instance of the 
  2311.  class, initializes the object using somDefaultInit, and then returns a pointer 
  2312.  to the new object. For instance, the following C example creates a new object 
  2313.  of the "Hello" class. 
  2314.  
  2315.      #include <hello.h>
  2316.      main()
  2317.      {
  2318.        SOMClass helloCls;   /* a pointer to the Hello class */
  2319.        Hello obj;           /* a pointer to an Hello instance */
  2320.        /* create the Hello class  */
  2321.        helloCls = HelloNewClass(Hello_MajorVersion, Hello_MinorVersion);
  2322.        obj = _somNew(helloCls); /* create the Hello instance */
  2323.      }
  2324.  
  2325.  An object created using the somNew method should be freed by invoking the 
  2326.  somFree method on it after the client program is finished using the object. 
  2327.  
  2328.  The somRenew method invoked on the class object creates a new instance of a 
  2329.  class using the given space, rather than allocating new space for the object. 
  2330.  The method converts the given space into an instance of the class, initializes 
  2331.  the new object using somDefaultInit, and then returns a pointer to it. The 
  2332.  argument to somRenew must point to a block of storage large enough to hold the 
  2333.  new instance. The method somGetInstanceSize can be used to determine the 
  2334.  amount of memory required. For example, the following C++ code creates ten 
  2335.  instances of the "Hello" class: 
  2336.  
  2337.      #include <hello.xh>
  2338.      #include <somcls.xh>
  2339.      main()
  2340.      {
  2341.        SOMClass *helloCls; // a pointer to the Hello class
  2342.        Hello *objA[10]  //  an array of Hello instance pointers
  2343.        unsigned char *buffer;
  2344.        int i;
  2345.        int size;
  2346.  
  2347.       // create the Hello class object
  2348.       helloCls =  HelloNewClass(Hello_MajorVersion, Hello_MinorVersion);
  2349.  
  2350.       // get the amount of space needed for a Hello instance:
  2351.       size = helloCls-> somGetInstanceSize();
  2352.       size = ((size+3)/4)*4;  // round up to doubleword multiple
  2353.  
  2354.       // allocate the total space needed for ten instances
  2355.       buffer =  SOMMalloc(10*size);
  2356.  
  2357.       // convert the space into ten separate Hello objects
  2358.       for (i=0; i<10; i++)
  2359.          objA[i] = helloCls-> somRenew(buffer+i*size);
  2360.  
  2361.       // Uninitialize the objects and free them
  2362.       for (i=0; i<10; i++)
  2363.          objA[i]-> somDestruct(0,0);
  2364.       SOMFree(buffer);
  2365.      }
  2366.  
  2367.  The somNew  and somRenew methods are useful for creating instances of a class 
  2368.  when the header file for the class is not included in the client program at 
  2369.  compile time. (The name of the class might be specified by user input, for 
  2370.  example.) However, the <className>New macro (for C) and the new operator (for 
  2371.  C++) can only be used for classes whose header file is included in the client 
  2372.  program at compile time. 
  2373.  
  2374.  Objects created using the somRenew method should be freed by the client 
  2375.  program that allocated it, using the dual to whatever allocation approach was 
  2376.  initially used. If the somFree method is not appropriate (because the method 
  2377.  somNew was not initially used), then, before memory is freed, the object 
  2378.  should be explicitly deinitialized by invoking the somDestruct method on it. 
  2379.  (The somFree method calls the somDestruct method.  Refer to the previous C 
  2380.  example for Renew for an explanation of the arguments to somDestruct.) 
  2381.  
  2382.  
  2383. ΓòÉΓòÉΓòÉ 5.2.3. Invoking methods on objects ΓòÉΓòÉΓòÉ
  2384.  
  2385. This topic describes the general way to invoke methods in C/C+ + and in other 
  2386. languages, and then presents subtopics for more specialized situations. 
  2387. Making typical method calls 
  2388.  
  2389. For C programmers with usage bindings: To invoke a method in C, use the macro: 
  2390.  
  2391. _<methodName> (receiver, args) 
  2392.  
  2393. (that is, an underscore followed by the method name). Arguments to the macro 
  2394. are the receiver of the method followed by all of the arguments to the method. 
  2395. For example: 
  2396.  
  2397.    _foo(obj, somGetGlobalEnvironment(), x, y)
  2398.  
  2399. This invokes method "foo" on "obj" (the remaining arguments are arguments to 
  2400. the method "foo"). This expression can be used anywhere that a standard 
  2401. function call can be used in C. 
  2402.  
  2403. Required arguments 
  2404.  
  2405. In C, calls to methods defined using IDL require at least two arguments--a 
  2406. pointer to the receiving object (the object responding to the method) and a 
  2407. value of type (Environment *). The Environment data structure is specified by 
  2408. CORBA, and is used to pass environmental information between a caller and a 
  2409. called method. For example, it is used to return exceptions. (For more 
  2410. information on how to supply and use the Environment structure, see the later 
  2411. section entitled "Exceptions and error handling.") 
  2412.  
  2413. In the IDL definition of a method, by contrast, the receiver and the 
  2414. Environment pointer are not listed as parameters to the method. (Unlike the 
  2415. receiver, the Environment pointer is considered a method parameter, even though 
  2416. it is never explicitly specified in IDL. For this reason, it is called an 
  2417. implicit method parameter.) For example, if a method is defined in a .idl file 
  2418. with two parameters, as in: 
  2419.  
  2420.    int foo (in char c, in float f);
  2421.  
  2422. then, with the C usage bindings, the method would be invoked with four 
  2423. arguments, as in: 
  2424.  
  2425.    intvar = _foo(obj, somGetGlobalEnvironment(), x, y);
  2426.  
  2427. where "obj" is the object responding to the method and "x" and "y" are the 
  2428. arguments corresponding to "c" and "f", above. 
  2429.  
  2430. If the IDL specification of the method includes a context specification, then 
  2431. the method has an additional (implicit) context parameter. Thus, when invoking 
  2432. the method, this argument must follow immediately after the Environment pointer 
  2433. argument.  (None of the SOM-supplied methods require context arguments.)  The 
  2434. Environment  and context method parameters are prescribed by the CORBA 
  2435. standard. 
  2436.  
  2437. If the IDL specification of the class that introduces the method includes the 
  2438. callstyle=oidl modifier, then the (Environment*) and context arguments should 
  2439. not be supplied when invoking the method. That is, the receiver of the method 
  2440. call is followed immediately by the arguments to the method (if any). Some of 
  2441. the classes supplied in the SOMobjects Toolkit (including SOMObject, SOMClass, 
  2442. and SOMClassMgr) are defined in this way, to ensure compatibility with the 
  2443. previous release of SOM. The SOMobjects Developer Toolkit: Programmers 
  2444. Reference Manual specifies for each method whether these arguments are used. 
  2445.  
  2446. If you use a C expression to compute the first argument to a method call (the 
  2447. receiver), you must use an expression without side effects, because the first 
  2448. argument is evaluated twice by the _<methodName> macro expansion. In 
  2449. particular, a somNew method call or a macro call of <className>New can not be 
  2450. used as the first argument to a C method call, because doing so would create 
  2451. two new class instances rather than one. 
  2452.  
  2453. Following the initial, required arguments to a method (the receiving object, 
  2454. the Environment, if any, and the context, if any), you enter any additional 
  2455. arguments required by that method, as specified in IDL.  For a discussion of 
  2456. how IDL in/out/inout argument types may to C/C++ data types, see the topic 
  2457. "Parameter list" in Chapter 4, "SOM IDL and the SOM Compiler." 
  2458.  
  2459. Short form vs long form 
  2460.  
  2461. If a client program uses the bindings for two different classes that introduce 
  2462. or inherit two different methods of the same name, then the _<methodName> macro 
  2463. described above (called the short form) will not be provided by the bindings, 
  2464. because the macro would be ambiguous in that circumstance. The following long 
  2465. form macro, however, is always provided by the usage bindings for each class 
  2466. that supports the method: 
  2467.  
  2468. <className>_<methodName> (receiver, args) 
  2469.  
  2470. For example, method "foo" supported by class "Bar" can be invoked as: 
  2471.  
  2472.  
  2473.   Bar_foo(obj, somGetGlobalEnvironment(), x, y)   (in C)
  2474.  
  2475. where "obj"  has type "Bar" and "x" and "y" are the arguments to method "foo". 
  2476.  
  2477. In most cases (where there is no ambiguity, and where the method is not a 
  2478. va_list method, as described in the subsequent subtopic "Using 'va_list' 
  2479. methods"), a C programmer may use either the short or the long form of a method 
  2480. invocation macro interchangeably. However, only the long form complies with the 
  2481. CORBA standard for C usage bindings.  If you wish to write code that can be 
  2482. easily ported to other vendor platforms that support the CORBA standard, use 
  2483. the long form exclusively. The long form is always available for every method 
  2484. that a class supports. The short form is provided both as a programming 
  2485. convenience and for source code compatibility with release 1 of SOM. 
  2486.  
  2487. In order to use the long form, a programmer will usually know what type an 
  2488. object is expected to have.  If this is not known, but the different methods 
  2489. have the same signature, the method can be invoked using name-lookup 
  2490. resolution, as described in a following subtopic of this section. 
  2491.  
  2492. For C++  programmers with usage bindings:  To invoke a method, use the standard 
  2493. C++ form shown below: 
  2494.  
  2495. obj-><methodName> (args) 
  2496.  
  2497. where args are the arguments to the method. For instance, the following example 
  2498. invokes method "foo" on "obj": 
  2499.  
  2500.    obj->foo(somGetGlobalEnvironment(), x, y)
  2501. Required arguments 
  2502.  
  2503. All methods introduced by classes declared using IDL (except those having the 
  2504. SOM IDL callstyle=oidl modifier) have at least one parameter--a value of type 
  2505. (Environment *). The Environment data structure is used to pass environmental 
  2506. information between a caller and a called method. For example, it is used to 
  2507. return exceptions. For more information on how to supply and use the 
  2508. Environment structure, see the later section entitled "Exceptions and error 
  2509. handling." 
  2510.  
  2511. The Environment pointer is an implicit parameter; in the IDL definition of a 
  2512. method, the Environment pointer is not explicitly listed as a parameter to the 
  2513. method. For example, if a method is defined in IDL with two explicit 
  2514. parameters, as in: 
  2515.  
  2516.    int foo (in char c, in float f);
  2517.  
  2518. then the method would be invoked from C++ bindings with three arguments, as in: 
  2519.  
  2520.    intvar = obj->foo(somGetGlobalEnvironment(), x, y);
  2521.  
  2522. where "obj" is the object responding to the method and "x" and "y" are the 
  2523. arguments corresponding to "c" and "f", above. 
  2524.  
  2525. If the IDL specification of the method includes a context specification, then 
  2526. the method has a second implicit parameter, of type context, and the method 
  2527. must be invoked with an additional context argument.  This argument must follow 
  2528. immediately after the Environment pointer argument.  (No SOM-supplied methods 
  2529. require context arguments.)  The Environment and context method parameters are 
  2530. prescribed by the CORBA standard. 
  2531.  
  2532. If the IDL specification of the class that introduces the method includes the 
  2533. callstyle=oidl modifier, then the (Environment  *) and context arguments should 
  2534. not be supplied when the method is invoked. Some of the classes supplied in the 
  2535. SOMobjects Toolkit (including SOMObject, SOMClass, and SOMClassMgr) are defined 
  2536. in this way, to ensure compatibility with the previous release of SOM. The 
  2537. SOMobjects Developer Toolkit: Programmers Reference Manual specifies for each 
  2538. method whether these arguments are used. 
  2539.  
  2540. Following the initial, required arguments to a method (the receiving object, 
  2541. the Environment, if any, and the context, if any), you enter any additional 
  2542. arguments required by that method, as specified in IDL.  For a discussion of 
  2543. how IDL in/out/inout argument types map to C/C++ data types, see the topic 
  2544. "Parameter list" in Chapter 4, "SOM IDL and the SOM Compiler." 
  2545.  
  2546. For non-C/C++ programmers:  To invoke a static method  (that is, a method 
  2547. declared when defining an OIDL or IDL object interface) without using the C or 
  2548. C++ usage bindings, a programmer can use the somResolve procedure. The 
  2549. somResolve  procedure takes as arguments a pointer to the object on which the 
  2550. method is to be invoked and a method token for the desired method. It returns a 
  2551. pointer to the method's procedure (or raises a fatal error if the object does 
  2552. not support the method). Depending on the language and system, it may be 
  2553. necessary to cast this procedure pointer to the appropriate type; the way this 
  2554. is done is language-specific. 
  2555.  
  2556. The method is then invoked by calling the procedure returned by somResolve (the 
  2557. means for calling a procedure, given a pointer to it, is language-specific), 
  2558. passing the method's receiver, the Environment pointer (if necessary), the 
  2559. context argument (if necessary) and the remainder of the method's arguments, if 
  2560. any. (See the section above for C programmers; the arguments to a method 
  2561. procedure are the same as the arguments passed using the long form of the 
  2562. C-language method-invocation macro for that method.) 
  2563.  
  2564. Using somResolve requires the programmer to know where to find the method token 
  2565. for the desired method. Method tokens are available from class objects that 
  2566. support the method (via the method somGetMethodToken), or from a global data 
  2567. structure, called the ClassData structure,  corresponding to the class that 
  2568. introduces the method. In C and C++ programs with access to the definitions for 
  2569. ClassData structures provided by usage bindings, the method token for method 
  2570. methodName introduced by class className may be accessed by the following 
  2571. expression: 
  2572.  
  2573. <className>ClassData.<methodName > 
  2574.  
  2575. For example, the method token for method "sayHello"introduced by class "Hello" 
  2576. is stored at location HelloClassData.sayHello, for C and C++ programmers.  The 
  2577. way method tokens are accessed in other languages is language-specific. 
  2578.  
  2579. As an  example of using offset resolution to invoke methods from a programming 
  2580. language other than C/C++, one would do the following to create an instance of 
  2581. a SOM Class X in Smalltalk: 
  2582.  
  2583.    1. Initialize the SOM run-time environment, if it has not previously been 
  2584.       initialized, using the somEnvironmentNew function. 
  2585.  
  2586.    2. If the class object for class X has not yet been created, use somResolve 
  2587.       with arguments SOMClassMgrObject (returned by somEnvironmentNew in step 
  2588.       1) and the method token for the somFindClass method,  to obtain a method 
  2589.       procedure pointer for the somFindClass method. Use the method procedure 
  2590.       for somFindClass to create the class object for class X:  Call the 
  2591.       procedure with arguments SOMClassMgrObject, the result of calling the 
  2592.       somIdFromString function with argument "X", and the major and minor 
  2593.       version numbers for class X (or zero). The procedure returns the class 
  2594.       object for class X. 
  2595.  
  2596.    3. Use somResolve with arguments representing the class object for X 
  2597.       (returned by somFindClass in step 2) and the method token for the somNew 
  2598.       method, to obtain a method procedure pointer for method somNew. (The 
  2599.       somNew method is used to create instances of class X.) 
  2600.  
  2601.    4. Call the method procedure for somNew (using the method procedure pointer 
  2602.       obtained in step 3) with the class object for X (returned by somFindClass 
  2603.       in step 3) as the argument. The procedure returns a new instance of class 
  2604.       X. 
  2605.  
  2606.  In addition to somResolve, SOM also supplies the somClassResolve procedure. 
  2607.  Instead of an object, the somClassResolve procedure takes a class as its first 
  2608.  argument, and then selects a method procedure from the instance method table 
  2609.  of the passed class. (The somResolve procedure, by contrast, selects a method 
  2610.  procedure from the instance method table of the class of which the passed 
  2611.  object is an instance.) The somClassResolve procedure therefore supports 
  2612.  casted  method resolution. See the SOMobjects Developer Toolkit: Programmers 
  2613.  Reference Manual for more information on somResolve  and somClassResolve. 
  2614.  
  2615.  If the programmer does not know at compile time which class introduces the 
  2616.  method to be invoked, or if the programmer cannot directly access method 
  2617.  tokens, then the procedure somResolveByName can be used to obtain a method 
  2618.  procedure using name-lookup resolution, as described in the next section. 
  2619.  
  2620.  If the signature of the method to be invoked is not known at compile time, but 
  2621.  can be discovered at run time, use somResolve or somResolveByName  to get a 
  2622.  pointer to the somDispatch method procedure, then use it to invoke the 
  2623.  specific method, as described below under "Method name or signature not known 
  2624.  at compile time." 
  2625.  Accessing Attributes 
  2626.  
  2627.  In addition to methods, SOM objects can also have attributes. An attribute is 
  2628.  an IDL shorthand for declaring methods, and does not necessarily indicate the 
  2629.  presence of any particular instance data in an object of that type. Attribute 
  2630.  methods are called "get" and "set" methods. For example, if a class "Hello" 
  2631.  declares an attribute called "msg", then object variables of type "Hello" will 
  2632.  support the methods _get_msg and _set_msg to access or set the value of the 
  2633.  "msg" attribute. (Attributes that are declared as "readonly" have no "set" 
  2634.  method, however.) 
  2635.  
  2636.  The "get" and "set" methods are invoked in the same way as other methods. For 
  2637.  example, given class "Hello" with attribute "msg" of type string, the 
  2638.  following code segments set and get the value of the "msg" attribute: 
  2639.  
  2640.  For C: 
  2641.  
  2642.      #include <hello.h>
  2643.      Hello obj;
  2644.      Environment *ev = somGetGlobalEnvironment();
  2645.  
  2646.      obj = HelloNew();
  2647.      __set_msg(obj, ev, "Good Morning");/*note: two leading underscores */
  2648.      printf("%s\n", __get_msg(obj, ev));
  2649.  
  2650.  For C++: 
  2651.  
  2652.      #include <hello.xh>
  2653.      #include <stdio.h>
  2654.      Hello *obj;
  2655.      Environment *ev = somGetGlobalEnvironment();
  2656.  
  2657.      obj = new Hello;
  2658.      obj->_set_msg(ev, "Good Morning");
  2659.      printf("%s\n", obj->_get_msg(ev));
  2660.  
  2661.  Attributes available with each class, if any, are described in the 
  2662.  documentation of the class itself in the SOMobjects Developer Toolkit 
  2663.  Programmers Reference Manual. 
  2664.  Using 'va_list' methods 
  2665.  
  2666.  SOM supports methods whose final argument is a va_list. A va_list is a 
  2667.  datatype whose representation depends on the operating system platform. On 
  2668.  AIX, OS/2 and Windows, a va_list is simply a pointer to a block of memory that 
  2669.  contains a number of arguments, sequentially laid out in memory. In the 
  2670.  future, SOMobjects may provide special facilities for creating a va_list, but 
  2671.  on the above systems the C/C++ va_arg macro can be used for this purpose. 
  2672.  This is illustrated below. 
  2673.  
  2674.  As a convenience, methods whose final argument is a va-list,  such as: 
  2675.  
  2676.   void setMany(in short start, in short numArgs, in va_list ap):
  2677.  can be invoked by specifying a variable number of arguments, as follows: 
  2678.  
  2679.  For C: 
  2680.  
  2681.   _setMany(aVector, somGetGlobalEnvironment(), 2, 4, 20, 12, 32, 41);
  2682.  For C++ 
  2683.  
  2684.   aVector->setMany(somGetGlobalEnvironment(), 2, 4, 20, 12, 32, 41);
  2685.  
  2686.  C programmers must be aware that the short form of the invocation macro shown 
  2687.  above to pass a variable number of arguments to a  va_list method is only 
  2688.  available in the absence of ambiguity. The long-form macro (which is always 
  2689.  available) requires and explicit va_list argument, as described next. 
  2690.  
  2691.  Note:  As mentioned above, the short form may not be available due to 
  2692.         ambiguity in the bindings.  If a varialbe-argument interface is desired 
  2693.         in such cases, however, you can inspect the usage bindings to find the 
  2694.         short form expansion and make use of this directly. 
  2695.  
  2696.  As an alternative to the preceding example, both C and C++ programmers can use 
  2697.  an explicit va_list argument, as suggested by the method definition.  That is, 
  2698.  to use a va_list  argument, a method must be invoked as 
  2699.  <className>_<methodName>, where <className> is the name of a class that 
  2700.  supports the method. 
  2701.  
  2702.  For example, assume that class "Vector" supports the "setMany" method above. 
  2703.  The following code first constructs a variable of type va_list, next uses the 
  2704.  va_arg macro to store the arguments to "setMany" in the va_list, and then 
  2705.  invokes the "setMany" method with this variable: 
  2706.  
  2707.  For C: 
  2708.  
  2709.   va_list start_ap, ap;
  2710.   Vector aVector = VectorNew();
  2711.   ...
  2712.   start_ap = ap = (va_list) SOMMalloc(4 * sizeof(long));
  2713.   va_arg(ap, long) = 20;
  2714.   va_arg(ap, long) = 12;
  2715.   va_arg(ap, long) = 32;
  2716.   va_arg(ap, long) = 41;
  2717.   Vector_setMany(aVector, somGetGlobalEnvironment(), 2, 4, start_ap);
  2718.  
  2719.  For C++: 
  2720.  
  2721.   va_list start_ap, ap;
  2722.   Vector *aVector = new Vector;
  2723.   ...
  2724.   start_ap = ap = (va_list) SOMMalloc(4 * sizeof(long));
  2725.   va_arg(ap, long) = 20;
  2726.   va_arg(ap, long) = 12;
  2727.   va_arg(ap, long) = 32;
  2728.   va_arg(ap, long) = 41;
  2729.   aVector->Vector_seMany(somGetGlobalEnvironment(), 2, 4, start_ap);
  2730.  
  2731.  Using name-lookup method resolution 
  2732.  
  2733.  For C/C++  programmers:  Offset resolution is the most efficient way to select 
  2734.  the method procedure appropriate to a given method call. Client programs can, 
  2735.  however, invoke a method using "name-lookup" resolution instead of offset 
  2736.  resolution. The C and C++ bindings for method invocation use offset resolution 
  2737.  by default, but methods defined with the namelookup SOM IDL modifier result in 
  2738.  C bindings in which the short form invocation macro uses name-lookup 
  2739.  resolution instead.  Also, for both C and C++ bindings, a special 
  2740.  lookup_<methodName> macro is defined. 
  2741.  
  2742.  Name-lookup resolution is appropriate in the case where a programmer knows at 
  2743.  compile time which arguments will be expected by a method (that is, its 
  2744.  signature), but does not know the type of the object on which the method will 
  2745.  be invoked. For example, name-lookup resolution can be used when two different 
  2746.  classes introduce different methods of the same name and signature, and it is 
  2747.  not known which method should be invoked (because the type of the object is 
  2748.  not known at compile time). 
  2749.  
  2750.  Name-lookup resolution is also used to invoke dynamic methods (that is, 
  2751.  methods that have been added to a class's interface at run time rather than 
  2752.  being specified in the class's IDL specification). For more information on 
  2753.  name-lookup method resolution, see the topic "Method Resolution" in Chapter 4, 
  2754.  "SOM IDL and the SOM Compiler." 
  2755.  
  2756.  For C: To invoke a method using name-lookup resolution, when using the C 
  2757.  bindings for a method that has been implemented with the namelookup modifier, 
  2758.  use either of the following macros: 
  2759.  
  2760.   _<methodName> (receiver, args) 
  2761.  
  2762.  lookup_<methodName> (receiver, args) 
  2763.  
  2764.  Thus, the short-form method invocation macro results in name-lookup resolution 
  2765.  (rather than offset resolution), when the method has been defined as a 
  2766.  namelookup method. (The long form of the macro for offset resolution is still 
  2767.  available in the C usage bindings.) If the method takes a variable number of 
  2768.  arguments, then the first form shown above is used when supplying a variable 
  2769.  number of arguments, and the second form is used when supplying a va_list 
  2770.  argument in place of the variable number of arguments. 
  2771.  
  2772.  For C++: To invoke a method using name-lookup resolution, when using the C++ 
  2773.  bindings for a method that has been defined with the namelookup modifier, use 
  2774.  either of the following macros: 
  2775.  
  2776.   lookup_<methodName> (receiver, args) 
  2777.  
  2778.   <className>_lookup_<methodName> (receiver, args) 
  2779.  
  2780.  If the method takes a variable number of arguments, then the first form shown 
  2781.  above is used when supplying a variable number of arguments, and the second 
  2782.  form is used when supplying a va_list argument in place of the variable number 
  2783.  of arguments. Note that the offset-resolution forms for invoking methods using 
  2784.  the C++ bindings are also still available, even if the method has been defined 
  2785.  as a namelookup method. 
  2786.  
  2787.  For C/C++  To invoke a method using name-lookup resolution, when the method 
  2788.  has not been defined as a namelookup method: 
  2789.  
  2790.    o  Use the somResolveByName procedure (described in the following section), 
  2791.       or any of the methods somLookupMethod, somFindMethod or somFindMethodOk 
  2792.       to obtain a pointer to the procedure that implements the desired method. 
  2793.  
  2794.    o  Then, invoke the desired method by calling that procedure, passing the 
  2795.       method's intended receiver, the Environment pointer (if needed), the 
  2796.       context argument (if needed), and the remainder of the method's 
  2797.       arguments, if any. 
  2798.  
  2799.  The somLookupMethod, somFindMethod and somFindMethodOK methods are invoked on 
  2800.  a class object  (the class of the method receiver should be used), and take as 
  2801.  an argument the somId for the desired method (which can be obtained from the 
  2802.  method's name using the somIdFromString function). For more information on 
  2803.  these methods, see the SOMobjects Developer Toolkit: Programmers Reference 
  2804.  Manual. 
  2805.  
  2806.  Important Note: SOM provides many ways for a SOM user to acquire a pointer to 
  2807.  a method procedure. Once this is done, it becomes the user's responsibility to 
  2808.  make appropriate use of this procedure. 
  2809.  
  2810.    o  First, the procedure should only be used on objects for which this is 
  2811.       appropriate-otherwise, run-time errors are likely to result. 
  2812.  
  2813.    o  Second, when the procedure is used, it is essential that the compiler be 
  2814.       given correct information concerning the signature of the method and the 
  2815.       linkage required by the method.  (On many systems, there are different 
  2816.       ways to pass method arguments, and linkage information tells a compiler 
  2817.       how to pass the arguments indicated by a method's signature). 
  2818.  
  2819.  SOM method procedures on OS/2 must be called with "system" linkage.  On AIX, 
  2820.  there is only one linkage convention for procedure calls. While C and C++ 
  2821.  provide standard ways to indicate a method signature, the way to indicate 
  2822.  linkage information depends on the specific compiler and system.  For each 
  2823.  method declared using OIDL or IDL,  the C and C++ usage bindings therefore use 
  2824.  conditional macros and a typedef to name a type that has the correct linkage 
  2825.  convention. This type name can then be used by programmers with access to the 
  2826.  usage bindings for the class that introduces the method whose procedure 
  2827.  pointer is used. The type is named somTD_<className>_<methodName>. This is 
  2828.  illustrated in the following example, and further details are provided in the 
  2829.  section below, titled "Obtaining a method's procedure pointer." 
  2830.  A name-lookup example 
  2831.  
  2832.  The following example shows the use of name-lookup by a SOM client programmer. 
  2833.  Name-lookup resolution is appropriate when a programmer knows that an object 
  2834.  will respond to a method of some given name, but does not know enough about 
  2835.  the type of the object to use offset method resolution. How can this happen? 
  2836.  It normally happens when a programmer wants to write generic code, using 
  2837.  methods of the same name and signature that are applicable to different 
  2838.  classes of objects, and yet these classes have no common ancestor that 
  2839.  introduces the method. This can easily occur in single-inheritance systems 
  2840.  (such as Smalltalk and SOM release 1) and can also happen in 
  2841.  multiple-inheritance systems such as SOM release 2--when class hierarchies 
  2842.  designed by different people are brought together for clients' use. 
  2843.  
  2844.  If multiple inheritance is available, it is always possible to create a common 
  2845.  class ancestor into which methods of this kind can be migrated. A refactoring 
  2846.  of this kind often implements a semantically pleasing generalization that 
  2847.  unifies common features of two previously unrelated class hierarchies. This 
  2848.  step is most practical, however, when it does not require the redefinition or 
  2849.  recompilation of current applications that use offset resolution. SOM is 
  2850.  unique in that it allows this. 
  2851.  
  2852.  However, such refactoring must redefine the classes that originally introduced 
  2853.  the common methods (so the methods can be inherited from the new "unifying" 
  2854.  class instead). A client programmer who simply wants to create an application 
  2855.  may not control the implementations of the classes. Thus, the use of 
  2856.  name-lookup method resolution seems the best alternative for programmers who 
  2857.  do not want to define new classes, but simply to make use of available ones. 
  2858.  
  2859.  For example, assume the existence of two different SOM classes, "classX" and 
  2860.  "classY", whose only common ancestor is SOMObject, and who both introduce a 
  2861.  method named "reduce" that accepts a string as an argument and returns a long. 
  2862.  We assume that the classes were not designed in conjunction with each other. 
  2863.  As a result, it is unlikely that the "reduce" method was defined with a 
  2864.  namelookup modifier. 
  2865.  
  2866.  Following is a C++ generic procedure that uses name-lookup method resolution 
  2867.  to invoke the "reduce" method on its argument, which may be either of type 
  2868.  "classX" or "classY". Note that there is no reason to include classY's usage 
  2869.  bindings, since the typedef provided for the "reduce" method procedure in 
  2870.  "classX" is sufficient for invoking the method procedure, independently of 
  2871.  whether the target object is of type "classX" or "classY". 
  2872.  
  2873.      #include <classX.xh> // use classX's method proc typedef
  2874.  
  2875.      // this procedure can be invoked on a target of type
  2876.      // classX or classY.
  2877.  
  2878.      long generic_reduce1(SOMObject *target, string arg)
  2879.      {
  2880.         somTD_classX_reduce reduceProc = (somTD_classX_reduce)
  2881.         somResolveByName(target, "reduce");
  2882.         return reduceProc(target, arg);
  2883.      }
  2884.  
  2885.  On the other hand, If the classes were designed in conjunction with each 
  2886.  other, and the class designer felt that programmers might want to write 
  2887.  generic code appropriate to either class of object, the namelookup modifier 
  2888.  might have been used. This is a possibility in SOM release 2, even with 
  2889.  multiple inheritance, but it is much more likely that the class designer would 
  2890.  use multiple inheritance to introduce the reduce method in a separate class, 
  2891.  and then use this other class as a parent for both classX and classY (thereby 
  2892.  allowing the use of offset resolution). 
  2893.  
  2894.  In any case, if the "reduce" method in "classX" were defined as a namelookup 
  2895.  method, the following code would be appropriate.  Note that the name-lookup 
  2896.  support provided by "classX" usage bindings is still appropriate for use on 
  2897.  targets that do not have type "classX".  As a result, the "reduce" method 
  2898.  introduced by "classY" need not have been defined as a namelookup method. 
  2899.  
  2900.      #include <classX.xh> // use classX's name-lookup support
  2901.  
  2902.      // this procedure can be invoked on a target of type
  2903.      // classX or classY.
  2904.  
  2905.      long generic_reduce2(SOMObject *target, string arg)
  2906.      {
  2907.          return lookup_reduce(target, arg);
  2908.      }
  2909.  
  2910.  For non-C/C++  programmers:  Name-lookup  resolution is useful for non-C/C++ 
  2911.  programmers when the type of an object on which a method must be invoked is 
  2912.  not known at compile time or when method tokens cannot be directly accessed by 
  2913.  the programmer. To invoke a method using name-lookup resolution when not using 
  2914.  the C or C++ usage bindings, use the somResolveByName procedure to acquire a 
  2915.  procedure pointer. How the programmer indicates the method arguments and the 
  2916.  linkage convention in this case is compiler specific. 
  2917.  
  2918.  The somResolveByName  procedure takes as arguments a pointer to the object on 
  2919.  which the method is to be invoked and the name of the method, as a string. It 
  2920.  returns a pointer to the method's procedure (or NULL if the method is not 
  2921.  supported by the object). The method can then be invoked by calling the method 
  2922.  procedure, passing the method's receiver, the Environment pointer (if 
  2923.  necessary), the context argument (if necessary), and the rest of the method's 
  2924.  arguments, if any. (See the section above for C programmers; the arguments to 
  2925.  a method procedure are the same as the arguments passed to the long-form 
  2926.  C-language method-invocation macro for that method.) 
  2927.  
  2928.  As an example of invoking methods using name-lookup resolution using the 
  2929.  procedure somResolveByName, the following steps are used to create an instance 
  2930.  of a SOM Class X in Smalltalk: 
  2931.  
  2932.    1. Initialize the SOM run-time environment (if it is not already 
  2933.       initialized) using the somEnvironmentNew function. 
  2934.  
  2935.    2. If the class object for class X has not yet been created, use 
  2936.       somResolveByName with the arguments SOMClassMgrObject (returned by 
  2937.       somEnvironmentNew in step 1) and the string "somFindClass", to obtain a 
  2938.       method procedure pointer for the somFindClass method. Use the method 
  2939.       procedure for somFindClass to create the class object for class X: Call 
  2940.       the method procedure with these four arguments: SOMClassMgrObject; the 
  2941.       variable holding class X 's somId (the result of calling the 
  2942.       somIdFromString function with argument "X"); and the major and minor 
  2943.       version numbers for class X (or zero). The result is the class object for 
  2944.       class X. 
  2945.  
  2946.    3. Use somResolveByName with arguments the class object for X (returned by 
  2947.       somFindClass in step 2) and the string "somNew", to obtain a method 
  2948.       procedure pointer for method somNew. (This somNew method is used to 
  2949.       create instances of a class.) 
  2950.  
  2951.    4. Call the method procedure for somNew (using the method procedure pointer 
  2952.       obtained in step 3) with the class object for X (returned by somFindClass 
  2953.       in step 3) as the argument. The result is a new instance of class X. How 
  2954.       the programmer indicates the method arguments and the linkage convention 
  2955.       is compiler-specific. 
  2956.  
  2957.  Obtaining a method's procedure pointer 
  2958.  
  2959.  Method resolution is the process of obtaining a pointer to the procedure that 
  2960.  implements a particular method for a particular object at run time.  The 
  2961.  method is then invoked subsequently by calling that procedure, passing the 
  2962.  method's intended receiver, the Environment pointer (if needed), the context 
  2963.  argument (if needed), and the method's other arguments, if any. C and C++ 
  2964.  programmers may wish to obtain a pointer to a method's procedure for efficient 
  2965.  repeated invocations. 
  2966.  
  2967.  Obtaining a pointer to a method's procedure is achieved in one of two ways, 
  2968.  depending on whether the method is to be resolved using offset resolution or 
  2969.  name-lookup resolution. Obtaining a method's procedure pointer via offset 
  2970.  resolution is faster, but it requires that the name of the class that 
  2971.  introduces the method and the name of the method be known at compile time.  It 
  2972.  also requires that the method be defined as part of that class's interface in 
  2973.  the IDL specification of the class. (See the topic "Method Resolution" in 
  2974.  Chapter 4, "SOM IDL and the SOM Compiler" for more information on offset and 
  2975.  name-lookup method resolution.) 
  2976.  Offset resolution 
  2977.  
  2978.  To obtain a pointer to a procedure using offset resolution, the C/C++ usage 
  2979.  bindings provide the SOM_Resolve and SOM_ResolveNoCheck macros. The usage 
  2980.  bindings themselves use the first of these, SOM_Resolve, for offset-resolution 
  2981.  method calls. The difference in the two macros is that the SOM_Resolve macro 
  2982.  performs consistency checking on its arguments, but the macro 
  2983.  SOM_ResolveNoCheck, which is faster, does not. Both macros require the same 
  2984.  arguments: 
  2985.  
  2986.  SOM_Resolve(<receiver>, <className>, <methodName>) 
  2987.  SOM_ResolveNoCheck(<receiver>, <className>, <methodName>) 
  2988.  
  2989.  where the arguments are as follows: 
  2990.  
  2991.  receiver          The object to which the method will apply. It should be 
  2992.                    specified as an expression without side effects. 
  2993.  
  2994.  className         The name of the class that introduces the method. 
  2995.  
  2996.  methodName        The name of the desired method. 
  2997.  
  2998.  These two names (className and methodName) must be given as tokens, rather 
  2999.  than strings or expressions. (For example, as Animal rather than "Animal".) If 
  3000.  the symbol SOM_TestOn is defined and the symbol SOM_NoTest is not defined in 
  3001.  the current compilation unit, then SOM_Resolve verifies that receiver is an 
  3002.  instance of className or some class derived from className. If this test 
  3003.  fails, an error message is output and execution is terminated. 
  3004.  
  3005.  The SOM_Resolve and SOM_ResolveNoCheck  macros use the procedure somResolve to 
  3006.  obtain the entry-point address of the desired method procedure (or raise a 
  3007.  fatal error if methodName is not introduced by className). This result can be 
  3008.  directly applied to the method arguments, or stored in a variable of generic 
  3009.  procedure type (for example, somMethodPtr) and retained for later method use. 
  3010.  This second possibility would result in a loss of information, however, for 
  3011.  the reasons now given. 
  3012.  
  3013.  The SOM_Resolve or SOM_ResolveNoCheck macros are especially useful because 
  3014.  they cast the method procedure they obtain to the right type to allow the C or 
  3015.  C++ compiler to call  this procedure with system linkage and with the 
  3016.  appropriate arguments. This is why the result of SOM_Resolve is immediately 
  3017.  useful for calling the method procedure, and why storing the result of 
  3018.  SOM_Resolve in a variable of some "generic" procedure type results in a loss 
  3019.  of information. The correct type information can be regained, however, because 
  3020.  the type used by SOM_Resolve for casting the result of somResolve  is 
  3021.  available from C/C++ usage bindings using the typedef name 
  3022.  somTD_<className>_<methodName>. This type name describes a pointer to a method 
  3023.  procedure for methodName introduced by class className. If the final argument 
  3024.  of the method is a va_list, then the method procedure returned by SOM_Resolve 
  3025.  or SOM_ResolveNoCheck must be called with a va_list  argument, and not a 
  3026.  variable number of arguments. 
  3027.  
  3028.  Below is a C example of using SOM_Resolve to obtain a method procedure pointer 
  3029.  for method "sayHello", introduced by class "Hello", and using it to invoke the 
  3030.  method on "obj." (Assume that the only argument required by the "sayHello" 
  3031.  method is the Environment pointer.) 
  3032.  
  3033.      somMethodProc *p;
  3034.      SOMObject obj = HelloNew();
  3035.      p = SOM_Resolve(obj, Hello, sayHello);
  3036.      ((somTD_Hello_sayHello)p) (obj, somGetGlobalEnvironment());
  3037.  
  3038.  SOM_Resolve and SOM_ResolveNoCheck can only be used to obtain method 
  3039.  procedures for static methods  (methods that have been declared in an IDL 
  3040.  specification for a class) and not methods that are added to a class at run 
  3041.  time. See the SOMobjects Programmers Reference Manual for more information and 
  3042.  examples on SOM_Resolve and SOM_ResolveNoCheck. 
  3043.  Name-lookup method resolution 
  3044.  
  3045.  To obtain a pointer to a method's procedure using name-lookup  resolution, use 
  3046.  the somResolveByName procedure (described in the following section), or any of 
  3047.  the somLookupMethod, somFindMethod and somFindMethodOK methods. These methods 
  3048.  are invoked on a class object that supports the desired method, and they take 
  3049.  an argument specifying the a somId for the desired method (which can be 
  3050.  obtained from the method's name using the somIdFromString function). For more 
  3051.  information on these methods and for examples of their use, see the SOMobjects 
  3052.  Developer Toolkit: Programmers Reference Manual. 
  3053.  Method name or signature not known at compile time 
  3054.  
  3055.  If the programmer does not know a method's name at compile time (for example, 
  3056.  it might be specified by user input), then the method can be invoked in one of 
  3057.  two ways, depending upon whether its signature is known: 
  3058.  
  3059.    o  Suppose the signature of the method is known at compile time (even though 
  3060.       the method name is not). In that case, when the name of the method 
  3061.       becomes available at run time, the somLookupMethod, somFindMethod or 
  3062.       somFindMethodOk methods or the somResolveByName procedure can be used to 
  3063.       obtain a pointer to the method's procedure using name-lookup method 
  3064.       resolution, as described in the preceding topics. That method procedure 
  3065.       can then be invoked, passing the method's intended receiver, the 
  3066.       Environment pointer (if needed), the context argument (if needed), and 
  3067.       the remainder of the method's arguments. 
  3068.  
  3069.    o  If the method's signature is unknown until run time, then 
  3070.       dispatch-function resolution is indicated, as described in the next 
  3071.       topic. 
  3072.  
  3073.  Dispatch-function method resolution 
  3074.  
  3075.  If the signature of the method is not known at compile time (and hence the 
  3076.  method's argument list cannot be constructed until run time), then the method 
  3077.  can be invoked at run time by (a) placing the arguments in a variable of type 
  3078.  va_list at run time and (b) either using the somGetMethodData method followed 
  3079.  by use of the somApply function, or by invoking the somDispatch or 
  3080.  somClassDispatch method. Using somApply is more efficient, since this is what 
  3081.  the somDispatch method does, but it requires two steps instead of one. In 
  3082.  either case, the result invokes a "stub" procedure called an apply stub, whose 
  3083.  purpose is to remove the method arguments from the va_list, and then pass them 
  3084.  to the appropriate method procedure in the way expected by that procedure. For 
  3085.  more information on these methods and for examples of their use, see the 
  3086.  somApply function, and the somGetMethodData, somDispatch, and somClassDispatch 
  3087.  methods in the SOMobjects Programmers Reference Manual. 
  3088.  
  3089.  
  3090. ΓòÉΓòÉΓòÉ 5.2.4. Using class objects ΓòÉΓòÉΓòÉ
  3091.  
  3092. Using a class object encompasses three aspects: getting the class of an object, 
  3093. creating a new class object, or simply referring to a class object through the 
  3094. use of a pointer. 
  3095. Getting the class of an object 
  3096.  
  3097. To get the class that an object is an instance of, SOM provides a method called 
  3098. somGetClass. The somGetClass method takes an object as its only argument and 
  3099. returns a pointer to the class object of which it is an instance. For example, 
  3100. the following statements store in "myClass" the class object of which "obj" is 
  3101. an instance. 
  3102.  
  3103. myClass = _somGetClass(obj);  (for C)
  3104. myClass = obj->somGetClass();  (for C++)
  3105.  
  3106. Getting the class of an object is useful for obtaining information about the 
  3107. object; in some cases, such information cannot be obtained directly from the 
  3108. object, but only from its class. The section below entitled "Getting 
  3109. information about a class" describes the methods that can be invoked on a class 
  3110. object after it is obtained using somGetClass. 
  3111.  
  3112. The somGetClass method can be overridden by a class to provide enhanced or 
  3113. alternative semantics for its objects. Because it is usually important to 
  3114. respect the intended semantics of a class of objects, the somGetClass method 
  3115. should normally be used to access the class of an object. 
  3116.  
  3117. In a few special cases, it is not possible to make a method call on an object 
  3118. in order to determine its class. For such situations, SOM provides the 
  3119. SOM_GetClass  macro. In general, the somGetClass method and the SOM_GetClass 
  3120. macro may have different behavior (if somGetClass has been overridden). This 
  3121. difference may be limited to side effects, but it is possible for their results 
  3122. to differ as well. The SOM_GetClass macro should only be used when absolutely 
  3123. necessary. 
  3124. Creating a class object 
  3125.  
  3126. A class object is created automatically the first time the <className>New 
  3127. macro (for C) or the new operator (C++) is invoked to create an instance of 
  3128. that class. In other situations, however, it may be necessary to create a class 
  3129. object explicitly, as this section describes. 
  3130. Using <className>Renew or somRenew 
  3131.  
  3132. It is sometimes necessary to create a class object before creating any 
  3133. instances of the class. For example, creating instances using the <className> 
  3134. Renew macro or the somRenew method requires knowing how large the created 
  3135. instance will be, so that memory can be allocated for it. Getting this 
  3136. information requires creating the class object (see the example under "Creating 
  3137. instances of a class" early in this chapter). As another example, a class 
  3138. object must be explicitly created when a program does not use the SOM bindings 
  3139. for a class. Without SOM bindings for a class, its instances must be created 
  3140. using somNew or somRenew, and these methods require that the class object be 
  3141. created in advance. 
  3142.  
  3143. Use the <className>NewClass procedure to create a class object: 
  3144.  
  3145.    o  When using the C/C++ language bindings for the class, and 
  3146.  
  3147.    o  When the name of the class is known at compile time. 
  3148.  
  3149.  Using <className>NewClass 
  3150.  
  3151.  The <className>NewClass procedure initializes the SOM run-time environment, if 
  3152.  necessary, creates the class object (unless it already exists), creates class 
  3153.  objects for the ancestor classes and metaclass of the class, if necessary, and 
  3154.  returns a pointer to the newly created class object. After its creation, the 
  3155.  class object can be referenced in client code using the macro 
  3156.  
  3157.  _<className>                            (for C and C++ programs) 
  3158.  
  3159.  or the expression 
  3160.  
  3161.  <className>ClassData.classObject        (for C and C++ programs). 
  3162.  
  3163.  The <className>NewClass procedure takes two arguments, the major version 
  3164.  number and minor version number of the class. These numbers are checked 
  3165.  against the version numbers built into the class library to determine if the 
  3166.  class is compatible with the client's expectations. The class is compatible if 
  3167.  it has the same major version number and the same or a higher minor version 
  3168.  number. If the class is not compatible, an error is raised. Major version 
  3169.  numbers usually only change when a significant enhancement or incompatible 
  3170.  change is made to a class. Minor version numbers change when minor 
  3171.  enhancements or fixes are made. Downward compatibility is usually maintained 
  3172.  across changes in the minor version number. Zero can be used in place of 
  3173.  version numbers to bypass version number checking. 
  3174.  
  3175.  When using SOM bindings for a class, these bindings define constants 
  3176.  representing the major and minor version numbers of the class at the time the 
  3177.  bindings were generated. These constants are named <className>_MajorVersion 
  3178.  and <className>_MinorVersion. For example, the following procedure call: 
  3179.  
  3180.      AnimalNewClass(Animal_MajorVersion, Animal_MinorVersion);
  3181.  
  3182.  creates the class object for class "Animal". Thereafter, _Animal can be used 
  3183.  to reference the "Animal" class object. 
  3184.  
  3185.  The preceding technique for checking version numbers is not failsafe. For 
  3186.  performance reasons, the version numbers for a class are only checked when the 
  3187.  class object is created, and not when the class object or its instances are 
  3188.  used. Thus, run-time errors may result when usage bindings for a particular 
  3189.  version of a class are used to invoke methods on objects created by an earlier 
  3190.  version of the class. 
  3191.  Using somFindClass or somFindClsInFile 
  3192.  
  3193.  To create a class object when  not using the C/C++  language bindings for the 
  3194.  class, or when the class name is not known at compile time: 
  3195.  
  3196.    o  First, initialize the SOM run-time environment by calling the 
  3197.       somEnvironmentNew function (unless it is known that the SOM run-time 
  3198.       environment has already been initialized). 
  3199.  
  3200.    o  Then, use the somFindClass or somFindClsInFile method to create the class 
  3201.       object. (The class must already be defined in a dynamically linked 
  3202.       library, or DLL.) 
  3203.  
  3204.  The somEnvironmentNew function initializes the SOM run-time environment. That 
  3205.  is, it creates the four primitive SOM objects (SOMClass, SOMObject, 
  3206.  SOMClassMgr, and the SOMClassMgrObject), and it initializes SOM global 
  3207.  variables. The function takes no arguments and returns a pointer to the 
  3208.  SOMClassMgrObject. 
  3209.  
  3210.  Note:  Although somEnvironmentNew must be called before using other SOM 
  3211.         functions and methods, explicitly calling somEnvironmentNew is usually 
  3212.         not necessary when using the C/C++ bindings,  because the macros for 
  3213.         <className>NewClass,  <className>New , and <className>Renew call it 
  3214.         automatically, as does the new operator for C++. Calling 
  3215.         somEnvironmentNew repeatedly does no harm. 
  3216.  
  3217.  After the SOM run-time environment has been initialized, the methods 
  3218.  somFindClass and somFindClsInFile can be used to create a class object. These 
  3219.  methods must be invoked on the class manager, which is pointed to by the 
  3220.  global variable SOMClassMgrObject.  (It is also returned as the result of 
  3221.  somEnvironmentNew.) 
  3222.  
  3223.  The somFindClass method takes the following arguments: 
  3224.  
  3225.  classId                  A somId identifying the name of the class to be 
  3226.                           created. The somIdFromString function returns a 
  3227.                           classId  given the name of the class. 
  3228.  
  3229.  major version number     The expected major version number of the class. 
  3230.  
  3231.  minor version number     The expected minor version number of the class. 
  3232.  
  3233.  The version numbers are checked against the version numbers built into the 
  3234.  class library to determine if the class is compatible with the client's 
  3235.  expectations. 
  3236.  
  3237.  The somFindClass  method dynamically loads the DLL containing the class's 
  3238.  implementation, if needed, creates the class object (unless it already exists) 
  3239.  by invoking its <className>NewClass procedure, and returns a pointer to it. If 
  3240.  the class could not be created, somFindClass returns NULL. For example, the 
  3241.  following C code fragment creates the class "Hello" and stores a pointer to it 
  3242.  in "myClass": 
  3243.  
  3244.      SOMClassMgr cm = somEnvironmentNew();
  3245.      somId classId = somIdFromString("Hello");
  3246.      SOMClass myClass = _somFindClass(SOMClassMgrObject, classId
  3247.                             Hello_MajorVersion, Hello_MinorVersion);
  3248.      ...
  3249.      SOMFree(classId);
  3250.  
  3251.  The somFindClass method uses somLocateClassFile to get the name of the library 
  3252.  file containing the class. If the class was defined with a "dllname" class 
  3253.  modifier, then somLocateClassFile returns that file name; otherwise, it 
  3254.  assumes that the class name is the name of the library file. The 
  3255.  somFindClsInFile method is similar to somFindClass, except that it takes an 
  3256.  additional (final) argument--the name of the library file containing the 
  3257.  class.  The somFindClsInFile method is useful when a class is packaged in a 
  3258.  DLL along with other classes and the "dllname" class modifier has not been 
  3259.  given in the class's IDL specification. 
  3260.  
  3261.  Warning:  On AIX, the somFindClass and somFindClsInFile methods should not  be 
  3262.  used to create a class whose implementation is statically linked with the 
  3263.  client program. Instead, the class object should be created using the 
  3264.  <className>NewClass procedure provided by the class's .h/.xh header file. 
  3265.  Static linkage is not created by including usage bindings in a program, but by 
  3266.  use of the offset-resolution method-invocation macros. 
  3267.  Referring to class objects 
  3268.  
  3269.  Saving a pointer as the class object is created: The <className>NewClass macro 
  3270.  and the somFindClass method, used to create class objects, both return a 
  3271.  pointer to the newly created class object. Hence, one way to obtain a pointer 
  3272.  to a class object is to save the value returned by <className>NewClass or 
  3273.  somFindClass  when the class object is created. 
  3274.  
  3275.  Getting a pointer after the class object is created: After a class object has 
  3276.  been created, client programs can also get a pointer to the class object from 
  3277.  the class name. When the class name is known at compile time and the client 
  3278.  program is using the C or C++ language bindings, the macro 
  3279.  
  3280.  _<className> 
  3281.  
  3282.  can be used to refer to the class object for <className>. Also, when the class 
  3283.  name is known at compile time and the client program is using the C or C++ 
  3284.  language bindings, the expression 
  3285.  
  3286.  <className>ClassData.classObject 
  3287.  
  3288.  refers to the class object for <className>. For example, _Hello refers to the 
  3289.  class object for class "Hello" in C or C++ programs, and 
  3290.  HelloClassData.classObject refers to the class object for class "Hello." in C 
  3291.  or C++ programs. 
  3292.  
  3293.  Getting a pointer to the class object from an instance:  If any instances of 
  3294.  the class are known to exist, a pointer to the class object can also be 
  3295.  obtained by invoking the somGetClass method on such an instance. (See "Getting 
  3296.  the class of an object," above.) 
  3297.  
  3298.  Getting a pointer in other situations: If the class name is not known until 
  3299.  run time, or if the client program is not using the C or C++ language 
  3300.  bindings, and no instances of the class are known to exist, then the 
  3301.  somClassFromId method can be used to obtain a pointer to a class object after 
  3302.  the class object has been created. The somClassFromId method should be invoked 
  3303.  on the class manager, which is pointed to by the global variable 
  3304.  SOMClassMgrObject. The only argument to the method is a somId for the class 
  3305.  name, which can be obtained using the somIdFromString function. The method 
  3306.  somClassFromId returns a pointer to the class object of the specified class. 
  3307.  For example, the following C code stores in "myClass" a pointer to the class 
  3308.  object for class "Hello" (or NULL, if the class cannot be located): 
  3309.  
  3310.      SOMClassMgr cm = somEnvironmentNew();
  3311.      somId classId = somIdFromString("Hello");
  3312.      SOMClass myClass =_somClassFromId(SOMClassMgrObject,classId
  3313.                             Hello_MajorVersion, Hello_MinorVersion);
  3314.      SOMFree(classId);
  3315.  
  3316.  
  3317. ΓòÉΓòÉΓòÉ 5.2.5. Compiling and linking ΓòÉΓòÉΓòÉ
  3318.  
  3319. This section describes how to compile and link C and C++ client programs. 
  3320. Compiling and linking a client program with a SOM class is done in one of two 
  3321. ways, depending on how the class is packaged. 
  3322.  
  3323. If the class is not packaged as a library (that is, the client program has the 
  3324. implementation source code for the class, as in the examples given in the SOM 
  3325. IDL tutorial), then the client program can be compiled together with the class 
  3326. implementation file as follows. (This assumes that the client program and the 
  3327. class are both implemented in the same language, C or C++. If this is not the 
  3328. case, then each module must be compiled separately to produce an object file 
  3329. and the resulting object files linked together to form an executable.) 
  3330.  
  3331. In the following examples, the environment variable SOMBASE refers to the 
  3332. directory in which SOM has been installed. The examples also assume that the 
  3333. header files and the import library for the "Hello" class reside in the 
  3334. "include" and "lib" directories where SOM has been installed.  If this is not 
  3335. the case, additional path information should be supplied for these files. For 
  3336. client program "main" and class "Hello": 
  3337.  
  3338. Under AIX, for C programmers: 
  3339.  
  3340.    > xlc -I. -I$SOMBASE/include main.c hello.c -L$SOMBASE/lib -lsomtk \
  3341.          -o main
  3342.  
  3343. Under AIX, for C++ programmers: 
  3344.  
  3345.    > xlC -I. -I$SOMBASE/include main.C hello.C -L$SOMBASE/lib -lsomtk \
  3346.          -o main
  3347.  
  3348. Under OS/2, for C programmers: 
  3349.  
  3350.    > set LIB=%SOMBASE%\lib;%LIB%
  3351.    > icc -I. -I%SOMBASE%\include main.c hello.c somtk.lib
  3352.  
  3353. Under OS/2, for C++ programmers: 
  3354.  
  3355.    > set LIB=%SOMBASE%\lib;%LIB%
  3356.    > icc -I. -I%SOMBASE%\include main.cpp hello.cpp somtk.lib
  3357.  
  3358. If the class is packaged as a class library, then the client program, "main", 
  3359. is compiled as above, except that the class implementation file is not part of 
  3360. the compilation. Instead, the "import library" provided with the class library 
  3361. is used to resolve the symbolic references that appear in "main". For example, 
  3362. to compile the C client program "main.c" that uses class "Hello": 
  3363.  
  3364. Under AIX: 
  3365.  
  3366.    > xlc -I. -I$SOMBASE/include main.c -lc -L$SOMBASE/lib -lsomtk \
  3367.          -lhello -o main
  3368.  
  3369. Under OS/2: 
  3370.  
  3371.    > set LIB=%SOMBASE%\lib;%LIB%
  3372.    > icc -I. -I%SOMBASE%\include main.c somtk.lib hello.lib
  3373.  
  3374.  
  3375. ΓòÉΓòÉΓòÉ 5.3. Language-neutral Methods and Functions ΓòÉΓòÉΓòÉ
  3376.  
  3377. This section describes methods, functions, and macros that client programs can 
  3378. use regardless of the programming language in which they are written. In other 
  3379. words, these functions and methods are not part of the C or C++ bindings. 
  3380.  
  3381.  
  3382. ΓòÉΓòÉΓòÉ 5.3.1. Generating output ΓòÉΓòÉΓòÉ
  3383.  
  3384. The following functions and methods are used to generate output, including 
  3385. descriptions of SOM objects. They all produce their output using the 
  3386. character-output procedure held by the global variable SOMOutCharRoutine. The 
  3387. default procedure for character output simply writes the character to stdout, 
  3388. but it can be replaced to change the output destination of the methods and 
  3389. functions below. (See Chapter 5 for more information on customizing SOM.) 
  3390.  
  3391.  somDumpSelf              (method) writes a detailed description of an object, 
  3392.                           including its class, its location, and its instance 
  3393.                           data. The receiver of the method is the object to be 
  3394.                           dumped. An additional argument is the "nesting level" 
  3395.                           for the description. [All lines in the description 
  3396.                           will be indented by (2 * level) spaces.] 
  3397.  
  3398.  somPrintSelf             (method) Writes a brief description of an object, 
  3399.                           including its class and location in memory. The 
  3400.                           receiver of the method is the object to be printed. 
  3401.  
  3402.  somPrintf                (function) SOM's version of the C "printf" function. 
  3403.                           It generates character stream output via 
  3404.                           SOMOutCharRoutine. It has the same interface as the C 
  3405.                           "printf" function. 
  3406.  
  3407.  somVprintf               (function) Represents the "vprint" form of somPrintf. 
  3408.                           Its arguments are a formatting string and a va_list 
  3409.                           holding the remaining arguments. 
  3410.  
  3411.  somPrefixLevel           (function) Generates (via somPrintf) spaces to prefix 
  3412.                           a line at the indicated level. The return type is 
  3413.                           void. The argument is an integer specifying the 
  3414.                           level. The number of spaces generated is (2 * level). 
  3415.  
  3416.  somLPrintf               (function) Combines somPrefixLevel and somPrintf. The 
  3417.                           first argument is the level of the description (as 
  3418.                           for somPrefixLevel) and the remaining arguments are 
  3419.                           as for somPrintf (or for the C "printf" function). 
  3420.  
  3421.  See the SOMobjects Developer Toolkit: Programmers Reference Manual for more 
  3422.  information on a specific function or method. 
  3423.  
  3424.  
  3425. ΓòÉΓòÉΓòÉ 5.3.2. Getting information about a class ΓòÉΓòÉΓòÉ
  3426.  
  3427. The following methods are used to obtain information about a class or to locate 
  3428. a particular class object: 
  3429.  
  3430.  somCheckVersion          Checks a class for compatibility with the specified 
  3431.                           major and minor version numbers. The receiver of the 
  3432.                           method is the SOM class about which information is 
  3433.                           needed. Additional arguments are values of the major 
  3434.                           and minor version numbers. The method returns TRUE if 
  3435.                           the class is compatible, or FALSE otherwise. 
  3436.  
  3437.  somClassFromId           Finds the class object of an existing class when 
  3438.                           given its somId, but without loading the class. The 
  3439.                           receiver of the method is the class manager (pointed 
  3440.                           to by the global variable SOMClassMgrObject). The 
  3441.                           additional argument is the class's somId. The method 
  3442.                           returns a pointer to the class (or NULL if the class 
  3443.                           does not exist). 
  3444.  
  3445.  somDescendedFrom         Tests whether one class is derived from another. The 
  3446.                           receiver of the method is the class to be tested, and 
  3447.                           the potential ancestor class is the argument. The 
  3448.                           method returns TRUE if the relationships exists, or 
  3449.                           FALSE otherwise. 
  3450.  
  3451.  somFindClass             Finds or creates the class object for a class, given 
  3452.                           the class's somId and its major and minor version 
  3453.                           numbers. The receiver of the method is the class 
  3454.                           manager (pointed to by the global variable 
  3455.                           SOMClassMgrObject). Additional arguments are the 
  3456.                           class's somId and the major and minor version 
  3457.                           numbers. The method returns a pointer to the class 
  3458.                           object, or NULL if the class could not be created. 
  3459.  
  3460.  somFindClsInFile         Finds or creates the class object for a class. This 
  3461.                           method is similar to somFindClass, except the user 
  3462.                           also provides the name of a file to be used for 
  3463.                           dynamic loading, if needed. The receiver of the 
  3464.                           method is the class manager (pointed to by the global 
  3465.                           variable SOMClassMgrObject). Additional arguments are 
  3466.                           the class's somId, the major and minor version 
  3467.                           numbers, and the file name. The method returns a 
  3468.                           pointer to the class object, or NULL if the class 
  3469.                           could not be created. 
  3470.  
  3471.  somGetInstancePartSize   Obtains the size of the instance variables introduced 
  3472.                           by a class. The receiver of the method is the class 
  3473.                           object. The method returns the amount of space, in 
  3474.                           bytes, needed for the instance variables. 
  3475.  
  3476.  somGetInstanceSize       Obtains the total size requirements for an instance 
  3477.                           of a class. The receiver of the method is the class 
  3478.                           object. The method returns the amount of space, in 
  3479.                           bytes, required for the instance variables introduced 
  3480.                           by the class itself and by all of its ancestor 
  3481.                           classes. 
  3482.  
  3483.  somGetName               Obtains the name of a class. The receiver of the 
  3484.                           method is the class object. The method returns the 
  3485.                           class name. 
  3486.  
  3487.  somGetNumMethods         Obtains the number of methods available for a class. 
  3488.                           The receiver of the method is the class object. The 
  3489.                           method returns the total number of currently 
  3490.                           available methods (static or otherwise, including 
  3491.                           inherited methods). 
  3492.  
  3493.  somGetNumStaticMethods   Obtains the number of static methods available for a 
  3494.                           class. (A static method is one declared in the 
  3495.                           class's interface specification [.idl] file.) The 
  3496.                           receiver of the method is the class object. The 
  3497.                           method returns the total number of available static 
  3498.                           methods, including inherited ones. 
  3499.  
  3500.  somGetParents            Obtains a sequence of the parent (base) classes of a 
  3501.                           specified class. The receiver of the method is the 
  3502.                           class object. The method returns a pointer to a 
  3503.                           linked list of the parent (base) classes (unless the 
  3504.                           receiver is SOMObject, for which it returns NULL). 
  3505.  
  3506.  somGetVersionNumbers     Obtains the major and minor version numbers of a 
  3507.                           class. The return type is void, and the two arguments 
  3508.                           are pointers to locations in memory where the method 
  3509.                           can store the major and minor version numbers (of 
  3510.                           type long). 
  3511.  
  3512.  somSupportsMethod        Indicates whether instances of a given class support 
  3513.                           a given method. The receiver of the somSupportsMethod 
  3514.                           method is the class object. The argument is the somId 
  3515.                           for the method in question. The somSupportsMethod 
  3516.                           method returns TRUE if the method is supported, or 
  3517.                           FALSE otherwise. 
  3518.  
  3519.  See the SOMobjects Developer Toolkit: Programmers Reference Manual for more 
  3520.  information on a specific method. 
  3521.  
  3522.  
  3523. ΓòÉΓòÉΓòÉ 5.3.3. Getting information about an object ΓòÉΓòÉΓòÉ
  3524.  
  3525. The following methods and functions are used to obtain information about an 
  3526. object (instance) or to determine whether a variable holds a valid SOM object. 
  3527. Methods 
  3528.  
  3529.  somGetClass              Gets the class object of a specified object. The 
  3530.                           receiver of the method is the object whose class is 
  3531.                           desired. The method returns a pointer to the object's 
  3532.                           corresponding class object. 
  3533.  
  3534.  somGetClassName          Obtains the class name of an object. The receiver of 
  3535.                           the method is the object whose class name is desired. 
  3536.                           The method returns a pointer to the name of the class 
  3537.                           of which the specified object is an instance. 
  3538.  
  3539.  somGetSize               Obtains the size of an object. The receiver of the 
  3540.                           method is the object. The method returns the amount 
  3541.                           of contiguous space, in bytes, that is needed to hold 
  3542.                           the object itself (not including any additional space 
  3543.                           that the object may be using or managing outside of 
  3544.                           this area). 
  3545.  
  3546.  somIsA                   Determines whether an object is an instance of a 
  3547.                           given class or of one of its descendant classes. The 
  3548.                           receiver of the method is the object to be tested. An 
  3549.                           additional argument is the name of the class to which 
  3550.                           the object will be compared. This method returns TRUE 
  3551.                           if the object is an instance of the specified class 
  3552.                           or if (unlike somIsInstanceOf) it is an instance of 
  3553.                           any descendant class of the given class; otherwise, 
  3554.                           the method returns FALSE. 
  3555.  
  3556.  somIsInstanceOf          Determines whether an object is an instance of a 
  3557.                           specific class (but not of any descendant class).The 
  3558.                           receiver of the method is the object. The argument is 
  3559.                           the name of the class to which the object will be 
  3560.                           compared. The method returns TRUE if the object is an 
  3561.                           instance of the specified class, or FALSE otherwise. 
  3562.  
  3563.  somRespondsTo            Determines whether an object supports a given method. 
  3564.                           The receiver of the method is the object. The 
  3565.                           argument is the somId for the method in question. (A 
  3566.                           somId can be obtained from a string by using the 
  3567.                           somIdFromString function.) The somRespondsTo method 
  3568.                           returns TRUE if the object supports the method, or 
  3569.                           FALSE otherwise. 
  3570.  
  3571.  Functions 
  3572.  
  3573.  somIsObj                 Takes as its only argument an address (which may not 
  3574.                           be valid). The function returns TRUE (1) if the 
  3575.                           address contains a valid SOM object, or FALSE (0) 
  3576.                           otherwise. This function is designed to be failsafe. 
  3577.  
  3578.  See the SOMobjects Developer Toolkit: Programmers Reference Manual for more 
  3579.  information on a specific method or function. 
  3580.  
  3581.  
  3582. ΓòÉΓòÉΓòÉ 5.3.4. Debugging ΓòÉΓòÉΓòÉ
  3583.  
  3584. The following macros are used to conditionally generate output for debugging. 
  3585. All output generated by these macros is written using the replaceable 
  3586. character-output procedure pointed to by the global variable SOMOutCharRoutine. 
  3587. The default procedure simply writes the character to stdout, but it can be 
  3588. replaced to change the output destination of the methods and functions below. 
  3589. (See Chapter 5 for more information on customizing SOM.) 
  3590.  
  3591. Debugging output is produced or suppressed based on the settings of three 
  3592. global variables, SOM_TraceLevel, SOM_WarnLevel, and SOM_AssertLevel: 
  3593.  
  3594.    o  SOM_TraceLevel controls the behavior of the <className>MethodDebug macro; 
  3595.  
  3596.    o  SOM_WarnLevel controls the behavior of the macros SOM_WarnMsg, SOM_TestC, 
  3597.       and SOM_Expect; and 
  3598.  
  3599.    o  SOM_AssertLevel controls the behavior of the SOM_Assert macro. 
  3600.  
  3601.  Available macros for generating debugging output are as follows: 
  3602.  
  3603.  <className>MethodDebug   (macro for C and C++ programmers using the SOM 
  3604.                           language bindings for <className>) 
  3605.  
  3606.                           The arguments to this macro are a class name and a 
  3607.                           method name. If the SOM_TraceLevel global variable 
  3608.                           has a nonzero value, the <className>MethodDebug macro 
  3609.                           produces a message each time the specified method (as 
  3610.                           defined by the specified class) is executed. This 
  3611.                           macro is typically used within the procedure that 
  3612.                           implements the specified method. (The SOM Compiler 
  3613.                           automatically generates calls to the 
  3614.                           <className>MethodDebug macro within the 
  3615.                           implementation template files it produces.) u To 
  3616.                           suppress method tracing for all methods of a class, 
  3617.                           put the following statement in the implementation 
  3618.                           file after including the header file for the class: 
  3619.  
  3620.                                                     #define <className>MethodDebug(c,m) \
  3621.                                                                        SOM_NoTrace(c,m)
  3622.  
  3623.                           This can yield a slight performance improvement. The 
  3624.                           SOMMTraced metaclass, discussed below, provides a 
  3625.                           more extensive tracing facility that includes method 
  3626.                           parameters and returned values. 
  3627.  
  3628.  SOM_TestC                The SOM_TestC macro takes as an argument a boolean 
  3629.                           expression. If the boolean expression is TRUE 
  3630.                           (nonzero) and SOM_AssertLevel is greater than zero, 
  3631.                           then an informational message is output. If the 
  3632.                           expression is FALSE (zero) and SOM_WarnLevel is 
  3633.                           greater than zero, a warning message is produced. 
  3634.  
  3635.  SOM_WarnMsg              The SOM_WarnMsg macro takes as an argument a 
  3636.                           character string. If the value of SOM_WarnLevel is 
  3637.                           greater than zero, the specified message is output. 
  3638.  
  3639.  SOM_Assert               The SOM_Assert macro takes as arguments a boolean 
  3640.                           expression and an error code (an integer). If the 
  3641.                           boolean expression is TRUE (nonzero) and 
  3642.                           SOM_AssertLevel  is greater than zero, then an 
  3643.                           informational message is output. If the expression is 
  3644.                           FALSE (zero), and the error code indicates a 
  3645.                           warning-level error and SOM_WarnLevel is greater than 
  3646.                           zero, then a warning message is output. If the 
  3647.                           expression is FALSE and the error code indicates a 
  3648.                           fatal error, then an error message is produced and 
  3649.                           the process is terminated. 
  3650.  
  3651.  SOM_Expect               The SOM_Expect macro takes as an argument a boolean 
  3652.                           expression. If the boolean expression is FALSE (zero) 
  3653.                           and SOM_WarnLevel is set to be greater than zero, 
  3654.                           then a warning message is output. If condition is 
  3655.                           TRUE and SOM_AssertLevel is set to be greater than 
  3656.                           zero, then an informational message is output. 
  3657.  
  3658.  See the SOMobjects Developer Toolkit: Programmers Reference Manual for more 
  3659.  information on a specific macro. 
  3660.  
  3661.  The somDumpSelf and somPrintSelf methods can be useful in testing and 
  3662.  debugging. The somPrintSelf method produces a brief description of an object, 
  3663.  and the somDumpSelf method produces a more detailed description. See the 
  3664.  SOMobjects Developer Toolkit: Programmers Reference Manual for more 
  3665.  information. 
  3666.  
  3667.  
  3668. ΓòÉΓòÉΓòÉ 5.3.5. Checking the validity of method calls ΓòÉΓòÉΓòÉ
  3669.  
  3670. The C and C++ language bindings include code to check the validity of method 
  3671. calls at run time. If a validity check fails, the SOM_Error macro ends the 
  3672. process. (SOM_Error is described below.) To enable method-call validity 
  3673. checking, place the following directive in the client program prior to any 
  3674. #include directives for SOM header files: 
  3675.  
  3676. #define SOM_TestOn
  3677.  
  3678. Alternatively, the -DSOM_TestOn option can be used when compiling the client 
  3679. program to enable method-call validity checking. 
  3680.  
  3681.  
  3682. ΓòÉΓòÉΓòÉ 5.3.6. Exceptions and error handling ΓòÉΓòÉΓòÉ
  3683.  
  3684. In the classes provided in the SOM run-time library (that is, SOMClass, 
  3685. SOMObject, and SOMClassMgr), error handling is performed by a user-replaceable 
  3686. procedure, pointed to by the global variable SOMError, that produces an error 
  3687. message and an error code and, if appropriate ate, ends the process where the 
  3688. error occurred. (Chapter 5 describes how to customize the error handling 
  3689. procedure.) 
  3690.  
  3691. Each error is assigned a unique integer error code. Errors are grouped into 
  3692. three categories, based on the last digit of the error code: 
  3693.  
  3694.  SOM_Ignore               This category of error represents an informational 
  3695.                           event. The event is considered normal and can be 
  3696.                           ignored or logged at the user's discretion. Error 
  3697.                           codes having a last digit of 2 belong to this 
  3698.                           category. 
  3699.  
  3700.  SOM_Warn                 This category of error represents an unusual 
  3701.                           condition that is not a normal event, but is not 
  3702.                           severe enough to require program termination. Error 
  3703.                           codes having a last digit of 1 belong to this 
  3704.                           category. 
  3705.  
  3706.  SOM_Fatal                This category of error represents a condition that 
  3707.                           should not occur or that would result in loss of 
  3708.                           system integrity if processing were allowed to 
  3709.                           continue. In the default error handling procedure, 
  3710.                           these errors cause the termination of the process in 
  3711.                           which they occur. Error codes having a last digit of 
  3712.                           9 belong to this category. 
  3713.  
  3714.  The various codes for all errors detected by SOM are listed in Appendix A, 
  3715.  "Customer Support and Error Codes." 
  3716.  
  3717.  When errors are encountered in client programs or user defined-classes, the 
  3718.  following two macros can be used to invoke the error-handling procedure: 
  3719.  
  3720.  SOM_Error                The SOM_Error macro takes an error code as its only 
  3721.                           argument and invokes the SOM error handling procedure 
  3722.                           (pointed to by the global variable SOMError) to 
  3723.                           handle the error. The default error handling 
  3724.                           procedure prints a message that includes the error 
  3725.                           code, the name of the source file, and the line 
  3726.                           number where the macro was invoked. If the last digit 
  3727.                           of the error code indicates a serious error (of 
  3728.                           category SOM_Fatal), the process causing the error is 
  3729.                           terminated. (Chapter 5 describes how to customize the 
  3730.                           error handling procedure.) 
  3731.  
  3732.  SOM_Test                 The SOM_Test macro takes a boolean expression as an 
  3733.                           argument. If the expression is TRUE (nonzero) and the 
  3734.                           SOM_AssertLevel is greater than zero, then an 
  3735.                           informational message is output. If the expression is 
  3736.                           FALSE (zero), an error message is produced and the 
  3737.                           program is terminated. 
  3738.  
  3739.  See the SOMobjects Developer Toolkit: Programmers Reference Manual for more 
  3740.  information on a specific macro. 
  3741.  
  3742.  Other classes provided by the SOMobjects Toolkit (including those in the 
  3743.  Persistence, Replication, DSOM, and Interface Repository frameworks, and the 
  3744.  utility classes and metaclasses) handle errors differently. Rather than 
  3745.  invoking SOMError with an error code, their methods return exceptions via the 
  3746.  (Environment *) inout parameter required by these methods. The following 
  3747.  sections describe the exception declarations, the standard exceptions, and how 
  3748.  to set and get exception information in an Environment structure. 
  3749.  Exception declarations 
  3750.  
  3751.  As discussed in Chapter 4 in the section entitled "SOM Interface Definition 
  3752.  Language," a method may be declared to return zero or more exceptions. IDL 
  3753.  exceptions are implemented by simply passing back error information after a 
  3754.  method call, as opposed to the "catch/throw" model where an exception is 
  3755.  implemented by a long jump or signal. Associated with each type of exception 
  3756.  is a name, and optionally, a struct-like data structure for holding error 
  3757.  information. A method declares the types of exceptions it may return in a 
  3758.  raises expression. 
  3759.  
  3760.  Below is an example IDL declaration of a "BAD_FLAG" exception, which may be 
  3761.  "raised" by a"checkFlag" method, as part of a "MyObject" interface: 
  3762.  
  3763.      interface MyObject {
  3764.         exception BAD_FLAG { long ErrCode; char Reason[80];}
  3765.  
  3766.         void checkFlag(in unsigned long flag) raises(BAD_FLAG);
  3767.      };
  3768.  
  3769.  An exception structure contains whatever information is necessary to help the 
  3770.  caller understand the nature of the error. The exception declaration can be 
  3771.  treated like a struct definition:  i.e., whatever you can access in an IDL 
  3772.  struct, you can access in an exception declaration. Alternatively, the 
  3773.  structure can be empty, whereby the exception is just identified by its name. 
  3774.  
  3775.  The SOM Compiler will map the exception declaration in the above example to 
  3776.  the following C language constructs: 
  3777.  
  3778.      typedef struct BAD_FLAG {
  3779.         long ErrCode;
  3780.         char Reason[80];
  3781.      } BAD_FLAG;
  3782.  
  3783.      #define ex_BAD_FLAG "MyObject::BAD_FLAG"
  3784.  
  3785.  When an exception is detected, the "checkFlag" method must call SOMMalloc to 
  3786.  allocate a "BAD_FLAG" structure, initialize it with the appropriate error 
  3787.  information, and make a call to somSetException (see "Setting an exception 
  3788.  value," below) to record the exception value in the Environment structure 
  3789.  passed in the method call. The caller, after invoking "checkFlag", can check 
  3790.  the Environment structure that was passed to the method to see if there was an 
  3791.  exception, and if so, extract the exception value from the Environment (see 
  3792.  "Getting an exception value," below.) 
  3793.  Standard exceptions 
  3794.  
  3795.  In addition to user-defined exceptions (those defined explicitly in an IDL 
  3796.  file), there are several predefined exceptions for system run-time errors. A 
  3797.  system exception  can be returned on any method call. (That is, they are 
  3798.  implicitly declared for every method whose class uses IDL call style, and they 
  3799.  do not appear in any raises expressions.) The standard exceptions are listed 
  3800.  in Table 2 of Section 4.2, "SOM Interface Definition Language". Most of the 
  3801.  predefined system exceptions pertain to Object Request Broker errors. 
  3802.  Consequently, these types of exceptions are most likely to occur in DSOM 
  3803.  applications (Chapter 6). 
  3804.  
  3805.  Each of the standard exceptions has the same structure: an error code (to 
  3806.  designate the subcategory of the exception) and a completion status code. For 
  3807.  example, the NO_MEMORY standard exception has the following definition: 
  3808.  
  3809.      enum completion_status {YES, NO, MAYBE};
  3810.      exception NO_MEMORY { unsigned long minor;
  3811.                            completion_status completed; };
  3812.  
  3813.  The completion status value indicates whether the method was never initiated 
  3814.  (NO), completed execution prior to the exception (YES), or the completion 
  3815.  status is indeterminate (MAYBE). 
  3816.  
  3817.  Since all the standard exceptions have the same structure, file "somcorba.h" 
  3818.  (included by "som.h") defines a generic StExcep typedef which can be used 
  3819.  instead of the specific typedefs: 
  3820.  
  3821.      typedef struct StExcep {
  3822.           unsigned long minor;
  3823.           completion_status completed;
  3824.      } StExcep;
  3825.  
  3826.  The standard exceptions are defined in an IDL module called StExcep, in the 
  3827.  file named "stexcep.idl", and the C definitions can be found in "stexcep.h". 
  3828.  The Environment 
  3829.  
  3830.  The Environment is a data structure that contains environmental information 
  3831.  that can be passed between a caller and a called object when a method is 
  3832.  executed. For example, it is used to pass information about the user id of a 
  3833.  client, to return exception data to the client following a method call, and so 
  3834.  on. 
  3835.  
  3836.  A pointer to an Environment variable is passed as an argument to method calls 
  3837.  (unless the method's class has the callstyle=oidl SOM IDL modifier). The 
  3838.  Environment typedef is defined in "som.h", and an instance of the structure is 
  3839.  allocated by the caller in any reasonable way: on  the stack (by declaring a 
  3840.  local variable and initializing it using the macro SOM_InitEnvironment), 
  3841.  dynamically (using the SOM_CreateLocalEnvironment macro), or by calling the 
  3842.  somGetGlobalEnvironment function to allocate an Environment structure to be 
  3843.  shared by objects running in the same thread. 
  3844.  
  3845.  For class libraries that use callstyle=oidl, there is no explicit Environment 
  3846.  parameter. For these libraries, exception information may be passed using the 
  3847.  per-thread Environment structure returned by the somGetGlobalEnvironment 
  3848.  procedure. 
  3849.  Setting an exception value 
  3850.  
  3851.  To set an exception value in the caller's Environment structure, a method 
  3852.  implementation makes a call to the somSetException procedure: 
  3853.  
  3854.      void  somSetException ( Environment *ev,
  3855.                                  exception_type major,
  3856.                                  string exception_name,
  3857.                                  void *params);
  3858.  
  3859.  where "ev" is a pointer to the Environment structure passed to the method, 
  3860.  "major" is an exception_type, "exception_name" is the string name of the 
  3861.  exception (usually the constant defined by the IDL compiler, for example, 
  3862.  ex_BAD_FLAG), and "params"  is a pointer to an (initialized) exception 
  3863.  structure which must be allocated by SOMMalloc: 
  3864.  
  3865.      typedef enum exception_type {
  3866.         NO_EXCEPTION, USER_EXCEPTION, SYSTEM_EXCEPTION
  3867.      } exception_type;
  3868.  
  3869.  It is important to reiterate that somSetException expects the params argument 
  3870.  to be a pointer to a structure that was allocated using SOMMalloc. When 
  3871.  somSetException is called, the client passes ownership of the exception 
  3872.  structure to the SOM run-time environment. The SOM run-time  environment will 
  3873.  free the structure when the exception is reset (that is, upon the next call to 
  3874.  somSetException), or when the somExceptionFree procedure is called. 
  3875.  
  3876.  Note that somSetException simply sets the exception value; it performs no exit 
  3877.  processing. If there are multiple calls to somSetException before the method 
  3878.  returns, the caller will only see the last exception value. 
  3879.  Getting an exception value 
  3880.  
  3881.  After a method returns, the calling client program can look at the Environment 
  3882.  structure to see if there was an exception. The Environment struct is mostly 
  3883.  opaque, except for an exception type field named _major: 
  3884.  
  3885.      typedef struct Environment {
  3886.         exception_type   _major;
  3887.         ...
  3888.      } Environment;
  3889.  
  3890.  If ev._major != NO_EXCEPTION, there was an exception returned by the call. The 
  3891.  caller can retrieve the exception name and value (passed as parameters in the 
  3892.  somSetException call) from an Environment struct via the following functions: 
  3893.  
  3894.  string somExceptionId (Environment *ev); 
  3895.  
  3896.  somToken somExceptionValue (Environment *ev); 
  3897.  
  3898.  The somExceptionId function returns the exception name, if any, as a string. 
  3899.  The function somExceptionValue returns a pointer to the value of the 
  3900.  exception, if any, contained in the exception structure. If NULL is passed as 
  3901.  the Environment pointer in either of the above calls, an implicit call is made 
  3902.  to somGetGlobalEnvironment. 
  3903.  
  3904.  The somExceptionFree procedure will free any memory in the Environment 
  3905.  associated with the last exception: 
  3906.  
  3907.  void  somExceptionFree (Environment *ev); 
  3908.  
  3909.  If preferred, developers can alternatively use the CORBA "exception_free" API 
  3910.  to free the memory in an Environment structure. 
  3911.  
  3912.  Note: File "somcorba.h" (included by "som.h") provides the following aliases 
  3913.  for strict compliance with CORBA programming interfaces: 
  3914.  
  3915.      #ifdef CORBA_FUNCTION_NAMES
  3916.      #define exception_id    somExceptionId
  3917.      #define exception_value somExceptionValue
  3918.      #define exception_free  somExceptionFree
  3919.      #endif /* CORBA_FUNCTION_NAMES */
  3920.  
  3921.  Example 
  3922.  
  3923.  Let us define an IDL interface for a "MyObject" object, which declares a 
  3924.  "BAD_FLAG" exception, which can be raised by the "checkFlag"method, in a file 
  3925.  called "myobject.idl": 
  3926.  
  3927.      interface MyObject {
  3928.        exception BAD_FLAG { long ErrCode;   char Reason[80]; }
  3929.  
  3930.        void checkFlag(in unsigned long flag) raises(BAD_FLAG);
  3931.      };
  3932.  
  3933.  The SOM IDL compiler will map the exception to the following C language 
  3934.  constructs, in myobject.h: 
  3935.  
  3936.      typedef struct BAD_FLAG {
  3937.         long ErrCode;
  3938.         char Reason[80];
  3939.      } BAD_FLAG;
  3940.  
  3941.      #define ex_BAD_FLAG "MyObject::BAD_FLAG"
  3942.  
  3943.  A client program that invokes the "checkFlag" method might contain the 
  3944.  following error handling code.  (Note: The error checking code below lies in 
  3945.  the user-written procedure, "ErrorCheck," so the code need not be replicated 
  3946.  through the program.) 
  3947.  
  3948.      #include "som.h"
  3949.      #include "myobject.h"
  3950.  
  3951.      boolean ErrorCheck(Environment *ev);   /* prototype */
  3952.  
  3953.      main()
  3954.      {
  3955.          unsigned long flag;
  3956.          Environment ev;
  3957.          MyObject myobj;
  3958.          char     *exId;
  3959.          BAD_FLAG *badFlag;
  3960.          StExcep  *stExValue;
  3961.  
  3962.          myobj = MyObjectNew();
  3963.          flag  = 0x01L;
  3964.          SOM_InitEnvironment(&ev);
  3965.  
  3966.           /* invoke the checkFlag method, passing the Environment param */
  3967.          _checkFlag(myobj, &ev, flag);
  3968.  
  3969.          /* check for exception */
  3970.          if (ErrorCheck(&ev))
  3971.          {
  3972.             /* ... */
  3973.             somExceptionFree(&ev);   /* free the exception memory */
  3974.          }
  3975.  
  3976.          /* ... */
  3977.      }
  3978.  
  3979.      /* error checking procedure */
  3980.  
  3981.      boolean ErrorCheck(Environment *ev)
  3982.      {
  3983.        switch (ev._major)
  3984.        {
  3985.        case SYSTEM_EXCEPTION:
  3986.          /* get system exception id and value */
  3987.          exId      =  somExceptionId(ev);
  3988.          stExValue =  somExceptionValue(ev);
  3989.          /* ... */
  3990.          return( TRUE);
  3991.  
  3992.        case USER_EXCEPTION:
  3993.          /* get user-defined exception id and value */
  3994.          exId =  somExceptionId(ev);
  3995.          if (strcmp(exId, ex_BAD_FLAG) == 0)
  3996.          {
  3997.             badFlag = (BAD_FLAG *)  somExceptionValue(ev);
  3998.             /* ... */
  3999.          }
  4000.          /* ... */
  4001.          return( TRUE);
  4002.  
  4003.        case NO_EXCEPTION:
  4004.          return( FALSE);
  4005.        }
  4006.      }
  4007.  
  4008.  The implementation of the "checkFlag" method might contain the following 
  4009.  error-handling code: 
  4010.  
  4011.      #include "som.h"
  4012.      #include "myobject.h"
  4013.  
  4014.      void  checkFlag(MyObject somSelf, Environment *ev,
  4015.                      unsigned long flag)
  4016.      {
  4017.         BAD_FLAG *badFlag;
  4018.         /* ... */
  4019.  
  4020.         if ( /* flag is invalid */ )
  4021.         {
  4022.            badFlag = (BAD_FLAG *) SOMMalloc(sizeof(BAD_FLAG));
  4023.            badFlag->ErrCode = /* bad flag code */;
  4024.            strcpy(badFlag->Reason, "bad flag was passed");
  4025.            somSetException(ev, USER_EXCEPTION,
  4026.                            ex_BAD_FLAG, (void *)badFlag);
  4027.  
  4028.            return;
  4029.         }
  4030.         /* ... */
  4031.      }
  4032.  
  4033.  
  4034. ΓòÉΓòÉΓòÉ 5.3.7. Memory management ΓòÉΓòÉΓòÉ
  4035.  
  4036. The memory management functions used by SOM are a subset of those supplied in 
  4037. the ANSI C standard library. They have the same calling interface and the same 
  4038. return types as their ANSI C equivalents, but include supplemental error 
  4039. checking. Errors detected by these functions are passed to SOMError (described 
  4040. in the previous section). The correspondence between SOM memory management 
  4041. functions and their ANSI C standard library equivalents is shown below: 
  4042.  
  4043.  
  4044.  SOM Function         Equivalent ANSI C
  4045.                       Library Routine
  4046.  
  4047.  SOMMalloc            malloc
  4048.  
  4049.  SOMCalloc            calloc
  4050.  
  4051.  SOMRealloc           realloc
  4052.  
  4053.  SOMFree              free
  4054.  
  4055. SOMMalloc, SOMCalloc, SOMRealloc, and SOMFree are actually global variables 
  4056. that point to the SOM memory management functions (rather than being the names 
  4057. of the functions themselves), so that users can replace them with their own 
  4058. memory management functions if desired. (See chapter 5 for a discussion of 
  4059. replacing the SOM memory management functions.) 
  4060.  
  4061. Clearing memory for objects 
  4062.  
  4063. The memory associated with objects initialized by a client program must also be 
  4064. freed by the client.  The SOM-provided method somFree  is used to release the 
  4065. storage containing the receiver object: 
  4066.  
  4067.  #include "origcls.h"
  4068.  
  4069. main ()
  4070. {
  4071.    OrigCls myObject;
  4072.    myObject = OrigClsNew ();
  4073.  
  4074.     /*  Code to use myObject  */
  4075.     _somFree (myObject);
  4076. {
  4077.  
  4078. Clearing memory for the Environment 
  4079.  
  4080. Any memory associated with an exception in an Environment structure is 
  4081. typically freed using the somExceptionFree function. (Or, the CORBA 
  4082. "exception_free" API can be used.) The somExceptionFree function takes the 
  4083. following form (also see "Example" in the previous topic for an application 
  4084. example): 
  4085.  
  4086.   void somExceptionFree(Environment *ev); 
  4087.  
  4088. Note: For information on managing the memory, objects, and exceptions used by 
  4089. DSOM applications, see "Memory management" in Chapter 6, "Distributed SOM 
  4090. (DSOM)." 
  4091.  
  4092.  
  4093. ΓòÉΓòÉΓòÉ 5.3.8. SOM manipulations using somId's ΓòÉΓòÉΓòÉ
  4094.  
  4095. A somId is similar to a number that represents a zero-terminated string. A 
  4096. somId is used in SOM to identify method names, class names, and so forth. For 
  4097. example, many of the SOM methods that take a method or class name as a 
  4098. parameter require a value of type somId rather than string. All SOM 
  4099. manipulations using somIds are case insensitive, although the original case of 
  4100. the string is preserved. 
  4101.  
  4102. During its first use with any of the following functions, a somId is 
  4103. automatically converted to an internal representation (registered). Because the 
  4104. representation of a somId changes, a special SOM type (somId) is provided for 
  4105. this purpose. Names and the corresponding somId can be declared at compile 
  4106. time, as follows: 
  4107.  
  4108.    string example = "exampleMethodName";
  4109.    somId exampleId = &example;
  4110.  
  4111. or a somId can be generated at run time, as follows: 
  4112.  
  4113.    somId myMethodId;
  4114.    myMethodId = somIdFromString("exampleMethodName");
  4115.  
  4116. SOM provides the following functions that generate or use a somId: 
  4117.  
  4118.  somIdFromString          Finds the somId that corresponds to a string. The 
  4119.                           method takes a string as its argument, and returns a 
  4120.                           value of type somId that represents the string. The 
  4121.                           returned somId must later be freed using SOMFree. 
  4122.  
  4123.  somStringFromId          Obtains the string that corresponds to a somId. The 
  4124.                           function takes a somId as its argument and returns 
  4125.                           the string that the somId represents. 
  4126.  
  4127.  somCompareIds            Determines whether two somId values are the same 
  4128.                           (that is, represent the same string). This function 
  4129.                           takes two somId values as arguments. It returns TRUE 
  4130.                           (1) if the somIds represent the same string, or FALSE 
  4131.                           (0) otherwise. 
  4132.  
  4133.  somCheckId               Determines whether SOM already knows a somId. The 
  4134.                           function takes a somId as its argument. It verifies 
  4135.                           whether the somId is registered and in normal form, 
  4136.                           registers it if necessary, and returns the input 
  4137.                           somId. 
  4138.  
  4139.  somRegisterId            The same as somCheckId, except it returns TRUE (1) if 
  4140.                           this is the first time the somId has been registered, 
  4141.                           or FALSE (0) otherwise. 
  4142.  
  4143.  somUniqueKey             Finds the unique key for a somId. The function takes 
  4144.                           a somId identifier as its argument, and returns the 
  4145.                           unique key for the somId--a number that uniquely 
  4146.                           represents the string that the somId represents. This 
  4147.                           key is the same as the key for another somId if and 
  4148.                           only if the other somId refers to the same string as 
  4149.                           the input somId. 
  4150.  
  4151.  somTotalRegIds           Finds the total number of somIds that have been 
  4152.                           registered, as an unsigned long. This function is 
  4153.                           used to determine an appropriate argument to 
  4154.                           somSetExpectedIds, below, in later executions of the 
  4155.                           program. The function takes no input arguments. 
  4156.  
  4157.  somSetExpectedIds        Indicates how many unique somIds SOM can expect to 
  4158.                           use during program execution, which, if accurate, can 
  4159.                           improve the space and time utilization of the program 
  4160.                           slightly. This routine must be called before the SOM 
  4161.                           run-time environment is initialized (that is, before 
  4162.                           the function somEnvironmentNew is invoked and before 
  4163.                           any objects are created). This is the only SOM 
  4164.                           function that can be invoked before the SOM run-time 
  4165.                           environment is initialized. The input argument is an 
  4166.                           unsigned long. The function has no return value. 
  4167.  
  4168.  somBeginPersistentIds and somEndPersistentIds Delimit a time interval for the 
  4169.                           current thread during which it is guaranteed that (a) 
  4170.                           any new somIds that are created will refer only to 
  4171.                           static strings and (b) these strings will not be 
  4172.                           subsequently modified or freed. These functions are 
  4173.                           useful because somIds that are registered within a 
  4174.                           "persistent ID interval" can be handled more 
  4175.                           efficiently. 
  4176.  
  4177.  See the SOMobjects Developer Toolkit: Programmers Reference Manual for more 
  4178.  information on a specific function. 
  4179.  
  4180.  
  4181. ΓòÉΓòÉΓòÉ 6. SOM IDL and the SOM Compiler ΓòÉΓòÉΓòÉ
  4182.  
  4183. This chapter first discusses how to define SOM classes and then describes the 
  4184. SOM Compiler. To allow a class of objects to be implemented in one programming 
  4185. language and used in another (that is, to allow a SOM class to be language 
  4186. neutral), the interface to objects of this class must be specified separately 
  4187. from the objects' implementation. 
  4188.  
  4189. To summarize:  As a first step, a file known as the .idl file is used to 
  4190. declare classes and their methods, using SOM's language#neutral Interface 
  4191. Definition Language (IDL). Next, the SOM Compiler is run on the .idl file to 
  4192. produce a template implementation file that contains stub method procedures for 
  4193. the new and overridden methods; this preliminary code corresponds to the 
  4194. computer language that will implement the class. Then, the class implementer 
  4195. fills in the stub procedures with code that implements the methods (or 
  4196. redefines overridden methods) and sets instance data. (This implementation 
  4197. process is the subject of Chapter 5, "Implementing Classes in SOM.") At this 
  4198. point, the implementation file can be compiled and linked with a client program 
  4199. that uses it (as described in Chapter 3, "Using SOM Classes in Client 
  4200. Programs"). 
  4201.  
  4202. Syntax for SOM IDL and the SOM Compiler are presented in this chapter, along 
  4203. with along with helpful information for using them correctly. 
  4204.  
  4205.  
  4206. ΓòÉΓòÉΓòÉ 6.1. Interface vs Implementation ΓòÉΓòÉΓòÉ
  4207.  
  4208. The interface to a class of objects contains the information that a client must 
  4209. know to use an object--namely, the names of its attributes and the signatures 
  4210. of its methods.  The interface is described in a formal language independent of 
  4211. the programming language used to implement the object's methods. In SOM, the 
  4212. formal language used to define object interfaces is the Interface Definition 
  4213. Language (IDL), standardized by CORBA. 
  4214.  
  4215. The implementation of a class of objects (that is, the procedures that 
  4216. implement methods) is written in the implementer's preferred programming 
  4217. language. This language can be object-oriented (for instance, C++) or 
  4218. procedural (for instance, C). 
  4219.  
  4220. A completely implemented class definition, then, consists of two main files: 
  4221.  
  4222.    o  An IDL specification of the interface to instances of the class (the 
  4223.       interface definition file (or .idl file) and 
  4224.  
  4225.    o  Method procedures written in the implementer's language of choice (the 
  4226.       implementation file). 
  4227.  
  4228.  The interface definition file has a .idl extension, as noted. The 
  4229.  implementation file, however, has an extension specific to the language in 
  4230.  which it is written. For example, implementations written in C have a .c 
  4231.  extension, and implementations written in C++ have a .C (for AIX) or .cpp (for 
  4232.  OS/2) extension. 
  4233.  
  4234.  To assist users in implementing SOM classes, the SOMobjects Toolkit provides a 
  4235.  SOM Compiler. The SOM Compiler takes as input an object interface definition 
  4236.  file  (the .idl file) and produces a set of binding files that make it 
  4237.  convenient to implement and use a SOM class whose instances are objects that 
  4238.  support the defined interface. The binding files and their purposes are as 
  4239.  follows: 
  4240.  
  4241.    o  An implementation template that serves as a guide for how the 
  4242.       implementation file for the class should look. The class implementer 
  4243.       fills in this template file with language-specific code to implement the 
  4244.       methods that are available on the class' instances. 
  4245.  
  4246.    o  Header files to be included (a) in the class's implementation file and 
  4247.       (b) in client programs that use the class. 
  4248.  
  4249.  These binding files produced by the SOM Compiler bridge the gap between  SOM 
  4250.  and the object model used in object-oriented languages (such as C++), and they 
  4251.  allow SOM to be used with non-object-oriented languages (such as C). The SOM 
  4252.  Compiler currently produces binding files for the C and C++ programming 
  4253.  languages. SOM can also be used with other programming languages; the bindings 
  4254.  simply offer a more convenient programmer's interface to SOM. Vendors of other 
  4255.  languages may also offer SOM bindings; check with your language vendor for 
  4256.  possible SOM support. 
  4257.  
  4258.  The subsequent sections of this chapter provide full syntax for SOM IDL and 
  4259.  the SOM Compiler. 
  4260.  
  4261.  
  4262. ΓòÉΓòÉΓòÉ 6.2. SOM Interface Definition Language ΓòÉΓòÉΓòÉ
  4263.  
  4264. This section describes the syntax of SOM's Interface Definition Language (SOM 
  4265. IDL). SOM IDL complies with CORBA's standard for IDL; it also adds constructs 
  4266. specific to SOM. (For more information on the CORBA standard for IDL, see The 
  4267. Common Object Request Broker: Architecture and Specification, published by 
  4268. Object Management Group and x/Open.) The full grammar for SOM IDL is given in 
  4269. Appendix C. Instructions for converting existing OIDL-syntax files to IDL are 
  4270. given in Appendix B. The current section describes the syntax and semantics of 
  4271. SOM IDL using the following conventions: 
  4272.  
  4273.       Constants (words to be used literally, such as keywords) appear in bold. 
  4274.       User-supplied elements appear in italics. 
  4275.  
  4276.            { }  Groups related items together as a single item. 
  4277.  
  4278.            [ ]  Encloses an optional item. 
  4279.  
  4280.            *    Indicates zero or more repetitions of the preceding item. 
  4281.  
  4282.            +    Indicates one or more repetitions of the preceding item. 
  4283.  
  4284.            |    Separates alternatives. 
  4285.  
  4286.            _    Within a set of alternatives, an underscore indicates the 
  4287.                 default, if defined. 
  4288.  
  4289.  IDL is a formal language used to describe object interfaces. Because, in SOM, 
  4290.  objects are implemented as instances of classes, an IDL object interface 
  4291.  definition specifies for a class of objects what methods (operations) are 
  4292.  available, their return types, and their parameter types. For this reason, we 
  4293.  often speak of an IDL specification for a class (as opposed to simply an 
  4294.  object interface). Constructs specific to SOM discussed below further 
  4295.  strengthen this connection between SOM classes and the IDL language. 
  4296.  
  4297.  IDL generally follows the same lexical rules as C and C++, with some 
  4298.  exceptions. In particular: 
  4299.  
  4300.    o  IDL uses the ISO Latin-1 (8859.1) character set (as per the CORBA 
  4301.       standard). 
  4302.  
  4303.    o  White space is ignored except as token delimiters. 
  4304.  
  4305.    o  C and C++ comment styles are supported. 
  4306.  
  4307.    o  IDL supports standard C/C++ preprocessing, including macro substitution, 
  4308.       conditional compilation, and source file inclusion. 
  4309.  
  4310.    o  Identifiers (user-defined names for methods, attributes, instance 
  4311.       variables, and so on) are composed of alphanumeric and underscore 
  4312.       characters, (with the first character alphabetic) and can be of arbitrary 
  4313.       length, up to an operating-system limit of about 250 characters. 
  4314.  
  4315.    o  Identifiers must be spelled consistently with respect to case throughout 
  4316.       a specification. 
  4317.  
  4318.    o  Identifiers that differ only in case yield a compilation error. 
  4319.  
  4320.    o  There is a single name space for identifiers (thus, using the same 
  4321.       identifier for a constant and a class name within the same naming scope, 
  4322.       for example, yields a compilation error). 
  4323.  
  4324.    o  Integer, floating point, character, and string literals are defined just 
  4325.       as in C and C++. 
  4326.  
  4327.  Keywords must be spelled using upper- and lower-case characters exactly as 
  4328.  shown in the table. For example, "void" is correct, but "Void" yields a 
  4329.  compilation error. 
  4330.  
  4331.  A typical IDL specification for a single class, residing in a single .idl 
  4332.  file, has the following form. (Also see the later section, "Defining multiple 
  4333.  interfaces within a single .idl file.") The order is unimportant, except that 
  4334.  names must be declared (or forward referenced) before they are referenced. The 
  4335.  subsequent topics of this section describe the requirements for these 
  4336.  specifications: 
  4337.  
  4338.  Include directives       (optional) 
  4339.  
  4340.  Type declarations        (optional) 
  4341.  
  4342.  Constant declarations    (optional) 
  4343.  
  4344.  Exception declarations   (optional) 
  4345.  
  4346.  Interface declaration    (optional) 
  4347.  
  4348.  Module declaration       (optional) 
  4349.  
  4350.  The following table contains the keywords for SOM IDLs. 
  4351.  
  4352.   ΓöîΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÉ
  4353.   Γöé  any        FALSE      readonlyΓöé
  4354.   Γöéattribute  float      sequence  Γöé
  4355.   Γöéboolean    implementa short     Γöé
  4356.   Γöécase char  in inout   string    Γöé
  4357.   Γöéclass      interface  struct    Γöé
  4358.   Γöéconst      long       switch    Γöé
  4359.   Γöécontext    module     TRUE      Γöé
  4360.   Γöédefault    octet      TypeCode  Γöé
  4361.   Γöédouble     oneway out typedef   Γöé
  4362.   Γöéenum       raises     unsigned  Γöé
  4363.   Γöéexception             union voidΓöé
  4364.   ΓööΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÿ
  4365.  
  4366.  
  4367. ΓòÉΓòÉΓòÉ 6.2.1. Include directives ΓòÉΓòÉΓòÉ
  4368.  
  4369. The IDL specification for a class normally contains #include statements that 
  4370. tell the SOM Compiler where to find the interface definitions (the .idl files) 
  4371. for: 
  4372.  
  4373.    o  Each of the class's parent (direct base) classes, and 
  4374.    o  The class's metaclass (if specified). 
  4375.  
  4376.  The #include statements must appear in the above order. For example, if class 
  4377.  "C" has parents "foo" and "bar" and metaclass "meta", then file "C.idl" must 
  4378.  begin with the following #include statements: 
  4379.  
  4380.      #include <foo.idl>
  4381.      #include <bar.idl>
  4382.      #include <meta.idl>
  4383.  
  4384.  As in C and C++, if a filename is enclosed in angle brackets (< >), the search 
  4385.  for the file will begin in system-specific locations. If the filename appears 
  4386.  in double quotation marks (" "), the search for the file will begin in the 
  4387.  current working directory, then move to the system-specific locations. 
  4388.  
  4389.  
  4390. ΓòÉΓòÉΓòÉ 6.2.2. Type and constant declarations ΓòÉΓòÉΓòÉ
  4391.  
  4392. IDL specifications may include type declarations and constant declarations as 
  4393. in C and C++, with the restrictions/extensions described below.  [Note: For any 
  4394. reader not familiar with C, a recommended reference is The C Programming 
  4395. Language (2nd edition, 1988, Prentice Hall) by Brian W. Kernighan and Dennis M. 
  4396. Ritchie. See pages 36-40 for a discussion of type and constant declarations.] 
  4397.  
  4398. IDL supports the following basic types (these basic types are also defined for 
  4399. C and C++ client and implementation programs, using the SOM bindings): 
  4400. Integral types 
  4401.  
  4402. IDL supports only the integral types short,  long, unsigned short, and unsigned 
  4403. long, which represent the following value ranges: 
  4404.  
  4405.  short                    -2^15 .. 2^15 - 1 
  4406.  long                     -2^31 .. 2^31 - 1 
  4407.  unsigned short           0 .. 2^16-1 
  4408.  unsigned long            0 .. 2^32 - 1 
  4409.  
  4410.  Floating point types 
  4411.  
  4412.  IDL supports the float and double floating-point types. The float type 
  4413.  represents the IEEE single-precision floating-point numbers; double represents 
  4414.  the IEEE double-precision floating point numbers. 
  4415.  Character type 
  4416.  
  4417.  IDL supports a char type, which represents an 8-bit quantity. The ISO Latin-1 
  4418.  (8859.1) character set defines the meaning and representation of graphic 
  4419.  characters. The meaning and representation of null and formatting characters 
  4420.  is the numerical value of the character as defined in the ASCII (ISO 646) 
  4421.  standard. Unlike C/C++, type char cannot be qualified as signed or unsigned. 
  4422.  (The octet type, below, can be used in place of unsigned char.) 
  4423.  Boolean type 
  4424.  
  4425.  IDL supports a boolean type for data items that can take only the values TRUE 
  4426.  and FALSE. 
  4427.  Octet type 
  4428.  
  4429.  IDL supports an octet type, an 8-bit quantity guaranteed not to undergo 
  4430.  conversion when transmitted by the communication system. The octet type can be 
  4431.  used in place of the unsigned char type. 
  4432.  Any type 
  4433.  
  4434.  IDL supports an any type, which permits the specification of values of any IDL 
  4435.  type. In the SOM C and C++ bindings, the any type is mapped onto the following 
  4436.  struct: 
  4437.  
  4438.      typedef struct any {
  4439.          TypeCode _type;
  4440.          void *_value;
  4441.      } any;
  4442.  
  4443.  The "_value" member for an any type is a pointer to the actual value. The 
  4444.  "_type" member is a pointer to an instance of a TypeCode that represents the 
  4445.  type of the value. The TypeCode provides functions for obtaining information 
  4446.  about an IDL type. Chapter 7, "The Interface Repository Framework," describes 
  4447.  TypeCodes and their associated functions. 
  4448.  Constructed types 
  4449.  
  4450.  In addition to the above basic types, IDL also supports three constructed 
  4451.  types: struct, union, and enum. The structure and enumeration types are 
  4452.  specified in IDL the same as they are in C and C++ [Kernighan-Ritchie 
  4453.  references: struct, p. 128; union, p. 147; enum, p. 39], with the following 
  4454.  restrictions: 
  4455.  
  4456.       Unlike C/C++, recursive type specifications are allowed only through the 
  4457.       use of the sequence template type (see below). 
  4458.  
  4459.       Unlike C/C++, structures, discriminated unions, and enumerations in IDL 
  4460.       must be tagged. For example, "struct { int a; ... }" is an invalid type 
  4461.       specification. The tag introduces a new type name. 
  4462.  
  4463.       In IDL, constructed type definitions need not be part of a typedef 
  4464.       statement; furthermore, if they are part of a typedef statement, the tag 
  4465.       of the struct must differ from the type name being defined by the 
  4466.       typedef. For example, the following are valid IDL struct and enum 
  4467.       definitions: 
  4468.  
  4469.                struct myStruct {
  4470.                   long x;
  4471.                   double y;
  4472.                };                               /* defines type name myStruct*/
  4473.  
  4474.                enum colors { red, white, blue };  /* defines type name colors */
  4475.  
  4476.       By contrast, the following definitions are not valid: 
  4477.  
  4478.                typedef struct myStruct {        /*  NOT VALID  */
  4479.                   long x;
  4480.                   double y;
  4481.                } myStruct;                      /* myStruct has been redefined */
  4482.  
  4483.                typedef enum colors { red, white, blue } colors;  /* NOT VALID */
  4484.  
  4485.  The valid IDL struct and enum definitions shown above are translated by the 
  4486.  SOM Compiler into the following definitions in the C and C++ bindings, 
  4487.  assuming they were declared within the scope of interface "Hello": 
  4488.  
  4489.      typedef struct Hello_myStruct {  /* C/C++ bindings for IDL struct */
  4490.         long x;
  4491.         double y;
  4492.      } Hello_myStruct;
  4493.  
  4494.      typedef unsigned long Hello_colors; /* C/C++ bindings for IDL enum */
  4495.      #define Hello_red 1UL
  4496.      #define Hello_white 2UL
  4497.      #define Hello_blue 3UL
  4498.  
  4499.  When an enumeration is defined within an interface statement for a class, then 
  4500.  within C/C++ programs, the enumeration names must be referenced by prefixing 
  4501.  the class name. For example, if the colors enum, above, were defined within 
  4502.  the interface statement for class Hello, then the enumeration names would be 
  4503.  referenced as Hello_red, Hello_white, and Hello_blue. Notice the first 
  4504.  identifier in an enumeration is assigned the value 1. 
  4505.  
  4506.  All types and constants generated by the SOM Compiler are fully qualified. 
  4507.  That is, prepended to them is the fully qualified name of the interface or 
  4508.  module in which they appear.  For example, consider the following fragment of 
  4509.  IDL: 
  4510.  
  4511.      module M {
  4512.          typedef long long_t;
  4513.          module  N {
  4514.              typedef long long_t;
  4515.              interface I {
  4516.                  typedef long long_t;
  4517.              };
  4518.          };
  4519.      };
  4520.  
  4521.  That specification would generate the following three types: 
  4522.  
  4523.      typedef long  M_long_t;
  4524.      typedef long  M_N_long_t;
  4525.      typedef long  M_N_I_long_t;
  4526.  
  4527.  For programmer convenience, the SOM Compiler also generates shorter bindings, 
  4528.  without the interface qualification. Consider the next IDL fragment: 
  4529.  
  4530.      module M {
  4531.          typedef long long_t;
  4532.          module  N {
  4533.              typedef short short_t;
  4534.              interface I {
  4535.                  typedef char char_t;
  4536.              };
  4537.          };
  4538.      };
  4539.  
  4540.  In the C/C++ bindings of the preceding fragment, you can refer to "M_long_t" 
  4541.  as "long_t", to "M_N_short_t" as "short_t", and to "M_N_I_char_t" as "char_t". 
  4542.  
  4543.  However, these shorter forms are available only when their interpretation is 
  4544.  not ambiguous. Thus, in the first example the shorthand for "M_N_I_long_t" 
  4545.  would not be allowed, since it clashes with "M_long_t" and "M_N_long_t". If 
  4546.  these shorter forms are not required, they can be ignored by setting #define 
  4547.  SOM_DONT_USE_SHORT_NAMES before including the public header files, or by using 
  4548.  the SOM Compiler option -mnouseshort so that they are not generated in the 
  4549.  header files. 
  4550.  
  4551.  In the SOM documentation and samples, both long and short forms are 
  4552.  illustrated, for both type names and method calls. It is the responsibility of 
  4553.  each user to adopt a style according to personal preference. It should be 
  4554.  noted, however, that CORBA specifies that only the long forms must be present. 
  4555.  Union type 
  4556.  
  4557.  IDL also supports a union type, which is a cross between the C union and 
  4558.  switch statements. The syntax of a union type declaration is as follows: 
  4559.  
  4560.   union identifier switch ( switch-type )
  4561.     { case+ }
  4562.  
  4563.  The "identifier" following the union keyword defines a new legal type. (Union 
  4564.  types may also be named using a typedef declaration.) The "switch-type" 
  4565.  specifies an integral, character, boolean, or enumeration type, or the name of 
  4566.  a previously defined integral, boolean, character, or enumeration type. Each 
  4567.  "case" of the union is specified with the following syntax: 
  4568.  
  4569.  case-label+  type-spec  declarator ; 
  4570.  
  4571.  where "type-spec" is any valid type specification; "declarator" is an 
  4572.  identifier, an array declarator (such as, foo[3][5]), or a pointer declarator 
  4573.  (such as, *foo); and each "case-label" has one of the following forms: 
  4574.  
  4575.  case const-expr: 
  4576.  
  4577.  default: 
  4578.  
  4579.  The "const-expr" is a constant expression that must match or be automatically 
  4580.  castable to the "switch-type". A default case can appear no more than once. 
  4581.  
  4582.  Unions are mapped onto C/C++ structs. For example, the following IDL 
  4583.  declaration: 
  4584.  
  4585.      union Foo switch (long) {
  4586.        case 1: long x;
  4587.        case 2: float y;
  4588.        default: char z;
  4589.      };
  4590.  
  4591.  is mapped onto the following C struct: 
  4592.  
  4593.      typedef Hello_struct {
  4594.        long _d;
  4595.        union {
  4596.          long x;
  4597.          float y;
  4598.          char z;
  4599.        } _u;
  4600.      } Hello_foo;
  4601.  
  4602.  The discriminator is referred to as "_d", and the union in the struct is 
  4603.  referred to as "_u". Hence, elements of the union are referenced just as in C: 
  4604.  
  4605.      Foo v;
  4606.  
  4607.      /* get a pointer to Foo in v: */
  4608.      switch(v->_d) {
  4609.        case 1: printf("x = %ld\n", v->_u.x); break;
  4610.        case 2: printf("y = %f\n", v->_u.y); break;
  4611.        default: printf("z = %c\n", v->_u.z); break;
  4612.      }
  4613.  
  4614.  Note: This example is from The Common Object Request Broker: Architecture and 
  4615.  Specification, revision 1.1, page 90. 
  4616.  Template types (sequences and strings) 
  4617.  
  4618.  IDL defines two template types not found in C and C++: sequences and strings. 
  4619.  A sequence is a one-dimensional array with two characteristics:  a maximum 
  4620.  size (specified at compile time) and a length (determined at run time). 
  4621.  Sequences permit passing unbounded arrays between objects. Sequences are 
  4622.  specified as follows: 
  4623.  
  4624.  sequence < simple-type [, positive-integer-const] > 
  4625.  
  4626.  where "simple-type" specifies any valid IDL type, and the optional 
  4627.  "positive-integer-const" is a constant expression that specifies the maximum 
  4628.  size of the sequence (as a positive integer). 
  4629.  
  4630.  Note: The "simple-type" cannot have a `*' directly in the sequence statement. 
  4631.  Instead, a typedef for the pointer type must be used. For example, instead of: 
  4632.  
  4633.      typedef sequence<long *> seq_longptr; // Error: '*' not allowed.
  4634.  
  4635.  use: 
  4636.  
  4637.      typedef long * longptr;
  4638.      typedef sequence<longptr> seq_longptr;  // Ok.
  4639.  
  4640.  In SOM's C and C++ bindings, sequences  are mapped onto structs with the 
  4641.  following members: 
  4642.  
  4643.   unsigned long _maximum;
  4644.   unsigned long _length;
  4645.   simple-type *_buffer;
  4646.  
  4647.  where "simple-type" is the specified type of the sequence.  For example, the 
  4648.  IDL declaration 
  4649.  
  4650.      typedef sequence<long, 10> vec10;
  4651.  
  4652.  results in the following C struct: 
  4653.  
  4654.      #ifndef _IDL_SEQUENCE_long_defined
  4655.      #define _IDL_SEQUENCE_long_defined
  4656.      typedef struct {
  4657.          unsigned long _maximum;
  4658.          unsigned long _length;
  4659.          long *_buffer;
  4660.      } _IDL_SEQUENCE_long;
  4661.      #endif /* _IDL_SEQUENCE_long_defined */
  4662.      typedef _IDL_SEQUENCE_long vec10;
  4663.  
  4664.  and an instance of this type is declared as follows: 
  4665.  
  4666.      vec10 v = {10L, 0L, (long *)NULL};
  4667.  
  4668.  The "_maximum" member designates the actual size of storage allocated for the 
  4669.  sequence, and the "_length" member designates the number of values contained 
  4670.  in the "_buffer" member. For bounded sequences, it is an error to set the 
  4671.  "_length" or "_maximum" member to a value larger than the specified bound of 
  4672.  the sequence. 
  4673.  
  4674.  Before a sequence is passed as the value of an "in" or "inout" method 
  4675.  parameter, the "_buffer" member must point to an array of elements of the 
  4676.  appropriate type, and the "_length" member must contain the number of elements 
  4677.  to be passed. (If the parameter is "inout" and the sequence is unbounded, the 
  4678.  "_maximum" member must also be set to the actual size of the array. Upon 
  4679.  return, "_length" will contain the number of values copied into "_buffer", 
  4680.  which must be less than "_maximum".) When a sequence is passed as an "out" 
  4681.  method parameter or received as the return value, the method procedure 
  4682.  allocates storage for "_buffer" as needed, the "_length" member contains the 
  4683.  number of elements returned, and the "_maximum" member contains the number of 
  4684.  elements allocated. (The client is responsible for subsequently freeing the 
  4685.  memory pointed to by  "_buffer".) 
  4686.  
  4687.  C and C++ programs using SOM's language bindings can refer to sequence types 
  4688.  as: 
  4689.  
  4690.  _IDL_SEQUENCE_type 
  4691.  
  4692.  where "type" is the effective type of the sequence members. For example, the 
  4693.  IDL type sequence<long,10> is referred to in a C/C++ program by the type name 
  4694.  _IDL_SEQUENCE_long. If longint is defined via a typedef to be type long, then 
  4695.  the IDL type sequence<longint,10> is also referred to by the type name 
  4696.  _IDL_SEQUENCE_long. 
  4697.  
  4698.  If the typedef is for a pointer type, then the effective type is the name of 
  4699.  the pointer type. For example, the following statements define a C/C++ type 
  4700.  _IDL_SEQUENCE_longptr and not _IDL_SEQUENCE_long: 
  4701.  
  4702.      typedef long * longptr;
  4703.      typedef sequence<longptr> seq_longptr;
  4704.  
  4705.  A string is similar to a sequence of type char. It can contain all possible 
  4706.  8-bit quantities except NULL. Strings are specified as follows: 
  4707.  
  4708.  string  [ < positive-integer-const > ] 
  4709.  
  4710.  where the optional "positive-integer-const" is a constant expression that 
  4711.  specifies the maximum size of the string (as a positive integer, which does 
  4712.  not include the extra byte to hold a NULL as required in C/C++). In SOM's C 
  4713.  and C++ bindings, strings are mapped onto zero-byte terminated character 
  4714.  arrays. The length of the string is encoded by the position of the zero-byte. 
  4715.  For example, the following IDL declaration: 
  4716.  
  4717.      typedef string<10> foo;
  4718.  
  4719.  is converted to the following C/C++ typedef: 
  4720.  
  4721.      typedef char *foo;
  4722.  
  4723.  A variable of this type is then declared as follows: 
  4724.  
  4725.      foo s = (char *) NULL;
  4726.  
  4727.  C and C++ programs using SOM's language bindings can refer to string types by 
  4728.  the type name string. 
  4729.  
  4730.  When an unbounded string is passed as the value of an "inout" method 
  4731.  parameter, the returned value is constrained to be no longer than the input 
  4732.  value. Hence, using unbounded strings as "inout" parameters is not advised. 
  4733.  Arrays 
  4734.  
  4735.  Multidimensional, fixed-size arrays can be declared in IDL as follows: 
  4736.  
  4737.  identifier {[ positive-integer-const ] }+ 
  4738.  
  4739.  where the "positive-integer-const" is a constant expression that specifies the 
  4740.  array size, in each dimension, as a positive integer. The array size is fixed 
  4741.  at compile time. 
  4742.  Pointers 
  4743.  
  4744.  Although the CORBA standard for IDL does not include them, SOM IDL offers 
  4745.  pointer types. Declarators of a pointer type are specified as in C and C++: 
  4746.  
  4747.  type *declarator 
  4748.  
  4749.  where "type" is a valid IDL type specification and "declarator" is an 
  4750.  identifier or an array declarator. 
  4751.  Object types 
  4752.  
  4753.  The name of the interface to a class of objects can be used as a type. For 
  4754.  example, if an IDL specification includes an interface declaration (described 
  4755.  below) for a class (of objects)  "C1", then "C1" can be used as a type name 
  4756.  within that IDL specification. When used as a type, an interface name 
  4757.  indicates a pointer to an object that supports that interface. An interface 
  4758.  name can be used as the type of a method argument, as a method return type, or 
  4759.  as the type of a member of a constructed type (a struct, union, or enum). In 
  4760.  all cases, the use of an interface name implicitly indicates a pointer to an 
  4761.  object that supports that interface. 
  4762.  
  4763.  As explained in Using SOM Classes in Client Programs, SOM's C usage bindings 
  4764.  for SOM classes also follow this convention. However, within SOM's C++ 
  4765.  bindings, the pointer is made explicit, and the use of an interface name as a 
  4766.  type refers to a class instance itself, rather than a pointer to a class 
  4767.  instance. For example, to declare a variable "myobj" that is a pointer to an 
  4768.  instance of class "Foo" in an IDL specification and in a C program, the 
  4769.  following declaration is required: 
  4770.  
  4771.      Foo myobj;
  4772.  
  4773.  However, in a C++ program, the following declaration is required: 
  4774.  
  4775.      Foo *myobj;
  4776.  
  4777.  If a C programmer uses the SOM Compiler option -maddstar, then the bindings 
  4778.  generated for C will also require an explicit `*' in declarations. Thus, 
  4779.  
  4780.  Foo myobj;               in IDL requires 
  4781.  
  4782.  Foo *myobj;              in both C and C++ programs 
  4783.  
  4784.  This style of bindings for C is permitted for two reasons: 
  4785.  
  4786.    o  It more closely resembles the bindings for C++, thus making it easier to 
  4787.       change to the C++ bindings at a later date; and 
  4788.  
  4789.    o  It is required for compatibility with existing SOM OIDL code. 
  4790.  
  4791.  Note: The same C and C++ binding emitters should not be run in the same SOM 
  4792.  Compiler command. For example, 
  4793.  
  4794.      sc "-sh;xh" cls.idl    // Not valid.
  4795.  
  4796.  If you wish to generate both C and C++ bindings, you should issue the commands 
  4797.  separately: 
  4798.  
  4799.      sc -sh cls.idl
  4800.      sc -sxh cls.idl
  4801.  
  4802.  
  4803. ΓòÉΓòÉΓòÉ 6.2.3. Exception declarations ΓòÉΓòÉΓòÉ
  4804.  
  4805. IDL specifications may include exception declarations, which define data 
  4806. structures to be returned when an exception occurs during the execution of a 
  4807. method. (IDL exceptions are implemented by simply passing back error 
  4808. information after a method call, as opposed to the "catch/throw" model where an 
  4809. exception is implemented by a long jump or signal.)  Associated with each type 
  4810. of exception is a name and, optionally, a struct-like data structure for 
  4811. holding error information. Exceptions are declared as follows: 
  4812.  
  4813. exception  identifier { member* }; 
  4814.  
  4815. The "identifier" is the name of the exception, and each "member" has the 
  4816. following form: 
  4817.  
  4818. type-spec declarators ; 
  4819.  
  4820. where "type-spec" is a valid IDL type specification and "declarators" is a list 
  4821. of identifiers, array declarators, or pointer declarators, delimited by commas. 
  4822. The members of an exception structure should contain information to help the 
  4823. caller understand the nature of the error. The exception declaration can be 
  4824. treated like a struct  definition; that is, whatever you can access in an IDL 
  4825. struct, you can access in an exception declaration.  Alternatively, the 
  4826. structure can be empty, whereby the exception is just identified by its name. 
  4827.  
  4828. If an exception is returned as the outcome of a method, the exception 
  4829. "identifier" indicates which exception occurred. The values of the members of 
  4830. the exception provide additional information specific to the exception. The 
  4831. topic "Method declarations" below describes how to indicate that a particular 
  4832. method may raise a particular exception, and Using SOM Classes in Client 
  4833. Programs, describes how exceptions are handled, in the section entitled 
  4834. "Exceptions and error handling." 
  4835.  
  4836. Following is an example declaration of a "BAD_FLAG" exception: 
  4837.  
  4838.    exception BAD_FLAG { long ErrCode; char Reason[80]; };
  4839.  
  4840. The SOM Compiler will map the above exception declaration to the following C 
  4841. language constructs: 
  4842.  
  4843.    #define ex_BAD_FLAG "::BAD_FLAG"
  4844.    typedef struct BAD_FLAG {
  4845.        long  ErrCode;
  4846.        char  Reason[80];
  4847.    } BAD_FLAG;
  4848.  
  4849. Thus, the ex_BAD_FLAG symbol can be used as a shorthand for naming the 
  4850. exception. 
  4851.  
  4852. An exception declaration within an interface "Hello", such as this: 
  4853.  
  4854.    interface Hello {
  4855.        exception LOCAL_EXCEPTION { long ErrCode; };
  4856.    };
  4857.  
  4858. would map onto: 
  4859.  
  4860.    #define ex_Hello_LOCAL_EXCEPTION "::Hello::LOCAL_EXCEPTION"
  4861.    typedef struct Hello_LOCAL_EXCEPTION {
  4862.        long  ErrCode;
  4863.    } Hello_LOCAL_EXCEPTION;
  4864.    #define ex_LOCAL_EXCEPTION ex_Hello_LOCAL_EXCEPTION
  4865.  
  4866. In addition to user-defined exceptions, there are several predefined exceptions 
  4867. for system run-time errors. These exceptions correspond to standard run-time 
  4868. errors that may occur during the execution of any method (regardless of the 
  4869. list of exceptions listed in its IDL specification). 
  4870.  
  4871. Each of the standard exceptions has the same structure: an error code (to 
  4872. designate the subcategory of the exception) and a completion status code. For 
  4873. example, the NO_MEMORY standard exception has the following definition: 
  4874.  
  4875.    enum completion_status {YES, NO, MAYBE};
  4876.    exception NO_MEMORY { unsigned long minor;
  4877.                          completion_status completed; };
  4878.  
  4879. The "completion_status" value indicates whether the method was never initiated 
  4880. (NO), completed its execution prior to the exception (YES), or the completion 
  4881. status is indeterminate (MAYBE). 
  4882.  
  4883. Since all the standard exceptions have the same structure,  somcorba.h 
  4884. (included by som.h) defines a generic StExcep typedef which can be used instead 
  4885. of the specific typedefs: 
  4886.  
  4887.    typedef struct StExcep {
  4888.         unsigned long minor;
  4889.         completion_status completed;
  4890.    } StExcep;
  4891.  
  4892. The standard exceptions are defined in an IDL module called StExcep, in the 
  4893. file called stexcep.idl, and the C definitions can be found in stexcep.h. 
  4894.  
  4895. The following table contains the standard exceptions defined by CORBA. 
  4896.  
  4897. ΓöîΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÉ
  4898. Γöémodule StExcep {                         Γöé
  4899. Γöé                                         Γöé
  4900. Γöé  #define ex_body {                      Γöé
  4901. Γöéunsigned long minor;                     Γöé
  4902. Γöécompletion_status                        Γöé
  4903. Γöécompleted; }                             Γöé
  4904. Γöé                                         Γöé
  4905. Γöé  enum                                   Γöé
  4906. Γöécompletion_status {                      Γöé
  4907. ΓöéYES, NO, MAYBE };                        Γöé
  4908. Γöé                                         Γöé
  4909. Γöé  enum                                   Γöé
  4910. Γöéexception_type                           Γöé
  4911. Γöé{NO_EXCEPTION,                           Γöé
  4912. ΓöéUSER_EXCEPTION,                          Γöé
  4913. ΓöéSYSTEM_EXCEPTION};                       Γöé
  4914. Γöé                                         Γöé
  4915. Γöé  exception UNKNOWN  ex_body;   // the   Γöé
  4916. Γöé                     unknown exception   Γöé
  4917. Γöé                                         Γöé
  4918. Γöé  exception          ex_body;   // an    Γöé
  4919. ΓöéBAD_PARAM            invalid parameter   Γöé
  4920. Γöé                     was passed          Γöé
  4921. Γöé                                         Γöé
  4922. Γöé  exception          ex_body;   //       Γöé
  4923. ΓöéNO_MEMORY            dynamic memory      Γöé
  4924. Γöé                     allocation failure  Γöé
  4925. Γöé                                         Γöé
  4926. Γöé  exception          ex_body;   //       Γöé
  4927. ΓöéIMP_LIMIT            violated            Γöé
  4928. Γöé                     implementation limitΓöé
  4929. Γöé                                         Γöé
  4930. Γöé  exception          ex_body;   //       Γöé
  4931. ΓöéCOMM_FAILURE         communication       Γöé
  4932. Γöé                     failure             Γöé
  4933. Γöé                                         Γöé
  4934. Γöé  exception          ex_body;   //       Γöé
  4935. ΓöéINV_OBJREF           invalid object      Γöé
  4936. Γöé                     reference           Γöé
  4937. Γöé                                         Γöé
  4938. Γöé  exception          ex_body;   // no    Γöé
  4939. ΓöéNO_PERMISSION        permission for      Γöé
  4940. Γöé                     attempted op.       Γöé
  4941. Γöé                                         Γöé
  4942. Γöé  exception INTERNAL ex_body;   // ORB   Γöé
  4943. Γöé                     internal error      Γöé
  4944. Γöé                                         Γöé
  4945. Γöé  exception MARSHAL  ex_body;   // error Γöé
  4946. Γöé                     marshalling         Γöé
  4947. Γöé                     param/result        Γöé
  4948. Γöé                                         Γöé
  4949. Γöé  exception          ex_body;   // ORB   Γöé
  4950. ΓöéINITIALIZE           initialization      Γöé
  4951. Γöé                     failure             Γöé
  4952. Γöé                                         Γöé
  4953. Γöé  exception          ex_body;   // op.   Γöé
  4954. ΓöéNO_IMPLEMENT         implementation      Γöé
  4955. Γöé                     unavailable         Γöé
  4956. Γöé                                         Γöé
  4957. Γöé  exception          ex_body;   // bad   Γöé
  4958. ΓöéBAD_TYPECODE         typecode            Γöé
  4959. Γöé                                         Γöé
  4960. Γöé  exception          ex_body;   //       Γöé
  4961. ΓöéBAD_OPERATION        invalid operation   Γöé
  4962. Γöé                                         Γöé
  4963. Γöé  exception          ex_body;   //       Γöé
  4964. ΓöéNO_RESOURCES         insufficient        Γöé
  4965. Γöé                     resources for       Γöé
  4966. Γöé                     request             Γöé
  4967. Γöé                                         Γöé
  4968. Γöé  exception          ex_body;   //       Γöé
  4969. ΓöéNO_RESPONSE          response to req. notΓöé
  4970. Γöé                     yet available       Γöé
  4971. Γöé                                         Γöé
  4972. Γöé  exception          ex_body;   //       Γöé
  4973. ΓöéPERSIST_STORE        persistent storage  Γöé
  4974. Γöé                     failure             Γöé
  4975. Γöé                                         Γöé
  4976. Γöé  exception          ex_body;   //       Γöé
  4977. ΓöéBAD_INV_ORDER        routine invocations Γöé
  4978. Γöé                     out of order        Γöé
  4979. Γöé                                         Γöé
  4980. Γöé  exception          ex_body;   //       Γöé
  4981. ΓöéTRANSIENT            transient failure - Γöé
  4982. Γöé                     reissue request     Γöé
  4983. Γöé                                         Γöé
  4984. Γöé  exception FREE_MEM ex_body;   // cannotΓöé
  4985. Γöé                     free memory         Γöé
  4986. Γöé                                         Γöé
  4987. Γöé  exception          ex_body;   //       Γöé
  4988. ΓöéINV_IDENT            invalid identifier  Γöé
  4989. Γöé                     syntax              Γöé
  4990. Γöé                                         Γöé
  4991. Γöé  exception INV_FLAG ex_body;   //       Γöé
  4992. Γöé                     invalid flag was    Γöé
  4993. Γöé                     specified           Γöé
  4994. Γöé                                         Γöé
  4995. Γöé  exception          ex_body;   // error Γöé
  4996. ΓöéINTF_REPOS           accessing interface Γöé
  4997. Γöé                     repository          Γöé
  4998. Γöé                                         Γöé
  4999. Γöé  exception CONTEXT  ex_body;   // error Γöé
  5000. Γöé                     processing context  Γöé
  5001. Γöé                     object              Γöé
  5002. Γöé                                         Γöé
  5003. Γöé  exception          ex_body;   //       Γöé
  5004. ΓöéOBJ_ADAPTER          failure detected by Γöé
  5005. Γöé                     object adapter      Γöé
  5006. Γöé                                         Γöé
  5007. Γöé  exception          ex_body;   // data  Γöé
  5008. ΓöéDATA_CONVERSION      conversion error    Γöé
  5009. Γöé                                         Γöé
  5010. Γöé};                                       Γöé
  5011. ΓööΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÿ
  5012.  
  5013.  
  5014. ΓòÉΓòÉΓòÉ 6.2.4. Interface declarations ΓòÉΓòÉΓòÉ
  5015.  
  5016. The IDL specification for a class of objects must contain a declaration of the 
  5017. interface these objects will support. Because, in SOM, objects are implemented 
  5018. using classes, the interface name is always used as a class name as well. 
  5019. Therefore, an interface declaration can be understood to specify a class name, 
  5020. and its parent (direct base) class names. This is the approach used in the 
  5021. following description of an interface declaration. In addition to the class 
  5022. name and its parents names, an interface indicates new methods (operations), 
  5023. and any constants, type definitions, and exception structures that the 
  5024. interface exports. An interface declaration has the following syntax: 
  5025.  
  5026. interface class-name [: parent-class1, parent-class2, ...]
  5027. {
  5028. constant declarations                 (optional)
  5029. type declarations                   (optional)
  5030. exception declarations                (optional)
  5031. attribute declarations                (optional)
  5032. method declarations                  (optional)
  5033. implementation statement               (optional)
  5034. };
  5035.  
  5036. Many class implementers distinguish a "class-name" by using an initial capital 
  5037. letter, but that is optional. The "parent-class" (or base-class) names specify 
  5038. the interfaces from which the interface of "class-name" instances is derived. 
  5039. Parent-class names are required only for the immediate parent(s). Each parent 
  5040. class must have its own IDL specification (which must be #included in the 
  5041. subclass's .idl file). A parent class cannot be named more than once in the 
  5042. interface statement header. 
  5043.  
  5044. Note: In general, an "interface class-name" header must precede any subsequent 
  5045. implementation that references "class-name." For more discussion of multiple 
  5046. interface statements, refer to the later topic "Defining multiple interfaces 
  5047. within a single idl file." 
  5048.  
  5049. The following topics describe the various declarations/statements that can be 
  5050. specified within the body of an interface declaration. The order in which these 
  5051. declarations are specified is usually optional, and declarations of different 
  5052. kinds can be intermixed. Although all of the declarations/statements are listed 
  5053. above as "optional," in some cases using one of them may mandate another. For 
  5054. example, if a method raises an exception, the exception structure must be 
  5055. defined beforehand. In general, types, constants, and exceptions, as well as 
  5056. interface declarations, must be defined before they are referenced, as in 
  5057. C/C++. 
  5058.  
  5059.  
  5060. ΓòÉΓòÉΓòÉ 6.2.5. Constant, type, and exception declarations ΓòÉΓòÉΓòÉ
  5061.  
  5062. The form of a constant, type, or exception declaration within the body of an 
  5063. interface declaration is the same as described previously in this chapter. 
  5064. Constants and types defined within an interface for a class are transferred by 
  5065. the SOM Compiler to the binding files it generates for that class, whereas 
  5066. constants and types defined outside of an interface are not. 
  5067.  
  5068. Global types (such as, those defined outside of an interface and module) can be 
  5069. emitted by surrounding them with the following #pragmas: 
  5070.  
  5071.    #pragma somemittypes on
  5072.         typedef sequence <long,10> vec10;
  5073.         exception BAD_FLAG { long ErrCode; char Reason[80]; };
  5074.         typedef long long_t;
  5075.    #pragma somemittypes off
  5076.  
  5077. Types, constants, and exceptions defined in a parent class are also accessible 
  5078. to the child class. References to them, however, must be unambiguous. Potential 
  5079. ambiguities can be resolved by prefacing a name with the name of the class that 
  5080. defines it, separated by the characters "::" as illustrated below: 
  5081.  
  5082.    MyParentClass::myType
  5083.  
  5084. The child class can redefine any of the type, constant, and exception names 
  5085. that have been inherited, although this is not advised. The derived class 
  5086. cannot, however, redefine attributes or methods. It can only replace the 
  5087. implementation of methods through overriding (as in example 3 of the Tutorial). 
  5088. To refer to a constant, type, or exception "name" defined by a parent class and 
  5089. redefined by "class-name," use the "parent-name::name" syntax as before. 
  5090.  
  5091. Note: A name reference such as MyParentClass::myType required in IDL syntax is 
  5092. equivalent to MyParentClass_myType in C/C++. For a full discussion of name 
  5093. recognition in SOM, see "Scoping and name resolution" later in this chapter. 
  5094.  
  5095.  
  5096. ΓòÉΓòÉΓòÉ 6.2.6. Attribute declarations ΓòÉΓòÉΓòÉ
  5097.  
  5098. Declaring an attribute as part of an interface is equivalent to declaring two 
  5099. accessor methods: one to retrieve the value of the attribute (a "get" method, 
  5100. named "_get_<attributeName>") and one to set the value of the attribute (a 
  5101. "set" method, named "_set_<attributeName>"). 
  5102.  
  5103. Attributes are declared as follows: 
  5104.  
  5105. [ readonly ]  attribute  type-spec declarators ; 
  5106.  
  5107. where "type-spec" specifies any valid IDL type and "declarators" is a list of 
  5108. identifiers or pointer declarators, delimited by commas. (An array declarator 
  5109. cannot be used directly when declaring an attribute, but the type of an 
  5110. attribute can be a user-defined type that is an array.) The optional readonly 
  5111. keyword specifies that the value of the attribute can be accessed but not 
  5112. modified by client programs.  (In other words, a readonly attribute has no 
  5113. "set" method.) Below are examples of attribute declarations, which are 
  5114. specified within the body of an interface statement for a class: 
  5115.  
  5116.    interface Goodbye: Hello, SOMObject
  5117.    {
  5118.      void  sayBye();
  5119.  
  5120.      attribute short xpos;
  5121.      attribute char c1, c2;
  5122.      readonly attribute float xyz;
  5123.    };
  5124.  
  5125. The preceding attribute declarations are equivalent to defining the following 
  5126. methods: 
  5127.  
  5128.    short _get_xpos();
  5129.    void  _set_xpos(in short xpos);
  5130.    char  _get_c1();
  5131.    void  _set_c1(in char c1);
  5132.    char  _get_c2();
  5133.    void  _set_c2(in char c2);
  5134.    float _get_xyz();
  5135.  
  5136. Note: Although the preceding attribute declarations are equivalent to the 
  5137. explicit method declarations above, these method declarations are not legal 
  5138. IDL, because the method names begin with an `_'. All IDL identifiers must begin 
  5139. with an alphabetic character, not including `_'. 
  5140.  
  5141. Attributes are inherited from ancestor classes (indirect base classes). An 
  5142. inherited attribute name cannot be redefined to be a different type. 
  5143.  
  5144.  
  5145. ΓòÉΓòÉΓòÉ 6.2.7. Method (operation) declarations ΓòÉΓòÉΓòÉ
  5146.  
  5147. Method (operation) declarations define the interface of each method introduced 
  5148. by the class. A method declaration is similar to a C/C++ function definition: 
  5149.  
  5150. [oneway] type-spec identifier ( parameter-list) [raises-expr]  [context-expr] ;
  5151. where "identifier" is the name of the method and "type-spec" is any valid IDL 
  5152. type (or the keyword void, indicating that the method returns no value). Unlike 
  5153. C and C++ procedures, methods that do not return a result must specify void as 
  5154. their return type. The remaining syntax of a method declaration is elaborated 
  5155. in the following subtopics. 
  5156.  
  5157. Note:  Although IDL does not allow methods to receive and return values whose 
  5158. type is a pointer to a function, it does allow methods to receive and return 
  5159. method names (as string values). Thus, rather than defining methods that pass 
  5160. pointers to functions (and that subsequently invoke those functions), 
  5161. programmers should instead define methods that pass method names (and 
  5162. subsequently invoke those methods using one of the SOM-supplied 
  5163. method-dispatching or method-resolution methods or functions, such as 
  5164. somDispatch). 
  5165. Oneway keyword 
  5166.  
  5167. The optional oneway keyword specifies that when a client invokes the method, 
  5168. the invocation semantics are "best-effort", which does not guarantee delivery 
  5169. of the call. "Best-effort" implies that the method will be invoked at most 
  5170. once. A oneway method should not have any output parameters and should have a 
  5171. return type of void. A oneway method also should not include a "raises 
  5172. expression" (see below), although it may raise a standard exception. 
  5173.  
  5174. If the oneway keyword is not specified, then the method has "at-most-once" 
  5175. invocation semantics if an exception is raised, and it has "exactly-once" 
  5176. semantics if the method succeeds. This means that a method that raises an 
  5177. exception has been executed zero or one times, and a method that succeeds has 
  5178. been executed exactly once. 
  5179.  
  5180. Note: Currently the "oneway" keyword, although accepted, has no effect on the 
  5181. C/C++ bindings that are generated. 
  5182. Parameter list 
  5183.  
  5184. The "parameter-list" contains zero or more parameter declarations for the 
  5185. method, delimited by commas. (The target object for the method is not 
  5186. explicitly specified as a method parameter in IDL, nor are the Environment or 
  5187. Context parameters.)  If there are no explicit parameters, the syntax "( )" 
  5188. must be used, rather than "(void)". A parameter declaration has the following 
  5189. syntax: 
  5190.  
  5191. { in Γöé out Γöé inout }  type-spec  declarator 
  5192.  
  5193. where "type-spec" is any valid IDL type and "declarator" is an identifier, 
  5194. array declarator, or pointer declarator. 
  5195.  
  5196. In, out, inout parameters:  The required inΓöéoutΓöéinout directional attribute 
  5197. indicates whether the parameter is to be passed from client to server (in), 
  5198. from server to client (out), or in both directions (inout). A method must not 
  5199. modify an in  parameter. If a method raises an exception, the values of the 
  5200. return result and the values of the out and inout parameters (if any) are 
  5201. undefined. When an unbounded string or sequence is passed as an inout 
  5202. parameter, the returned value must be no longer than the input value. 
  5203.  
  5204. The following are examples of valid method declarations in SOM IDL: 
  5205.  
  5206.    short meth1(in char c, out float f);
  5207.    oneway void meth2(in char c);
  5208.    float meth3();
  5209.  
  5210. Classes derived from SOMObject can declare methods that take a pointer to a 
  5211. block of memory containing a variable number of arguments, using a final 
  5212. parameter of type va_list. The va_list must use the parameter name "ap", as in 
  5213. the following example: 
  5214.  
  5215.    void MyMethod(in short numArgs, in va_list ap);
  5216.  
  5217. For in parameters of type array, C and C++ clients must pass the address of the 
  5218. first element of the array. For in parameters of type struct,  union, sequence 
  5219. or any, C/C++ clients must pass the address of a variable of that type, rather 
  5220. than the variable itself. 
  5221.  
  5222. For all IDL types except arrays, if a parameter of a method is out or inout, 
  5223. then C/C++ clients must pass the address of a variable of that type (or the 
  5224. value of a pointer to that variable) rather than the variable itself. (For 
  5225. example, to invoke method "meth1" above, a pointer to a variable of type float 
  5226. must be passed in place of parameter "f".) For arrays, C/C++ clients must pass 
  5227. the address of the first element of the array. 
  5228.  
  5229. If the return type of a method is a struct, union, sequence, or any type, then 
  5230. for C/C++ clients, the method returns the value of the C/C++ struct 
  5231. representing the IDL struct, union, sequence, or any. If the return type is 
  5232. string, then the method returns a pointer to the first character of the string. 
  5233. If the return type is array, then the method returns a pointer to the first 
  5234. element of the array. 
  5235.  
  5236. The pointers implicit in the parameter types and return types for IDL method 
  5237. declarations are made explicit in SOM's C and C++ bindings. Thus, the stub 
  5238. procedure that the SOM Compiler generates for method "meth1", above, has the 
  5239. following signature: 
  5240.  
  5241.    SOM_Scope short  SOMLINK meth1(char c, float *f)
  5242.  
  5243. For C and C++ clients, if a method has an out parameter of type  string 
  5244. sequence, or any, then the method must allocate the storage for the string, for 
  5245. the "_buffer" member of the struct that represents the sequence, or for the 
  5246. "_value" member of the struct that represents the any. It is then the 
  5247. responsibility of the client program to free the storage when it is no longer 
  5248. needed. Similarly, if the return type of a method is string, sequence, array, 
  5249. or any, then storage must be allocated by the method, and it will be the 
  5250. responsibility of the client program to subsequently free it. 
  5251.  
  5252. Note: The foregoing description also applies for the _get_ <attributeName> 
  5253. method associated with an attribute of type string, sequence, any, or array. 
  5254. Hence, the attribute should be specified with a "noget" modifier to override 
  5255. automatic implementation of the attribute's "get" method.  Then, needed memory 
  5256. can be allocated by the developer's "get" method implementation and 
  5257. subsequently deallocated by the caller.  (The "noget" modifier is described 
  5258. under the topic "Modifier statements" later in this section.) 
  5259. Raises expression 
  5260.  
  5261. The optional raises expression ("raises-expr") in a method declaration 
  5262. indicates which exceptions the method may raise. (IDL exceptions are 
  5263. implemented by simply passing back error information after a method call, as 
  5264. opposed to the "catch/throw" model where an exception is implemented by a long 
  5265. jump or signal.)  A raises expression is specified as follows: 
  5266.  
  5267. raises ( identifier1, identifier2, ... ) 
  5268.  
  5269. where each "identifier" is the name of a previously defined exception. In 
  5270. addition to the exceptions listed in the raises expression, a method may also 
  5271. signal any of the standard exceptions. Standard exceptions, however, should not 
  5272. appear in a raises expression. If no raises expression is given, then a method 
  5273. can raise only the standard exceptions. (See the earlier topic "Exception 
  5274. declarations" for information on defining exceptions and for the list of 
  5275. standard exceptions. See Chapter 3, the section entitled "Exceptions and error 
  5276. handling," for information on using exceptions.) 
  5277. Context expression 
  5278.  
  5279. The optional context expression ("context-expr") in a method declaration 
  5280. indicates which elements of the client's context the method may consult. A 
  5281. context expression is specified as follows: 
  5282.  
  5283. context ( identifier1, identifier2, ... ) 
  5284.  
  5285. where each "identifier" is a string literal made up of alphanumeric characters, 
  5286. periods, underscores, and asterisks. (The first character must be alphabetic, 
  5287. and an asterisk can only appear as the last character, where it serves as a 
  5288. wildcard matching any characters. If convenient, identifiers may consist of 
  5289. period-separated valid identifier names, but that form is optional.) 
  5290.  
  5291. The Context is a special object that is specified by the CORBA standard.  It 
  5292. contains a properly list--a set of property-name/string-value pairs that the 
  5293. client can use to store information about its environment that methods may find 
  5294. useful.  It is used in much the same way as environment variables.  It is 
  5295. passed as an additional (third) parameter to CORBA-compliant methods that are 
  5296. defined as "context-sensitive" in IDL, along with the CORBA-defined Environment 
  5297. structure. 
  5298.  
  5299. The context expression of a mehod declaration in IDL specifies which property 
  5300. names the method uses.  If these properties are present in the Context object 
  5301. supplied by the client, they will be passed to the object implementation, which 
  5302. can access them via the get_values method of the Context object. However, the 
  5303. argument that is passed to the method having a context expression is a Context 
  5304. object, not the names of the properties.  The client program must either create 
  5305. a Context object and use the set_values or set_one_value method of the Context 
  5306. class to set the context properties, or use the get_default_context method. The 
  5307. client program then passes the Context object in the method invocation.  Note 
  5308. that the CORBA standard also allows properties in addition to those in the 
  5309. context expression to be passed in the Context object. 
  5310.  
  5311. In Chapter 3, "Using SOM Classes in Client Programs," the topic "Invoking 
  5312. Methods" describes the placement of a context parameter in a method call. See 
  5313. also Chapter 6 of The Common Object Request Broker: Architecture and 
  5314. Specification for a discussion of how clients associate values with context 
  5315. identifiers. A description of the Context class and its methods is contained in 
  5316. the SOMobjects Developer Toolkit: Programmers Reference Manual. 
  5317.  
  5318.  
  5319. ΓòÉΓòÉΓòÉ 6.2.8. Implementation statements ΓòÉΓòÉΓòÉ
  5320.  
  5321. A SOM IDL interface statement for a class may contain an implementation 
  5322. statement, which specifies information about how the class will be implemented 
  5323. (version numbers for the class, overriding of inherited methods, what 
  5324. resolution mechanisms the bindings for a particular method will support, and so 
  5325. forth). If the implementation statement is omitted, default information is 
  5326. assumed. 
  5327.  
  5328. Because the implementation statement is specific to SOM IDL (and is not part of 
  5329. the CORBA standard), the implementation statement should be preceded by an 
  5330. "#ifdef _ _SOMIDL_ _" directive and followed by an "#endif" directive. (See 
  5331. Example 3 in the SOM IDL Tutorial presented earlier.) 
  5332.  
  5333. The syntax for the implementation statement is as follows: 
  5334.  
  5335.    #ifdef __SOMIDL__
  5336.    implementation
  5337.    {
  5338.      implementation*
  5339.    };
  5340.    #endif
  5341.  
  5342. where each "implementation" can be a modifier  statement, a passthru statement, 
  5343. or a declarator of an instance variable, terminated by a semicolon. These 
  5344. constructs are described below. An interface statement may not contain multiple 
  5345. implementation statements. 
  5346. Modifier statements 
  5347.  
  5348. A modifier statement gives additional implementation information about IDL 
  5349. definitions, such as interfaces, attributes, methods, and types. Modifiers can 
  5350. be unqualified or qualified: An unqualified modifier is associated with the 
  5351. interface it is defined in. An unqualified modifier statement has the following 
  5352. two syntactic forms: 
  5353.  
  5354.   modifier
  5355.   modifier = value
  5356. where "modifier" is either a SOM Compiler-defined identifier or a user-defined 
  5357. identifier, and where "value" is an identifier, a string enclosed in double 
  5358. quotes (" "), or a number. 
  5359.  
  5360. For example: 
  5361.  
  5362.    filestem = foo;
  5363.    nodata;
  5364.    persistent;
  5365.    dllname = "E:/som/dlls";
  5366.  
  5367. A qualified modifier is associated with a qualifier.  The qualified modifier 
  5368. has the syntax: 
  5369.  
  5370.    qualifier : modifier
  5371.    qualifier : modifier = value
  5372.    #pragma modifier qualifier : modifier
  5373.    #pragma modifier qualifier : modifier = value
  5374.  
  5375. where "qualifier" is the identifier of an IDL definition or is user defined. If 
  5376. the "qualifier" is an IDL definition introduced in the current interface, 
  5377. module, or global scope, then the modifier is attached to that definition. 
  5378. Otherwise, if the qualifier is user defined, the modifier is attached to the 
  5379. interface it occurs in. If a user-defined modifier is defined outside of an 
  5380. interface body (by using #pragma modifier), then it is ignored. 
  5381.  
  5382. For example, consider the following IDL file.  (Notice that qualified modifiers 
  5383. can be defined with the "qualifier" and "modifier[=value]" in either order. 
  5384. Also observe that additional modifiers can be included by separating them with 
  5385. commas.) 
  5386.  
  5387.    #include <somobj.idl>
  5388.    #include <somcls.idl>
  5389.  
  5390.  
  5391.    typedef long newInt;
  5392.    #pragma somemittypes on
  5393.    #pragma modifier newInt : nonportable;
  5394.    #pragma somemittypes off
  5395.    module M {
  5396.        typedef long long_t;
  5397.        module  N {
  5398.            typedef short short_t;
  5399.            interface M_I : SOMClass {
  5400.                implementation {
  5401.                    somInit : override;
  5402.                };
  5403.            };
  5404.            interface I : SOMObject {
  5405.                void op ();
  5406.                #pragma modifier op : persistent;
  5407.  
  5408.  
  5409.                typedef char char_t;
  5410.                implementation {
  5411.                    releaseorder : op;
  5412.                    metaclass = M_I;
  5413.                    callstyle = oidl;
  5414.                    mymod : a, b;
  5415.                    mymod : c, d;
  5416.                    e     : mymod;
  5417.                    f     : mymod;
  5418.                    op : persistent;
  5419.                };
  5420.           };
  5421.        };
  5422.     };
  5423.  
  5424. From the preceding IDL file, we associate modifiers with the following 
  5425. definitions: 
  5426.  
  5427.    TypeDef "::newInt"             1  modifier: nonportable
  5428.    InterfaceDef "::M::N::M_I"     1  modifier: override = somInit
  5429.    InterfaceDef "::M::N::I"       9 modifiers: metaclass = M_I,
  5430.                                                releaseorder = op
  5431.                                                callstyle = oidl
  5432.                                                mymod = a,b,c,d,e,f
  5433.                                                a = mymod
  5434.                                                b = mymod
  5435.                                                c = mymod
  5436.                                                d = mymod
  5437.                                                e = mymod
  5438.                                                f = mymod
  5439.    OperationDef "::M::N::I::op"   1 modifier: persistent
  5440.  
  5441. Notice, how the modifiers for the user-defined qualifier "mymod": 
  5442.  
  5443.    mymod : a, b;
  5444.    mymod : c, d;
  5445.    e     : mymod;
  5446.    f     : mymod;
  5447.  
  5448. map onto: 
  5449.  
  5450.    mymod = a,b,c,d,e,f
  5451.    a     = mymod
  5452.    b     = mymod
  5453.    c     = mymod
  5454.    d     = mymod
  5455.    e     = mymod
  5456.    f     = mymod
  5457.  
  5458. This enables users to look up the modifiers with "mymod", either by looking for 
  5459. "mymod" or by using each individual value that uses "mymod". These user-defined 
  5460. modifiers are available for Emitter writers (see the Emitter Writer's Guide and 
  5461. Reference) and from the Interface Repository (see Chapter 7, "The Interface 
  5462. Repository Framework"). 
  5463. SOM Compiler unqualified modifiers 
  5464.  
  5465. Unqualified modifiers (described below) include the SOM Compiler-defined 
  5466. identifiers abstract, baseproxyclass, callstyle, classinit, directinitclasses, 
  5467. dllname, filestem, functionprefix, majorversion, metaclass, memory_management, 
  5468. minorversion, somallocte and somdeallocate. 
  5469.  
  5470.  abstract                 Specifies that the class is intended for use as a 
  5471.                           parent for subclass derivations, but not for creating 
  5472.                           instances. 
  5473.  
  5474.  baseproxyclass =class    Specifies the base proxy class to be used by DSOM 
  5475.                           when dynamically creating a proxy class for the 
  5476.                           current class. The base proxy class must be derived 
  5477.                           from the class SOMDClientProxy  The SOMDClientProxy 
  5478.                           class will be used if the baseproxyclass modifier is 
  5479.                           unspecified. (See chapter 6, "distributed SOM," for a 
  5480.                           discussion on customizing proxy classes.) 
  5481.  
  5482.  callstyle = oidl         Specifies that the method stub procedures generated 
  5483.                           by SOM's C/C++ bindings will not include the 
  5484.                           CORBA-specified (Environment *ev) and (context *ctx) 
  5485.                           parameters. 
  5486.  
  5487.  classinit = procedure    Specifies a user-written procedure that will be 
  5488.                           executed to initialize the class object when it is 
  5489.                           created.  If the classinit modifier is specified in 
  5490.                           the .idl file for a class, the SOM Compiler will 
  5491.                           provide a template for the procedure in the 
  5492.                           implementation file it generates. The class 
  5493.                           implementer can then fill in the body of this 
  5494.                           procedure template. 
  5495.  
  5496.  directinitclasses ="ancestor1, ancestor2, ..."  Specifies the ancestor 
  5497.                           class(es) whose initializers (and destructors) will 
  5498.                           be directly invoked by this class's initialization 
  5499.                           (and destruction) routines.  If this modifier is not 
  5500.                           explicitly specified, the default setting is the 
  5501.                           parents of the class. For further information, see 
  5502.                           "Initializing and Uninitializing Objects" in Chapter 
  5503.                           5, "Implementing Classes in SOM." 
  5504.  
  5505.  dllname = filename       Specifies the name of the library file that will 
  5506.                           contain the class's implementation. If filename 
  5507.                           contains special characters (e.g., periods, 
  5508.                           backslashes), then filename should be surrounded by 
  5509.                           double quotes (""). The filename specified can be 
  5510.                           either a full pathname, or an unqualified (or 
  5511.                           partially qualified) filename. In the latter cases, 
  5512.                           the LIBPATH environment variable is used to locate 
  5513.                           the file. 
  5514.  
  5515.  filestem  = stem         Specifies how the SOM Compiler will construct file 
  5516.                           names for the binding files it generates (<stem>.h, 
  5517.                           <stem>.c, etc.). The default stem is the file stem of 
  5518.                           the .idl file for the class. 
  5519.  
  5520.  functionprefix  = prefix Directs the SOM Compiler to construct 
  5521.                           method-procedure names by prefixing method names with 
  5522.                           "prefix". For example, "functionprefix = xx;"  within 
  5523.                           an implementation statement would result in a 
  5524.                           procedure name of xxfoo for method foo.  The default 
  5525.                           for this attribute is the empty string. If an 
  5526.                           interface is defined in a module, then the default 
  5527.                           function prefix is the fully scooped interface name. 
  5528.                           Tip:  Using a function prefix with the same name as 
  5529.                           the class makes it easier to remember 
  5530.                           method-procedure names when debugging. 
  5531.  
  5532.                           When multiple classes are specified in the same .idl 
  5533.                           file, function prefixes can be used to avoid name 
  5534.                           conflicts in the implementation file. For example, if 
  5535.                           one class introduces a method and another class in 
  5536.                           the same file overrides it, then the implementation 
  5537.                           file for the classes will contain two method 
  5538.                           procedures of the same name (unless function prefixes 
  5539.                           are defined for one of the classes), resulting in a 
  5540.                           name collision at compile time. 
  5541.  
  5542.  majorversion = number    Specifies the major version number of the current 
  5543.                           class definition. The major version number of a class 
  5544.                           definition usually changes only when a significant 
  5545.                           enhancement or incompatible change is made to the 
  5546.                           class. The "number" must be a positive integer less 
  5547.                           than 2^32 - 1.  If a non-zero major version number is 
  5548.                           specified, SOM will verify that any code that 
  5549.                           purports to implement the class has the same major 
  5550.                           version number. The default major version number is 
  5551.                           zero. 
  5552.  
  5553.  memory_management = corba  Specifies that all methods introduced by the class 
  5554.                           follow the CORBA specification for parameter memory 
  5555.                           management, except where a particular method has an 
  5556.                           explicit modifier indicating otherwise (either 
  5557.                           "object_owns_result" or "object_owns_parameters"). 
  5558.                           See the section in Chapter 6 entitled "Memory 
  5559.                           Management" for a discussion of the CORBA 
  5560.                           memory-management requirements. 
  5561.  
  5562.  metaclass = class        Specifies the class's metaclass. The specified 
  5563.                           metaclass (or one automatically derived from it at 
  5564.                           run time) will be used to create the class object for 
  5565.                           the class. If a metaclass is specified, its .idl file 
  5566.                           (if separate) must be included in the include section 
  5567.                           of the class's .idl file. If no metaclass is 
  5568.                           specified, the metaclass will be defined 
  5569.                           automatically. 
  5570.  
  5571.  minorversion = number    Specifies the minor version number of the current 
  5572.                           class definition. The minor version number of a class 
  5573.                           definition changes whenever minor enhancements or 
  5574.                           fixes are made to a class. Class implementers usually 
  5575.                           maintain backward compatibility across changes in the 
  5576.                           minor version number. The "number" must be a positive 
  5577.                           integer less than 2^32 - 1. If a non-zero minor 
  5578.                           version number is specified, SOM will verify that any 
  5579.                           code that purports to implement the class has the 
  5580.                           same or a higher minor version number. The default 
  5581.                           minor version number is zero. 
  5582.  
  5583.  somallocate=procedure    Specifies a user-written procedure that will be 
  5584.                           executed to allocate memory for class instances when 
  5585.                           the somAllocate class method is invoked. 
  5586.  
  5587.  somdeallocate=procedure  Specifies a user-written procedure that will be 
  5588.                           executed to deallocate memory for class instances 
  5589.                           when the somDeallocate class method is invoked. 
  5590.  
  5591.  The following example illustrates the specification of unqualified interface 
  5592.  modifiers: 
  5593.  
  5594.      implementation
  5595.      {
  5596.        filestem = hello;
  5597.        functionprefix = hel;
  5598.        majorversion = 1;
  5599.        minorversion = 2;
  5600.        classinit = helloInit;
  5601.        metaclass = M_Hello;
  5602.      };
  5603.  
  5604.  SOM Compiler qualified modifiers 
  5605.  
  5606.  Qualified modifiers are categorized according to the IDL component (class, 
  5607.  attribute, method, or type) to which each modifier applies. Listed below are 
  5608.  the SOM Compiler-defined identifiers used as qualified modifiers, along with 
  5609.  the IDL component to which it applies. Descriptions of all qualified modifiers 
  5610.  are then given in alphabetical order. Recall that qualified modifiers are 
  5611.  defined using the syntax qualifier: modifier[=value]. 
  5612.  
  5613.  For classes: 
  5614.       releaseorder 
  5615.  
  5616.  For attributes: 
  5617.       indirect, nodata, noget, noset 
  5618.  
  5619.  For methods: 
  5620.       caller_owns_parameters, caller_owns_result, const, init, method, migrate, 
  5621.       namelookup, nocall, noenv, nonstatic, nooverride, noself, 
  5622.       object_owns_parameters, object_owns_result, offset, override, procedure, 
  5623.       reintroduce, and select 
  5624.  
  5625.  For variables: 
  5626.       staticdata 
  5627.  
  5628.  For types: 
  5629.       impctx 
  5630.  
  5631.  caller_owns_parameters ="p1,p2,...,pn" Specifies the names of the method's 
  5632.                           parameters whose ownership is retained by (in the 
  5633.                           case of "in"parameters) or transferred to (for 
  5634.                           "inout" or "out" parameters) the caller. This 
  5635.                           modifier is only valid in the interface specification 
  5636.                           of the method's introducing class.  This modifier 
  5637.                           only makes sense for parameters whose IDL type is a 
  5638.                           data item that can be freed (string, object, array, 
  5639.                           pointer, or TypeCode), or a data item containing 
  5640.                           memory that can be freed (for example, a sequence or 
  5641.                           any), or a struct or union. 
  5642.  
  5643.                           For parameters whose type is an object, ownership 
  5644.                           applies to the object reference rather than to the 
  5645.                           object (that is, the caller should invoke release on 
  5646.                           the parameter, rather than somFree). 
  5647.  
  5648.  caller_owns_result       Specifies that ownership of the return result of  the 
  5649.                           method is transferred to the caller, and that the 
  5650.                           caller is responsible for freeing the memory. This 
  5651.                           modifier is only valid in the interface specification 
  5652.                           of the method's introducing class. This modifier only 
  5653.                           makes sense when the method's return type is a data 
  5654.                           type that can be freed (string, object, array, 
  5655.                           pointer, or TypeCode), or a data item containing 
  5656.                           memory that can be freed (for example, a sequence or 
  5657.                           any). For methods that return an object, ownership 
  5658.                           applies to the object reference rather than to the 
  5659.                           object (that is, the caller should invoke release on 
  5660.                           the result, rather than somFree). 
  5661.  
  5662.  const                    Indicates that implementations of the related method 
  5663.                           should not modify their target argument. SOM provides 
  5664.                           no way to verify or guarantee that implementations do 
  5665.                           not modify the targets of such methods, and the 
  5666.                           information provided by this modifier is not 
  5667.                           currently of importance to any of the Toolkit 
  5668.                           emitters. However, the information may prove useful 
  5669.                           in the future. For example, since modifiers are 
  5670.                           available in the Interface Repository, there may be 
  5671.                           future uses of this information by DSOM. 
  5672.  
  5673.  impctx                   Supports types that cannot be fully defined using 
  5674.                           IDL. For full information, see "Using the tk_foreign 
  5675.                           TypeCode" in Chapter 7, "The Interface Repository 
  5676.                           Framework." 
  5677.  
  5678.  indirect                 Directs the SOM Compiler to generate "get" and "set" 
  5679.                           methods for the attribute that take and return a 
  5680.                           pointer to the attribute's value, rather than the 
  5681.                           attribute value itself. For example, if an attribute 
  5682.                           x of type float is declared to be an indirect 
  5683.                           attribute, then the "_get_x" method will return a 
  5684.                           pointer to a float, and the input to the "_set_x" 
  5685.                           method must be a pointer to a float. (This modifier 
  5686.                           is provided for OIDL compatibility only.) 
  5687.  
  5688.  init                     Indicates that a method is an initializer method. 
  5689.                           For information concerning the use of this modifier, 
  5690.                           see "Initializing and Uninitializing Objects: in 
  5691.                           Chapter 5, "Implementing Classes in SOM" 
  5692.  
  5693.  method or nonstatic or  procedure  Indicates the category of method 
  5694.                           implementation. Refer to the topic "The four kinds of 
  5695.                           SOM methods" in Chapter 5, "Implementing Classes in 
  5696.                           SOM," for an explanation of the meanings of these 
  5697.                           different method modifiers.  If none of these 
  5698.                           modifiers is specified, the default is method. 
  5699.                           Methods with the procedure modifier cannot be invoked 
  5700.                           remotely using DSOM. 
  5701.  
  5702.  migrate  = ancestor      Indicates that a method originally introduced by this 
  5703.                           interface has been moved upward to a specified 
  5704.                           <ancestor> interface. When this is done, the method 
  5705.                           introduction must be removed from this interface 
  5706.                           (because the method is now inherited). However, the 
  5707.                           original  releaseorder entry for the method should be 
  5708.                           retained, and migrate should be used to assure that 
  5709.                           clients compiled based on the original interface will 
  5710.                           not require recompilation. The ancestor interface is 
  5711.                           specified using a C-scoped interface name. For 
  5712.                           example, "Module_InterfaceName", not 
  5713.                           "Module::InterfaceName". See the later topic "Name 
  5714.                           usage in client programs" for an explanation of 
  5715.                           C-scoped names. 
  5716.  
  5717.  namelookup               See "offset or namelookup." 
  5718.  
  5719.  nocall                   Specifies that the related method should not be 
  5720.                           invoked on an instance of this class even though it 
  5721.                           is supported by the interface. 
  5722.  
  5723.  nodata                   Directs the SOM Compiler not to define an instance 
  5724.                           variable corresponding to the attribute. For example, 
  5725.                           a "time" attribute would not require an instance 
  5726.                           variable to maintain its value, because the value can 
  5727.                           be obtained from the operating system.  The "get" and 
  5728.                           "set" methods for "nodata" attributes must be defined 
  5729.                           by the class implementer; stub method procedures for 
  5730.                           them are automatically generated in the 
  5731.                           implementation template for the class by the SOM 
  5732.                           Compiler. 
  5733.  
  5734.  noenv                    Indicates that a direct-call procedure does not 
  5735.                           receive an environment as an argument. 
  5736.  
  5737.  noget                    Directs the SOM Compiler not to automatically 
  5738.                           generate a "get" method procedure for the attribute 
  5739.                           in the .ih/.xih binding file for the class. Instead, 
  5740.                           the "get" method must be implemented by the class 
  5741.                           implementer. A stub method procedure for the "get" 
  5742.                           method is automatically generated in the 
  5743.                           implementation template for the class by the SOM 
  5744.                           Compiler, to be filled in by the implementer. 
  5745.  
  5746.  nonstatic                See "method or nonstatic or procedure." 
  5747.  
  5748.  nooverride               Indicates that the method should not be overridden by 
  5749.                           subclasses. The SOM Compiler will generate an error 
  5750.                           if this method is overridden. 
  5751.  
  5752.  noself                   Indicates that a direct-call procedure does not 
  5753.                           receive a target object as an argument. 
  5754.  
  5755.  noset                    Directs the SOM Compiler not  to automatically 
  5756.                           generate a "set" method procedure for the attribute 
  5757.                           in the .ih/.xih binding file for the class. Instead, 
  5758.                           the "set" method must be implemented by the class 
  5759.                           implementer. A stub method procedure for the "set" 
  5760.                           method is automatically generated in the 
  5761.                           implementation template for the class by the SOM 
  5762.                           Compiler. 
  5763.  
  5764.                           Note: The "set" method procedure that the SOM 
  5765.                           Compiler generates by default for an attribute in the 
  5766.                           .h/.xh binding file (when the noset modifier is not 
  5767.                           used) does a shallow copy of the value that is passed 
  5768.                           to the attribute. For some attribute types, including 
  5769.                           strings and pointers, this may not be appropriate. 
  5770.                           For instance, the "set" method for an attribute of 
  5771.                           type string should perform a string copy, rather than 
  5772.                           a shallow copy, if the attribute's value may be 
  5773.                           needed after the client program has freed the memory 
  5774.                           occupied by the string. In such situations, the class 
  5775.                           implementer should specify the noset attribute 
  5776.                           modifier and implement the attribute's "set" method 
  5777.                           manually, rather than having SOM implement the "set" 
  5778.                           method automatically. 
  5779.  
  5780.  object_owns_parameters  ="p1, p2, ..., pn" Specifies the names of the method's 
  5781.                           parameters whose ownership is transferred to (in the 
  5782.                           case of "in" parameters) or is retained by (for 
  5783.                           "inout" or "out" parameters) the object.  For "in" 
  5784.                           parameters, the object can free the parameter at any 
  5785.                           time after receiving it. (Hence, the caller should 
  5786.                           not reuse the parameter or pass it as any other 
  5787.                           object-owned parameter in the same method call.) For 
  5788.                           "inout" and "out" parameters, the object is 
  5789.                           responsible for freeing the parameter sometime before 
  5790.                           the object is destroyed. This modifier is only valid 
  5791.                           in the interface specification of the method's 
  5792.                           introducing class. This modifier only makes sense for 
  5793.                           parameters whose IDL type is a data item that can be 
  5794.                           freed (string, object, array, pointer, or TypeCode), 
  5795.                           or a data item containing memory that can be freed 
  5796.                           (for example, a sequence or any), or a struct or 
  5797.                           union. 
  5798.  
  5799.                           For parameters whose type is an object, ownership 
  5800.                           applies to the object reference  rather than to the 
  5801.                           object (that is, the object will invoke release on 
  5802.                           the parameter, rather than somFree). For "in" and 
  5803.                           "out" parameters whose IDL-to-C/C++ mapping 
  5804.                           introduces a pointer, ownership applies only to the 
  5805.                           data item itself, and not to the introduced pointer. 
  5806.                           (For example, even if an "out string" IDL parameter 
  5807.                           (which becomes a "string *" C/C++ parameter) is 
  5808.                           designated, as "object-owned," the object assumes 
  5809.                           ownership of the string, but not of the pointer to 
  5810.                           the string.) 
  5811.  
  5812.  object_owns_result       Specifies that the object retains ownership of the 
  5813.                           return result of the method, and that the caller must 
  5814.                           not free the memory. The object is responsible for 
  5815.                           freeing the memory sometime before the object is 
  5816.                           destroyed. This modifier is only valid in the 
  5817.                           interface specification of the method's introducing 
  5818.                           class. This modifier only makes sense when the 
  5819.                           method's return type is a data type that can be freed 
  5820.                           (string, object, array, pointer, or TypeCode), or a 
  5821.                           data item containing memory that can be freed (for 
  5822.                           example, a sequence or any). For methods that return 
  5823.                           an object, ownership applies to the object reference 
  5824.                           rather than to the object (that is, the object will 
  5825.                           be responsible for invoking release on the result, 
  5826.                           rather than somFree). 
  5827.  
  5828.  offset or namelookup     Indicates whether the SOM Compiler should generate 
  5829.                           bindings for invoking the method using offset 
  5830.                           resolution or name lookup. Offset resolution requires 
  5831.                           that the class of the method's target object be known 
  5832.                           at compile time. When different methods of the same 
  5833.                           name are defined by several classes, namelookup is a 
  5834.                           more appropriate technique for method resolution than 
  5835.                           is offset resolution. (See Chapter 3, the section 
  5836.                           entitled "Invoking Methods.")  The default modifier 
  5837.                           is offset. 
  5838.  
  5839.  override                 Indicates that the method is one introduced by an 
  5840.                           ancestor class and that this class will re-implement 
  5841.                           the method. See also the related modifier, select. 
  5842.  
  5843.  procedure                See "method or nonstatic or procedure." 
  5844.  
  5845.  reintroduce              Indicates that this interface will "hide" a method 
  5846.                           introduced by some ancestor interface, and will 
  5847.                           replace it with another implementation. Methods 
  5848.                           introduced as direct-call procedures or nonstatic 
  5849.                           methods can be reintroduced. However, static methods 
  5850.                           (the default implementation category for SOM met 
  5851.                           hods) cannot be reintroduced. 
  5852.  
  5853.  releaseorder: a, b, c, ... Specifies the order in which the SOM Compiler will 
  5854.                           place the class's methods in the data structures it 
  5855.                           builds to represent the class. Maintaining a 
  5856.                           consistent release order for a class allows the 
  5857.                           implementation of a class to change without requiring 
  5858.                           client programs to be recompiled. 
  5859.  
  5860.                           The release order should contain every method name 
  5861.                           introduced by the class (private and nonprivate), but 
  5862.                           should not include any inherited methods, even if 
  5863.                           they are overridden by the class. The "get" and "set" 
  5864.                           methods defined automatically for each new attribute 
  5865.                           (named "_get_<attributeName>" and 
  5866.                           "_set_<attributeName>") should also be included in 
  5867.                           the release order list. The order of the names on the 
  5868.                           list is unimportant except that once a name is on the 
  5869.                           list and the class has client programs, it should not 
  5870.                           be reordered or removed, even if the method is no 
  5871.                           longer supported by the class, or the client programs 
  5872.                           will require recompilation. New methods should be 
  5873.                           added only to the end of the list. If a method named 
  5874.                           on the list is to be moved up in the class hierarchy, 
  5875.                           its name should remain on the current list, but it 
  5876.                           should also be added to the release order list for 
  5877.                           the class that will now introduce it. 
  5878.  
  5879.                           If not explicitly specified, the release order will 
  5880.                           be determined by the SOM Compiler, and a warning will 
  5881.                           be issued for each missing method. If new methods or 
  5882.                           attributes are subsequently added to the class, the 
  5883.                           default release order might change; programs using 
  5884.                           the class would then require recompilation. Thus, it 
  5885.                           is advisable to explicitly give a release order. 
  5886.  
  5887.  select = parent          Used in conjunction with the override modifier, this, 
  5888.                           indicates that an inherited static method will use 
  5889.                           the implementation inherited from the indicated 
  5890.                           <parent> class. The parent is specified using the 
  5891.                           C-scoped name. For example, "Module_InterfaceName", 
  5892.                           not "Module:: InterfaceName". See the later topic 
  5893.                           "Name usage in client programs" for an explanation of 
  5894.                           C-scoped names. 
  5895.  
  5896.  staticdata               Indicates that the declared variable is not stored 
  5897.                           within objects, but, instead, that the ClassData 
  5898.                           structure for the implementing class will contain a 
  5899.                           pointer to the staticdata variable. This is similar 
  5900.                           in concept to C++ static data members. The staticdata 
  5901.                           variable must also be included in the releaseorder. 
  5902.                           The class implementer has responsibility for loading 
  5903.                           the ClassData pointer during class initialization. 
  5904.                           This can be facilitated by writing a special class 
  5905.                           initialization function and indicating its name using 
  5906.                           the classinit unqualified modifier. 
  5907.  
  5908.                           Note:  Attributes can be declared as staticdata. This 
  5909.                                  is an important implementation technique that 
  5910.                                  allows classes to introduce attributes whose 
  5911.                                  backing storage is not inherited by 
  5912.                                  subclasses. 
  5913.  
  5914.  
  5915.  The following example illustrates the specification of qualified modifiers: 
  5916.  
  5917.   implementation
  5918.   {
  5919.     releaseorder : op1, op3, op2, op5, op6, x, y;
  5920.     op1 : persistent;
  5921.     somDefaultInit : override, init;
  5922.     op2: reintroduce, procedure;
  5923.     op3: reintroduce, nonstatic;
  5924.     op4: override, select = ModuleName_parentInterfaceName;
  5925.     op5: migrate = ModuleName_ancestorInterfaceName;
  5926.     op6: procedure, noself, noenv;
  5927.     long x;
  5928.     x: staticdata;
  5929.     y: staticdata; // y is an attribute
  5930.     mymod : a, b;
  5931.   };
  5932.  
  5933.  
  5934.  Passthru statements 
  5935.  
  5936.  A passthru statement (used within the body of an implementation statement, 
  5937.  described above) allows a class implementer to specify blocks of code (for 
  5938.  C/C++ programmers, usually only #include directives) that the SOM compiler 
  5939.  will pass into the header files it generates. 
  5940.  
  5941.  Passthru statements are included in SOM IDL primarily for backward 
  5942.  compatibility with the SOM OIDL language, and their use by C and C++ 
  5943.  programmers should be limited to #include directives. C and C++ programmers 
  5944.  should use IDL type and constant declarations rather than passthru statements 
  5945.  when possible. (Users of other languages, however, may require passthru 
  5946.  statements for type and constant declarations.) 
  5947.  
  5948.  The contents of the passthru lines are ignored by the SOM compiler and can 
  5949.  contain anything that needs to placed near the beginning of a header file for 
  5950.  a class. Even comments contained in passthru lines are processed without 
  5951.  modification. The syntax for specifying passthru lines is one of the following 
  5952.  forms: 
  5953.  
  5954.  passthru language_suffix      = literal+ ; 
  5955.  passthru language_suffix_before = literal+ ; 
  5956.  passthru language_suffix_after = literal+ ; 
  5957.  
  5958.  where "language" specifies the programming language and "suffix" indicates 
  5959.  which header files will be affected. The SOM Compiler supports suffixes h, ih, 
  5960.  xh, and xih. For both C and C++, "language" is specified as C. 
  5961.  
  5962.  Each "literal" is a string literal (enclosed in double quotes) to be placed 
  5963.  verbatim into the specified header file.  [Double quotes within the passthru 
  5964.  literal should be preceded by a backslash. No other characters escaped with a 
  5965.  backslash will be interpreted, and formatting characters (newlines, tab 
  5966.  characters, etc.) are passed through without processing.]  The last literal 
  5967.  for a passthru statement must not end in a backslash (put a space or other 
  5968.  character between a final backslash and the closing double quote). 
  5969.  
  5970.  When either of the first two forms is used, passthru  lines are placed before 
  5971.  the #include statements in the header file. When the third form is used, 
  5972.  passthru lines are placed just after the #include statements in the header 
  5973.  file. 
  5974.  
  5975.  For example, the following passthru statement 
  5976.  
  5977.      implementation
  5978.      {
  5979.        passthru C_h = "#include <foo.h>";
  5980.      };
  5981.  
  5982.  results in the directive #include <foo.h> being placed at the beginning of the 
  5983.  .h C binding file that the SOM Compiler generates. 
  5984.  Declaring instance variables and staticdata variables 
  5985.  
  5986.  Declarators are used within the body of an implementation statement (described 
  5987.  above) to specify the instance variables that are introduced by a class, and 
  5988.  the staticdata variables pointed to by the class's ClassData structure. These 
  5989.  variables are declared using ANSI C syntax for variable declarations, 
  5990.  restricted to valid SOM IDL types (see "Type and constant declarations," 
  5991.  above). For example, the following implementation statement declares two 
  5992.  instance variables, x and y, and a staticdata variable, z, for class "Hello," 
  5993.  : 
  5994.  
  5995.   implementation
  5996.   {
  5997.     short x;
  5998.     long y;
  5999.     double z;
  6000.     z: staticdata;
  6001.   };
  6002.  
  6003.  Instance variables are normally intended to be accessed only by the class's 
  6004.  methods and not by client programs or subclasses' methods. For data to be 
  6005.  accessed by client programs or subclass methods, attributes should be used 
  6006.  instead of instance variables. (Note, however, that declaring an attribute has 
  6007.  the effect of also declaring an instance variable of the same name, unless the 
  6008.  "nodata" attribute modifier is specified.) 
  6009.  
  6010.  Staticdata variables, by contrast, are publicly available and are associated 
  6011.  specifically with their introducing class. They are, however, very different 
  6012.  in concept from class variables. Class variables are really instance variables 
  6013.  introduced by a metaclass, and are therefore present in any class that is an 
  6014.  instance of the introducing metaclass (or of any metaclass derived from this 
  6015.  metaclass). As a result, class variables present in any given class will also 
  6016.  be present in any class derived from this class (that is, class variables are 
  6017.  inherited). In contrast, staticdata variables are introduced by a class (not a 
  6018.  metaclass) and are (only) accessed from the class's ClassData structure -- 
  6019.  they are not inherited. 
  6020.  
  6021.  To declare an instance variable that is not  a valid IDL type, a dummy typedef 
  6022.  can be declared before the interface declaration and a passthru statement then 
  6023.  used to pass the real typedef to  the language-specific binding file(s). See 
  6024.  also the section "Using the tk_foreign TypeCode" in Chapter 7, "The Interface 
  6025.  Repository Framework." In the following example, the generic SOM type somToken 
  6026.  is used in the IDL file for the user's type "myRealType". The passthru 
  6027.  statement then causes an appropriate #include statement to be emitted into the 
  6028.  C/C++ binding file, so that the file defining type "MyRealType" will be 
  6029.  included when the binding file processes: 
  6030.  
  6031.   typedef somToken myRealType;
  6032.  
  6033.   interface myClass : SOMObject {
  6034.   . . .
  6035.     implementation {
  6036.        myRealType myInstVar;
  6037.        passthru C_h = "#include <myTypes.h>";
  6038.     };
  6039.   };
  6040.  
  6041.  
  6042. ΓòÉΓòÉΓòÉ 6.2.9. Comments within a SOM IDL file ΓòÉΓòÉΓòÉ
  6043.  
  6044. SOM IDL supports both C and C++ comment styles. The characters "//" start a 
  6045. line comment, which finishes at the end of the current line. The characters 
  6046. "/*" start a block comment that finishes with the "*/". Block comments do not 
  6047. nest. The two comment styles can be used interchangeably. 
  6048.  
  6049. Comments in a SOM IDL specification must be strictly associated with particular 
  6050. syntactic elements, so that the SOM Compiler can put them at the appropriate 
  6051. place in the header and implementation files it generates. Therefore, comments 
  6052. may appear only in these locations (in general, following the syntactic unit 
  6053. being commented): 
  6054.  
  6055.    o  At the beginning of the IDL specification 
  6056.  
  6057.    o  After a semicolon 
  6058.  
  6059.    o  Before or after the opening brace of a module, interface statement, 
  6060.       implementation statement, structure definition, or union definition 
  6061.  
  6062.    o  After a comma that separates parameter declarations or enumeration 
  6063.       members 
  6064.  
  6065.    o  After the last parameter in a prototype (before the closing parenthesis) 
  6066.  
  6067.    o  After the last enumeration name in an enumeration definition (before the 
  6068.       closing brace) 
  6069.  
  6070.    o  After the colon following a case label of a union definition 
  6071.  
  6072.    o  After the closing brace of an interface statement 
  6073.  
  6074.  Numerous examples of the use of comments can be found in the Tutorial of 
  6075.  Chapter 2. 
  6076.  
  6077.  Because comments appearing in a SOM IDL specification are transferred to the 
  6078.  files that the SOM Compiler generates, and because these files are often used 
  6079.  as input to a programming language compiler, it is best within the body of 
  6080.  comments to avoid using characters that are not generally allowed in comments 
  6081.  of most programming languages. For example, the C language does not allow "*/" 
  6082.  to occur within a comment, so its use is to be avoided, even when using C++ 
  6083.  style comments in the .idl file. 
  6084.  
  6085.  SOM IDL also supports throw-away comments. They may appear anywhere in an IDL 
  6086.  specification, because they are ignored by the SOM Compiler and are not 
  6087.  transferred to any file it generates. Throw-away comments start with the 
  6088.  string "//#" and end at the end of the line. Throw-away comments can be used 
  6089.  to "comment out" portions of an IDL specification. 
  6090.  
  6091.  To disable comment processing (that is, to prevent the SOM Compiler from 
  6092.  transferring comments from the IDL specification to the binding files it 
  6093.  generates), use the -c option of the sc or somc command when running the SOM 
  6094.  Compiler (See Section 4.3, "The SOM Compiler").  When comment processing is 
  6095.  disabled, comment placement is not restricted and comments can appear anywhere 
  6096.  in the IDL specification. 
  6097.  
  6098.  
  6099. ΓòÉΓòÉΓòÉ 6.2.10. Designating `private' methods and attributes ΓòÉΓòÉΓòÉ
  6100.  
  6101. To designate methods or attributes within an IDL specification as "private," 
  6102. the declaration of the method or attribute must be surrounded with the 
  6103. preprocessor commands #ifdef__PRIVATE__ (with two leading underscores and two 
  6104. following underscores) and #endif. For example, to declare a method "foo" as a 
  6105. private method, the following declaration would appear within the interface 
  6106. statement: 
  6107.  
  6108.    #ifdef __PRIVATE__
  6109.    void foo();
  6110.    #endif
  6111.  
  6112. Any number of methods and attributes can be designated as private, either 
  6113. within a single #ifdef or in separate ones. [Kernighan-Ritchie reference for 
  6114. the C preprocessor: pages 88-92.] 
  6115.  
  6116. When compiling a .idl file, the SOM Compiler normally recognizes only public 
  6117. (nonprivate) methods and attributes, as that is generally all that is needed. 
  6118. To generate header files for client programs that do need to access private 
  6119. methods and attributes, the -p option should be included when running the SOM 
  6120. Compiler. The resulting .h or .xh header file will then include bindings for 
  6121. private, as well as public, methods and attributes. The -p option is described 
  6122. in the topic "Running the SOM Compiler" later in this chapter. 
  6123.  
  6124. The SOMobjects Toolkit also provides a pdl (Public Definition Language) emitter 
  6125. that can be used with the SOM Compiler to generate a copy of a .idl file which 
  6126. has the portions designated as private removed. The next main section of this 
  6127. chapter describes how to invoke the SOM Compiler and the various emitters. 
  6128.  
  6129.  
  6130. ΓòÉΓòÉΓòÉ 6.2.11. Defining multiple interfaces in a .idl file ΓòÉΓòÉΓòÉ
  6131.  
  6132. A single .idl file can define multiple interfaces. This allows, for example, a 
  6133. class and its metaclass to be defined in the same file. When a file defines two 
  6134. (or more) interfaces that reference one another, forward declarations can be 
  6135. used to declare the name of an interface before it is defined. This is done as 
  6136. follows: 
  6137.  
  6138. interface class-name ; 
  6139.  
  6140. The actual definition of the interface for "class-name" must appear later in 
  6141. the same .idl file. 
  6142.  
  6143. If multiple interfaces are defined in the same .idl file, and the classes are 
  6144. not a class-metaclass pair, they can be grouped into modules, by using the 
  6145. following syntax: 
  6146.  
  6147. module module-name { definition+ }; 
  6148.  
  6149. where each "definition" is a type declaration, constant declaration, exception 
  6150. declaration, interface statement, or nested module statement. Modules are used 
  6151. to scope identifiers (see below). 
  6152.  
  6153. Alternatively, multiple interfaces can be defined in a single .idl file without 
  6154. using a module to group the interfaces. Whether or not a module is used for 
  6155. grouping multiple interfaces, the languages bindings produced from the .idl 
  6156. file will include support for all of the defined interfaces. 
  6157.  
  6158. Note:  When multiple interfaces are defined in a single .idl file and a module 
  6159.        statement is not used for grouping these interfaces, it is necessary to 
  6160.        use the functionprefix modifier to assure that different names exist for 
  6161.        functions that provide different implementations for a method.  In 
  6162.        general, it is a good idea to always use the functionprefix modifier, 
  6163.        but in this case it is essential. 
  6164.  
  6165.  
  6166. ΓòÉΓòÉΓòÉ 6.2.12. Scooping and name resolution ΓòÉΓòÉΓòÉ
  6167.  
  6168. A .idl file forms a naming scope (or scope). Modules, interface statements, 
  6169. structures, unions, methods, and exceptions form nested scopes. An identifier 
  6170. can only be defined once in a particular scope. Identifiers can be redefined in 
  6171. nested scopes. 
  6172.  
  6173. Names can be used in an unqualified form within a scope, and the name will be 
  6174. resolved by successively searching the enclosing scopes. Once an unqualified 
  6175. name is defined in an enclosing scope, that name cannot be redefined. 
  6176.  
  6177. Fully qualified names are of the form: 
  6178.  
  6179. scoped-name::identifier 
  6180.  
  6181. For example, method name "meth" defined within interface "Test" of module "M1" 
  6182. would have the fully qualified name: 
  6183.  
  6184.   M1::Test::meth
  6185.  
  6186. A qualified name is resolved by first resolving the "scoped-name" to a 
  6187. particular scope S, then locating the definition of "identifier" within that 
  6188. scope. Enclosing scopes of S are not searched. 
  6189.  
  6190. Qualified names of the form: 
  6191.  
  6192. ::identifier 
  6193.  
  6194. These names are resolved by locating the definition of "identifier" within the 
  6195. smallest enclosing module. 
  6196.  
  6197. Every name defined in an IDL specification is given a global name, constructed 
  6198. as follows: 
  6199.  
  6200.    o  Before the SOM Compiler scans a .idl file, the name of the current root 
  6201.       and the name of the current scope are empty. As each module is 
  6202.       encountered, the string "::" and the module name are appended to the name 
  6203.       of the current root. At the end of the module, they are removed. 
  6204.  
  6205.    o  As each interface, struct, union, or exception definition is encountered, 
  6206.       the string "::" and the associated name are appended to the name of the 
  6207.       current scope. At the end of the definition, they are removed. While 
  6208.       parameters of a method declaration are processed, a new unnamed scope is 
  6209.       entered so that parameter names can duplicate other identifiers. 
  6210.  
  6211.    o  The global name of an IDL definition is then the concatenation of the 
  6212.       current root, the current scope, a "::", and the local name for the 
  6213.       definition. 
  6214.  
  6215.  The names of types, constants, and exceptions defined by the parents of a 
  6216.  class are accessible in the child class. References to these names must be 
  6217.  unambiguous. Ambiguities can be resolved  by using a scoped name (prefacing 
  6218.  the name with the name of the class that defines it and the characters "::", 
  6219.  as in "parent-class::identifier). Scope names can also be used to refer to a 
  6220.  constant, type, or exception name defined by a parent class but redefined by 
  6221.  the child class. 
  6222.  Name usage in client programs 
  6223.  
  6224.  Within a C or C++ program, the global name for a type, constant, or exception 
  6225.  corresponding to an IDL scoped name is derived by converting the string "::" 
  6226.  to an underscore ("_") and removing the leading underscore. Such names are 
  6227.  referred to as C-scoped names. This means that types, constants, and 
  6228.  exceptions defined within the interface statement for a class can be 
  6229.  referenced in a C/C++ program by prepending the class name to the name of the 
  6230.  type, constant, or exception. For example, consider the types defined in the 
  6231.  following IDL specification: 
  6232.  
  6233.      typedef sequence<long,10> mySeq;
  6234.      interface myClass : SOMObject
  6235.      {
  6236.         enum color {red, white, blue};
  6237.         typedef string<100> longString;
  6238.         ...
  6239.      }
  6240.  
  6241.  These types could be accessed within a C or C++ program with the following 
  6242.  global names: 
  6243.  
  6244.   mySeq,
  6245.   myClass_color,
  6246.   myClass_red,
  6247.   myClass_white,
  6248.   myClass_blue, and
  6249.   myClass_longString.
  6250.  
  6251.  Type, constant, and exception names defined within modules similarly have the 
  6252.  module name prepended. When using SOM's C/C++ bindings, the short form of 
  6253.  type, constant, and exception names (such as, color, longString) can also be 
  6254.  used where unambiguous, except that enumeration names must be referred to 
  6255.  using the long form (for example, myClass_red and not simply red). 
  6256.  
  6257.  Because replacing "::" with an underscore to create global names can lead to 
  6258.  ambiguity if an IDL identifier contains underscores, it is best to avoid the 
  6259.  use of underscores when defining IDL identifiers. 
  6260.  
  6261.  
  6262. ΓòÉΓòÉΓòÉ 6.2.13. Extensions to CORBA IDL permitted by SOM IDL ΓòÉΓòÉΓòÉ
  6263.  
  6264. The following topics describe several SOM-unique extensions of the standard 
  6265. CORBA syntax that are permitted by SOM IDL for convenience. These constructs 
  6266. can be used in a .idl file without generating a SOM Compiler error. 
  6267.  
  6268. If you want to verify that an IDL file contains only standard CORBA 
  6269. specifications, the SOM Compiler option -mcorba turns off each of these 
  6270. extensions and produces compiler errors wherever non-CORBA specifications are 
  6271. used. (The SOM Compiler command and options are described in the topic "Running 
  6272. the SOM Compiler" later in this chapter.) 
  6273. Pointer `*' types 
  6274.  
  6275. In addition to the base CORBA types, SOM IDL permits the use of pointer types 
  6276. (`*'). As well as increasing the range of base types available to the SOM IDL 
  6277. programmer, using pointer types also permits the construction of more complex 
  6278. data types, including self-referential and mutually recursive structures and 
  6279. unions. 
  6280.  
  6281. If self-referential structures and unions are required, then, instead of using 
  6282. the CORBA approach for IDL sequences, such as the following: 
  6283.  
  6284.    struct X {
  6285.        ...
  6286.        sequence <X> self;
  6287.        ...
  6288.    };
  6289.  
  6290. it is possible to use the more typical C/C++ approach. For example: 
  6291.  
  6292.    struct X {
  6293.        ...
  6294.        X *self;
  6295.        ...
  6296.    };
  6297.  
  6298. SOM IDL does not permit an explicit `*' in sequence declarations. If a sequence 
  6299. is required for a pointer type, then it is necessary to typedef the pointer 
  6300. type before use.  For example: 
  6301.  
  6302.    sequence <long *> long_star_seq;        // error.
  6303.  
  6304.    typedef long * long_star;
  6305.    sequence <long_star> long_star_seq;      // OK.
  6306.  
  6307. Unsigned types 
  6308.  
  6309. SOM IDL permits the syntax "unsigned <type>", where <type> is a previously 
  6310. declared type mapping onto "short" or "long".  (Note that CORBA permits only 
  6311. "unsigned short" and "unsigned long".) 
  6312. Implementation section 
  6313.  
  6314. SOM IDL permits an implementation section in an IDL interface specification to 
  6315. allow the addition of instance variables, method overrides, metaclass 
  6316. information, passthru information, and "pragma-like" information, called 
  6317. modifiers, for the emitters. See the topic "Implementation statements" earlier 
  6318. in this chapter. 
  6319. Comment processing 
  6320.  
  6321. The SOM IDL Compiler by default does not remove comments in the input source; 
  6322. instead, it attaches them to the nearest preceding IDL statement. This facility 
  6323. is useful, since it allows comments to be emitted in header files, C template 
  6324. files, documentation files, and so forth. However, if this capability is 
  6325. desired, this does mean that comments cannot be placed with quite as much 
  6326. freedom as with an ordinary IDL compiler. To turn off comment processing so 
  6327. that you can compile .idl files containing comments placed anywhere, you can 
  6328. use the compiler option -c or use "throw-away" comments throughout the .idl 
  6329. file (that is, comments preceded by //#); as a result, no comments will be 
  6330. included in the output files. 
  6331. Generated header files 
  6332.  
  6333. CORBA expects one header file, <file>.h, to be generated from <file>.idl. 
  6334. However, SOM IDL permits use of a class modifier, filestem, that changes this 
  6335. default output file name.  (See "Running the SOM Compiler" later in this 
  6336. chapter.) 
  6337.  
  6338.  
  6339. ΓòÉΓòÉΓòÉ 6.3. The SOM Compiler ΓòÉΓòÉΓòÉ
  6340.  
  6341. The SOM Compiler translates the IDL definition of a SOM class into a set of 
  6342. "binding files" appropriate for the language that will implement the class's 
  6343. methods and the language(s) that will use the class. These bindings make it 
  6344. more convenient for programmers to implement and use SOM classes. The SOM 
  6345. Compiler currently produces binding files for the C and C++ languages. 
  6346.  
  6347. Important Note: C and C++ bindings can not both be generated during the same 
  6348. execution of the SOM compiler. 
  6349.  
  6350.  
  6351. ΓòÉΓòÉΓòÉ 6.3.1. Generating binding files ΓòÉΓòÉΓòÉ
  6352.  
  6353. The SOM Compiler operates in two phases: 
  6354.  
  6355.    o  A precompile phase, in which a precompiler analyzes an OIDL or IDL class 
  6356.       definition, and 
  6357.  
  6358.    o  An emission phase, in which one or more  emitter programs produce 
  6359.       binding files. 
  6360.  
  6361.  Each binding file is generated by a separate emitter program. Setting the 
  6362.  SMEMIT environment variable determines which emitters will be used, as 
  6363.  described below. Note: In the discussion below, the <filesystem> is determined 
  6364.  by default from the name of the source .idl file with the ".idl" extension 
  6365.  removed. Otherwise, a "filestem" modifier can be defined in the .idl file to 
  6366.  specify another file name (see "Modifier statements" above). 
  6367.  
  6368.  Note: If changes to definitions in the .idl file later become necessary, the 
  6369.  SOM Compiler should be rerun to update the current implementation template 
  6370.  file, provided that the c or xc emitter is specified (either with the -s 
  6371.  option or the SMEMIT environment variable, as described below). For more 
  6372.  information on generating updates, see "Running incremental updates of the 
  6373.  implementation template file" later in this chapter. 
  6374.  
  6375.  The emitters for the C language produce the following binding files: 
  6376.  
  6377.  <filestem>.c             (produced by the c emitter) 
  6378.  
  6379.                           This is a template for a C source program that 
  6380.                           implements a class's methods. This will become the 
  6381.                           primary source file for the class. (The other binding 
  6382.                           files can be generated from the .idl file as needed.) 
  6383.                           This template implementation file contains "stub" 
  6384.                           procedures for each method introduced or overridden 
  6385.                           by the class. (The stub procedures are empty of code 
  6386.                           except for required initialization and debugging 
  6387.                           statements.) 
  6388.  
  6389.                           After the class implementer has supplied the code for 
  6390.                           the method procedures, running the c emitter again 
  6391.                           will update the implementation file to reflect 
  6392.                           changes made to the class definition (in the .idl 
  6393.                           file). These updates include adding new stub 
  6394.                           procedures, adding comments, and changing method 
  6395.                           prototypes to reflect changes made to the method 
  6396.                           definitions in the IDL specification. Existing code 
  6397.                           within method procedures is not disturbed, however. 
  6398.  
  6399.                           The .c file contains an #include directive for the 
  6400.                           .ih file, described below. 
  6401.  
  6402.                           The contents of the C source template is controlled 
  6403.                           by the Emitter Framework file 
  6404.                           <SOMBASE>/include/ctm.efw. This file can be 
  6405.                           customized to change the template produced. For 
  6406.                           detailed information on changing the template file 
  6407.                           see the Emitter Framework Guide and Reference. 
  6408.  
  6409.  <filestem>.h             (produced by the h emitter) 
  6410.  
  6411.                           This is the header file to be included by C client 
  6412.                           programs (programs that use the class). It contains 
  6413.                           the C usage bindings for the class, including macros 
  6414.                           for accessing the class's methods and a macro for 
  6415.                           creating new instances of the class. This header file 
  6416.                           includes the header files for the class's parent 
  6417.                           classes and its metaclass, as well as the header file 
  6418.                           that defines SOM's generic C bindings, som.h. 
  6419.  
  6420.  <filestem>.ih            (produced by the ih emitter) 
  6421.  
  6422.                           This is the header file to be included in the 
  6423.                           implementation file (the file that implements the 
  6424.                           class's methods--the .c file). It contains the 
  6425.                           implementation bindings for the class, including: 
  6426.  
  6427.    o  a struct defining the class's instance variables, 
  6428.    o  macros for accessing instance variables, 
  6429.    o  macros for invoking parent methods the class overrides, 
  6430.    o  the <className>GetData  macro used by the method procedures in the 
  6431.       <filestem>.c file (see "Stub procedures for methods" in Section 5.4 of 
  6432.       Chapter 5.) 
  6433.    o  a <className>NewClass procedure for constructing the class object at run 
  6434.       time, and 
  6435.    o  any IDL types and constants defined in the IDL interface. 
  6436.  
  6437.  The emitters for the C++ language produce the following binding files: 
  6438.  
  6439.  <filestem>.C (for AIX) or  <filestem>.cpp (for OS/2) (produced by the xc 
  6440.                           emitter) 
  6441.  
  6442.                           This is a template for a C++ source program that 
  6443.                           implements a class's methods. This will become the 
  6444.                           primary source file for the class. (The other binding 
  6445.                           files can be generated from the .idl file as needed.) 
  6446.                           This template implementation file contains "stub" 
  6447.                           procedures for each method introduced or overridden 
  6448.                           by the class. (The stub procedures are empty of code 
  6449.                           except for required initialization and debugging 
  6450.                           statements.) 
  6451.  
  6452.                           After the class implementer has supplied the code for 
  6453.                           the method procedures, running the xc emitter again 
  6454.                           will update this file to reflect changes made to the 
  6455.                           class definition (in the .idl file). These updates 
  6456.                           include adding new stub procedures, adding comments, 
  6457.                           and changing method prototypes to reflect changes 
  6458.                           made to the method definitions in the IDL 
  6459.                           specification. Existing code within method procedures 
  6460.                           is not disturbed, however. 
  6461.  
  6462.                           The C++ implementation file contains an #include 
  6463.                           directive for the .xih file, described below. 
  6464.  
  6465.                           The contents of the C++ source template is controlled 
  6466.                           by the Emitter Framework file 
  6467.                           <SOMBASE>/include/ctm.efw. This file can be 
  6468.                           customized to change the template produced. For 
  6469.                           detailed information on changing the template file 
  6470.                           see the Emitter Framework Guide and Reference. 
  6471.  
  6472.  <filestem>.xh            (produced by the xh emitter) 
  6473.  
  6474.                           This is the header file to be included by C++ client 
  6475.                           programs that use the class. It contains the usage 
  6476.                           bindings for the class, including a C++ definition of 
  6477.                           the class, macros for accessing the class's methods, 
  6478.                           and the new operator for creating new instances of 
  6479.                           the class. This header file includes the header files 
  6480.                           for the class's parent classes and its metaclass, as 
  6481.                           well as the header file that defines SOM's generic 
  6482.                           C++ bindings, som.xh. 
  6483.  
  6484.  <filestem>.xih           (produced by the xih emitter) 
  6485.  
  6486.                           This is the header file to be included in the 
  6487.                           implementation file (the file that implements the 
  6488.                           class's methods). It contains the implementation 
  6489.                           bindings for the class, including: 
  6490.  
  6491.    o  a struct defining the class's instance variables, 
  6492.    o  macros for accessing instance variables, 
  6493.    o  macros for invoking parent methods the class overrides, 
  6494.    o  the <className>GetData  macro (see section 5.4), 
  6495.    o  a <className>NewClass procedure for constructing the class object at run 
  6496.       time, and 
  6497.    o  any IDL types and constants defined in the IDL interface. 
  6498.  
  6499.  Other files the SOM Compiler generates: 
  6500.  
  6501.  <filestem>.hh            (produced by the hh emitter) 
  6502.  
  6503.                           This file is a DirectToSOM C++ header file that 
  6504.                           describes a SOMobjects class in a way appropriate to 
  6505.                           DTS C++. When running this emitter, you must include 
  6506.                           the noqualitytypes command-line modifier for the -m 
  6507.                           optionof the SOM Compiler command sc or somc. 
  6508.  
  6509.  <filestem>pdl            (produced by the pdl emitter) This file is the same 
  6510.                           as the .idl file from which it is produced except 
  6511.                           that all items within the .idl file that are marked 
  6512.                           as "private" have been removed.  (an item is marked 
  6513.                           as private by surrounding it with "#ifdef_PRIVATE_" 
  6514.                           and "#endif" directives.  Thus, the pdl (Public 
  6515.                           Definition Lnguage) emitter can be used to generate a 
  6516.                           "public" version of the .idl file. 
  6517.  
  6518.  <filestem>.def (for OS/2) (produced by the def emitter) 
  6519.  
  6520.                           This file is used by the linker to package a class as 
  6521.                           a library. To combine several classes into a single 
  6522.                           library, you must merge the exports statements from 
  6523.                           each of their .def  files into a single .def file for 
  6524.                           the entire library. When packaging multiple classes 
  6525.                           in a single library, you must also write a simple C 
  6526.                           procedure named SOMInitModule and add it to the 
  6527.                           export list. This procedure should call the routine 
  6528.                           <className>NewClass for each class packaged in the 
  6529.                           library. The SOMInitModule procedure is called by the 
  6530.                           SOM Class Manager when the library is dynamically 
  6531.                           loaded. 
  6532.  
  6533.  <filestem>.exp  (for AIX) (produced by the exp emitter) 
  6534.  
  6535.                           This file is used by the linker to package a class as 
  6536.                           a library. To combine several classes into a single 
  6537.                           library, you must merge the exports statements from 
  6538.                           each of their .exp  files into a single .exp file for 
  6539.                           the entire library. When packaging multiple classes 
  6540.                           in a single library, you must also write a simple C 
  6541.                           procedure named SOMInitModule and add it to the 
  6542.                           export list. This procedure should call the routine 
  6543.                           <className>NewClass for each class packaged in the 
  6544.                           library The SOMInitModule procedure is called by the 
  6545.                           SOM Class Manager when the library is dynamically 
  6546.                           loaded. 
  6547.  
  6548.  The Interface Repository (produced by the ir emitter) 
  6549.  
  6550.                           See Chapter 7 for a discussion on the Interface 
  6551.                           Repository. 
  6552.  Note: The C/C++ bindings generated by the SOM Compiler have the following 
  6553.  limitation: If two classes named "ClassName" and "ClassNameC" are defined, the 
  6554.  bindings for these two classes will clash. That is, if a client program uses 
  6555.  the C/C++ bindings (includes the .h/.xh header file) for both classes, a name 
  6556.  conflict will occur. Thus, class implementers should keep this limitation in 
  6557.  mind when naming their classes. 
  6558.  
  6559.  SOM users can extend the SOM Compiler to generate additional files by writing 
  6560.  their own emitters. To assist users in extending the SOM Compiler, SOM 
  6561.  provides an Emitter Framework a collection of classes and methods useful for 
  6562.  writing object-oriented emitters that the SOM Compiler can invoke. For more 
  6563.  information, see the Emitter Framework Guide and Reference. 
  6564.  
  6565.  Note re:  porting SOM classes: The header files (binding files) that the SOM 
  6566.  Compiler generates will only work on the platform (operating system) on which 
  6567.  they were generated. Thus, when porting SOM classes from the platform where 
  6568.  they were developed to another platform, the header files must be regenerated 
  6569.  from the .idl file by the SOM Compiler on that target platform. 
  6570.  
  6571.  
  6572. ΓòÉΓòÉΓòÉ 6.3.2. Environment variables affecting the SOM Compiler ΓòÉΓòÉΓòÉ
  6573.  
  6574. To execute the SOM Compiler on one or more files that contain IDL 
  6575. specifications for one or more classes, use the sc. or somc as follows: 
  6576.  
  6577. sc [-options] files       (on AIX or OS/2)  somc [-options] files         (on 
  6578. Windows) 
  6579.  
  6580. where "files" specifies one or more .idl files. 
  6581.  
  6582. Available "-options" for the command are detailed in the next topic. The 
  6583. operation of the SOM Compiler (whether it produces C binding files or C++ 
  6584. binding files, for example) is also controlled by a set of environment 
  6585. variables that can be set before the sc command is issued. The applicable 
  6586. environment variables are as follows: 
  6587.  
  6588.  SMEMIT              Determines which output files the SOM Compiler produces. 
  6589.                      Its value consists of a list of items separated by 
  6590.                      semicolons for OS/2, or by semicolons or colons for AIX. 
  6591.                      Each item designates an emitter to execute.  For example, 
  6592.                      the statement: 
  6593.  
  6594.       SET SMEMIT=c;h;ih        (for OS/2, for C binding files) 
  6595.       export SMEMIT="c;h;ih"   (for AIX) 
  6596.  
  6597.                      directs the SOM Compiler to produce the C binding files 
  6598.                      "hello.c", "hello.h", and"hello.ih" from the "hello.idl" 
  6599.                      input specification. By comparison, 
  6600.  
  6601.       SET SMEMIT=xc;xh;xih     (for OS/2) 
  6602.       export SMEMIT="xc;xh;xih" (for AIX) 
  6603.  
  6604.                      directs the SOM Compiler to produce C++ binding files 
  6605.                      "hello.C" (for AIX) or "hello.cpp" (for OS/2), "hello.xh", 
  6606.                      and "hello.xih" from the "hello.idl" input specification. 
  6607.  
  6608.                      By default, all output files are placed in the same 
  6609.                      directory as the input file. If the SMEMIT environment 
  6610.                      variable is not set, then a default value of "h;ih" is 
  6611.                      assumed. 
  6612.  
  6613.                      Windows note: The SMEMIT environmental variable can be set 
  6614.                      by using the SET command before the somc command is 
  6615.                      issued.  For example: 
  6616.  
  6617.                                             SET SMEMIT="c;h;ih"             (for Windows)
  6618.  
  6619.                      If you are running the SOM Compiler from a DOS box under 
  6620.                      Windows, make sure to define SMEMIT before Windows is 
  6621.                      started. 
  6622.  
  6623.  SMINCLUDE           Specifies where the SOM Compiler should look for .idl 
  6624.                      files #included by the .idl file being compiled. Its value 
  6625.                      should be one or more directory names separated by a 
  6626.                      semicolon when using OS/2, or separated by a semicolon or 
  6627.                      colon when using AIX. Directory names can be specified 
  6628.                      with absolute or relative pathnames. For example: 
  6629.  
  6630.       SET SMINCLUDE=.;..\MYSCDIR;C:\TOOLKT20\C\INCLUDE; (for OS/2 or Windows) 
  6631.  
  6632.       export SMINCLUDE=.:myscdir:/u/som/include (for AIX) 
  6633.  
  6634.                      The default value of the SMINCLUDE environment variable is 
  6635.                      the "include" subdirectory of the directory into which SOM 
  6636.                      has been installed. 
  6637.  
  6638.  SMTMP               Specifies the directory that the SOM Compiler should use 
  6639.                      to hold intermediate output files. This directory should 
  6640.                      not coincide with the directory of the input or output 
  6641.                      files. For AIX, the default setting of SMTMP is /tmp; for 
  6642.                      OS/2, the default setting of SMTMP is the root directory 
  6643.                      of the current drive. 
  6644.  
  6645.                      OS/2 or Windows example: 
  6646.  
  6647.                                              SET SMTMP=..\MYSCDIR\GARBAGE
  6648.  
  6649.                      tells the SOM Compiler to place the temporary files in the 
  6650.                      GARBAGE directory.  Or, on OS/2 only: 
  6651.  
  6652.                                              SET SMTMP=%TMP%
  6653.  
  6654.                      tells the SOM Compiler to use the same directory for 
  6655.                      temporary files as given by the setting of the TMP 
  6656.                      environment variable (the defult location for temporary 
  6657.                      system files). (On Windows, you cannot set one variable to 
  6658.                      another.) 
  6659.  
  6660.                      AIX example: 
  6661.  
  6662.                                              export SMTMP=$TMP
  6663.                                              export SMTMP=../myscdir/garbage
  6664.  
  6665.  SMKNOWNEXTS         Specifies additional emitters to which the SOM Compiler 
  6666.                      should add a header. For example, if you were to write a 
  6667.                      new emitter for Pascal, called "emitpas", then by default 
  6668.                      the SOM Compiler would not add any header comments to it. 
  6669.                      However, by setting SMKNOWNEXTS=pas, as shown: 
  6670.  
  6671.         set SMKNOWNEXTS=pas    (for OS/2 or Windows) 
  6672.  
  6673.         export SMKNOWNEXTS=pas (for AIX) 
  6674.  
  6675.                      the SOM Compiler will add a header to files generated with 
  6676.                      the "emitpas" emitter. The "header" added is a SOM 
  6677.                      Compiler-generated message plus any comments, such as 
  6678.                      copyright statements, that appear at the head of your .idl 
  6679.                      input file. For details on writing your own emitter, see 
  6680.                      the Emitter Framework Guide and Reference. 
  6681.  
  6682.  SOMIR               Specifies the name (or list of names) of the Interface 
  6683.                      Repository file. The ir emitter, if run, creates the 
  6684.                      Interface Repository, or checks it for consistency if it 
  6685.                      already exists. If the -u option is specified when 
  6686.                      invoking the SOM Compiler, the ir emitter also updates an 
  6687.                      existing Interface Repository. 
  6688.  
  6689.  
  6690. ΓòÉΓòÉΓòÉ 6.3.3. Running the SOM Compiler ΓòÉΓòÉΓòÉ
  6691.  
  6692. The syntax of the command for running the SOM Compiler takes the forms: 
  6693.  
  6694. sc  [-options] files  somc[-options] files 
  6695.  
  6696. The "files" specified in the sc or somc command denote one or more files 
  6697. containing the IDL class definitions to be compiled. If no extension is 
  6698. specified, .idl is assumed. By default, the <filestem> of the .idl file 
  6699. determines the filestem of each emitted file. Otherwise, a "filestem" modifier 
  6700. can be defined in the .idl file to specify another name (see "Modifier 
  6701. statements" discussed earlier). 
  6702.  
  6703. Selected "-options" can be specified individually, as a string of option 
  6704. characters, or as a combination of both. Any option that takes an argument 
  6705. either must be specified individually or must appear as the final option in a 
  6706. string of option characters. Available options and their purposes are as 
  6707. follows: 
  6708.  
  6709.  -C n        Sets the maximum allowable size for a simple comment in the .idl 
  6710.              file (default: 32767). This is only needed for very large single 
  6711.              comments. 
  6712.  
  6713.  -D name[=def] Defines name as in a #define directive. The default def is 1. 
  6714.              This option is the same as the -D option for the C compiler. Note: 
  6715.              This option can be used to define __PRIVATE__ so that the SOM 
  6716.              Compiler will also compile any methods and attributes that have 
  6717.              been defined as private using the directive  #ifdef__PRIVATE__; 
  6718.              however, the -p option does the same thing more easily. 
  6719.  
  6720.  -E variable=value Sets an environment variable. (See the previous topic for a 
  6721.              discussion of the available environment variables: SMEMIT, 
  6722.              SMINCLUDE, SMTMP, and SMNOIR.) 
  6723.  
  6724.  -I dir      When looking for #included files, looks first in dir, then in the 
  6725.              standard directories (same as the C compiler -I option). 
  6726.  
  6727.  -S n        Sets the total allowable amount of unique string space used in the 
  6728.              IDL specification for names and passthru lines (default: 32767). 
  6729.              This is only needed for very large .idl files. 
  6730.  
  6731.  -U name     Removes any initial definition (via a #define preprocessor 
  6732.              directive) of symbol name. 
  6733.  
  6734.  -V          Displays version information about the SOM Compiler. 
  6735.  
  6736.  -c          Turns off comment processing. This allows comments to appear 
  6737.              anywhere within an IDL specification (rather than in restricted 
  6738.              places), and it causes comments not to be transferred to the 
  6739.              output files that the SOM Compiler produces. 
  6740.  
  6741.  -d  directory Specifies a directory where all output files should be placed. 
  6742.              If the -d option is not used, all output files are placed in the 
  6743.              same directory as the input file. 
  6744.  
  6745.  -h or -?    Produces a listing of this option list. (This option is typically 
  6746.              used in an sc or somc command that does not include a .idl file 
  6747.              name) 
  6748.  
  6749.  -i filename Specifies the name of the class definition file. Use this option 
  6750.              to override the built-in assumption that the input file will have 
  6751.              a .idl extension. Any filename supplied with the -i option is used 
  6752.              exactly as it is specified. 
  6753.  
  6754.  -m name[=value] Adds a global modifier. The currently supported global 
  6755.              modifiers are as follows: 
  6756.  
  6757.       addprefixes    Adds `functionprefixes' to the method procedure prototypes 
  6758.                      during an incremental update of the implementation 
  6759.                      template file. This option applies only when rerunning the 
  6760.                      c or xc emitter on an IDL file that previously did not 
  6761.                      specify a functionprefix. A class implementor who later 
  6762.                      decides to use prefixes should add a line in the 
  6763.                      `implementation' section of the .idl file containing the 
  6764.                      specification: 
  6765.  
  6766.                      functionprefix = prefix 
  6767.  
  6768.                      (as described earlier in the topic "Modifier statements") 
  6769.                      and then rerun the c or xc emitter using the -maddprefixes 
  6770.                      option. The method procedure prototypes in the 
  6771.                      implementation file will then be updated so that each 
  6772.                      method name includes the assigned prefix. (This option 
  6773.                      does not support changes to existing prefix names, nor 
  6774.                      does it apply for OIDL files.) 
  6775.  
  6776.       addstar        This option causes all interface references to have a `*' 
  6777.                      added to them for the C bindings. See the earlier section 
  6778.                      entitled "Object types" for further details. 
  6779.  
  6780.       comment=comment string where comment string can be either of the 
  6781.                      designations: "/*"  or "//". This option indicates that 
  6782.                      comments marked in the designated manner in the .idl file 
  6783.                      are to be completely ignored by the SOM Compiler and will 
  6784.                      not be included in the output files.  Note: Comments on 
  6785.                      lines beginning with "//#" are always ignored by the SOM 
  6786.                      Compiler. 
  6787.  
  6788.       corba          This option directs the SOM Compiler to compile the input 
  6789.                      definition according to strict CORBA-defined IDL syntax. 
  6790.                      This means, for example, that comments may appear anywhere 
  6791.                      and that pointers are not allowed. When the -mcorba option 
  6792.                      is used, parts of a .idl file surrounded by 
  6793.                      #ifdef__SOMIDL__ and #endif directives are ignored. This 
  6794.                      option can be used to determine whether all nonstandard 
  6795.                      constructs (those specific to SOM IDL) are properly 
  6796.                      protected by #ifdef__SOMIDL__ and #endif directives. 
  6797.  
  6798.       csc            This option forces the OIDL compiler to be run. This is 
  6799.                      required only if you want to compile an OIDL file that 
  6800.                      does not have an extension of .csc or .sc. 
  6801.  
  6802.       emitappend     This option causes emitted files to be appended at the end 
  6803.                      of existing files of the same name. 
  6804.  
  6805.       noheader       This option ensures that the SOM Compiler does not add a 
  6806.                      header to the beginning of an emitted file. 
  6807.  
  6808.       noint          This option directs the SOM Compiler not to warn about the 
  6809.                      portability problems of using int's in the source. 
  6810.  
  6811.       nolock         This option causes the Interface Repository Emitter emitir 
  6812.                      (see Chapter 7, "Interface Repository Framework") to leave 
  6813.                      the IR unlocked when updates are made to it. This can 
  6814.                      improve performance on networked file systems. By not 
  6815.                      locking the IR, however, there is the risk of multiple 
  6816.                      processes attempting to write to the same IR, with 
  6817.                      unpredictable results. This option should only be used 
  6818.                      when you know that only one process is updating an IR at 
  6819.                      once. 
  6820.  
  6821.       nopp           This option directs the SOM Compiler not to run the SOM 
  6822.                      preprocessor on the .idl input file. 
  6823.  
  6824.       noqualifytypes This option prevents the use od C-scoped names in emitter 
  6825.                      output, and is used in conjunction with the .hh emitter. 
  6826.  
  6827.       notc           This option directs the SOM Compiler not to create 
  6828.                      TypeCode information when emitting files. This is required 
  6829.                      only when the .idl files contain some undeclared types. 
  6830.                      This option is typically used when compiling converted 
  6831.                      .csc files that have not had typing information added. 
  6832.  
  6833.       nouseshort     This option directs the SOM Compiler not to generate short 
  6834.                      forms for type names in the .h and .xh public header 
  6835.                      files. This can be useful to save disk space. 
  6836.  
  6837.       pp=preprocessor This option directs the SOM Compiler to use the specified 
  6838.                      preprocessor as the SOM preprocessor, rather than the 
  6839.                      default "somcpp". Any standard C/C++ preprocessor can be 
  6840.                      used as a preprocessor for IDL specifications. 
  6841.  
  6842.       tcconsts       This option directs the SOM Compiler to generate TypeCode 
  6843.                      constants in the h and .xh public header files. Please 
  6844.                      refer to the Interface Repository (described in Chapter 7) 
  6845.                      for more details. 
  6846.  
  6847.  Note: All command-line -m modifier options can be specified in the environment 
  6848.  by changing them to UPPERCASE and prepending "SM" to them. For example, if you 
  6849.  want to always set the options "-mnotc" and "-maddstar", set corresponding 
  6850.  environment variables as follows: 
  6851.  
  6852.    On OS/2: 
  6853.  
  6854.           set SMNOTC=1
  6855.           set SMADDSTAR=1
  6856.  
  6857.    On AIX: 
  6858.  
  6859.           export SMNOTC=1
  6860.           export SMADDSTAR=1
  6861.  
  6862.  -p          Causes the "private" sections of the IDL file to be included in 
  6863.              the compilation (that is, sections preceded by #ifdef __PRIVATE__ 
  6864.              that contain private methods and attributes). Note: The -p option 
  6865.              is equivalent to the earlier option -D__PRIVATE__. 
  6866.  
  6867.  -r          Checks that all names specified in the release order statement are 
  6868.              valid method names (default: FALSE). 
  6869.  
  6870.  -s string   Substitutes string in place of the contents of the SMEMIT 
  6871.              environment variable for the duration of the current sc command. 
  6872.              This determines which emitters will be run and, hence, which 
  6873.              output files will be produced. (If a list of values is given, on 
  6874.              OS/2 only the list must be enclosed in double quotes.) 
  6875.  
  6876.              The -s option is a convenient way to override the SMEMIT 
  6877.              environment variable. In OS/2 for example, the command: 
  6878.  
  6879.                              > SC -s"h;c" EXAMPLE
  6880.  
  6881.              is equivalent to the following sequence of commands: 
  6882.  
  6883.                              > SET OLDSMEMIT=%SMEMIT%
  6884.                              > SET SMEMIT=H;C
  6885.                              > SC EXAMPLE
  6886.                              > SET SMEMIT=%OLDSMEMIT%
  6887.  
  6888.              Similarly, in AIX the command: 
  6889.  
  6890.                              > sc -sh";"c example
  6891.  
  6892.              is equivalent to the following sequence of commands: 
  6893.  
  6894.                              > export OLDSMEMIT=$SMEMIT
  6895.                              > export SMEMIT=h";"c
  6896.                              > sc example
  6897.                              > export SMEMIT=$OLDSMEMIT
  6898.  
  6899.  -u          Updates the Interface Repository (default: no update). With this 
  6900.              option, the Interface Repository will be updated even if the ir 
  6901.              emitter is not explicitly requested in the SMEMIT environment 
  6902.              variable or the -s option. 
  6903.  
  6904.  -v          Uses verbose mode to display informational messages (default: 
  6905.              FALSE). This option is primarily intended for debugging purposes 
  6906.              and for writers of emitters. 
  6907.  
  6908.  -w          Suppresses warning messages (default: FALSE). 
  6909.  
  6910.  The following sample commands illustrate various options for the sc command or 
  6911.  similarly with somc): 
  6912.  
  6913.  sc -sc hello.idl         Generates file "hello.c". 
  6914.  
  6915.  sc -hV                   Generates a help message and displays the version of 
  6916.                           the SOM Compiler currently available. 
  6917.  
  6918.  sc -vsh";"ih hello.idl   Generates "hello.h" and "hello.ih" with informational 
  6919.                           messages. 
  6920.  
  6921.  sc -sxc -doutdir hello.idl Generates "hello.xc" in directory "outdir". 
  6922.  
  6923.  
  6924. ΓòÉΓòÉΓòÉ 6.4. The `pdl' Facility ΓòÉΓòÉΓòÉ
  6925.  
  6926. As discussed earlier in this chapter, the SOM Compiler provides a pdl (Public 
  6927. Definition Language) emitter. This emitter generates a file that is the same as 
  6928. the .idl file from which it is produced, except that it removes all items 
  6929. within the .idl file that are marked as "private." An item is marked as private 
  6930. by surrounding it with "#ifdef_ _PRIVATE_ _" and "#endif" directives. Thus, the 
  6931. pdl emitter can be used to generate a "public" version of a .idl file. 
  6932. (Generally, client programs will need only the "public" methods and 
  6933. attributes.) 
  6934.  
  6935. The SOMobjects Toolkit also provides a separate program, pdl, which performs 
  6936. the same function as the pdl emitter, but can be invoked independently of the 
  6937. SOM Compiler. In addition, the pdl program can remove any kind of items in the 
  6938. .idl file that are preceded by a user-specified "#ifdef" directive and followed 
  6939. by an "#endif" directive:  The pdl  program is invoked as follows: 
  6940.  
  6941.         pdl [ -c | d | f | h | s |/]  files 
  6942.  
  6943.  where "files" specifies one or more .idl files whose specified "#ifdef" 
  6944.  sections are to be removed.  Filenames must be completely specified (with the 
  6945.  .idl extension).  If no "#ifdef" directive is specified (by including a 
  6946.  -/<string> option), then the "#ifdef_ _PRIVATE_ __"sections will be removed by 
  6947.  default. 
  6948.  
  6949.  The pdl command supports the following options.  (Selected options can be 
  6950.  specified individually, as a string of option characters, or as a combination 
  6951.  of both. Any option that takes an argument either must be specified 
  6952.  individually or must appear as the final option in a string of option 
  6953.  characters.) 
  6954.  
  6955.  -c cmd      Specifies that, for each .idl file, the pdl program is to run the 
  6956.              specified system command. This command may contain a single 
  6957.              occurrence of the string "%s", which will be replaced with the 
  6958.              source file name before the command is executed. For example the 
  6959.              option -c"sc -sh %s" has the same effect as issuing the sc command 
  6960.              with the -sh option. 
  6961.  
  6962.  -d dir      Specifies a directory in which the output files are to be placed. 
  6963.              (The output files are given the same name as the input files.) If 
  6964.              no directory is specified, the output files are named 
  6965.              <fileStem>.pdl (where fileStem is the file stem of the input file) 
  6966.              and are placed in the current working directory. 
  6967.  
  6968.  -h          Requests this description of the pdl command syntax and options. 
  6969.  
  6970.  -f          Specifies that output files are to replace existing files with the 
  6971.              same name, even if the existing files are read-only. By default, 
  6972.              files are replaced only if they have write access. 
  6973.  
  6974.  -s smemit   Specifies the SMEMIT variable with which the pdl program is to 
  6975.              invoke the SOM Compiler. 
  6976.  
  6977.  -/ <string> Specifies the "#ifdef" pattern for which the pdl program will 
  6978.              strip out .idl statements. The default is "#ifdef _ _PRIVATE_ _". 
  6979.  
  6980.  For example, to install public versions of the .idl files in the directory 
  6981.  "pubinclude", type: 
  6982.  
  6983.      pdl -d pubinclude *.idl
  6984.  
  6985.  
  6986. ΓòÉΓòÉΓòÉ 6.5. Implementing SOM Classes ΓòÉΓòÉΓòÉ
  6987.  
  6988. The IDL specification for a class defines only the interface to the class's 
  6989. instances. The implementation of those objects (the procedures that perform 
  6990. their methods) is defined in an implementation file. To assist users in 
  6991. implementing classes, the SOM Compiler  produces a template implementation 
  6992. file--a type-correct guide for how the implementation of a class should look. 
  6993. The class implementer then modifies this template to implement the class's 
  6994. methods. 
  6995.  
  6996. The SOM Compiler can also update the implementation file to reflect later 
  6997. changes made to a class's interface definition file (the .idl file). These 
  6998. incremental updates include adding new stub procedures, adding comments, and 
  6999. changing method prototypes to reflect changes made to the method definitions in 
  7000. the IDL specification. These updates to the implementation file, however, do 
  7001. not disturb existing code in the method procedures. These updates are discussed 
  7002. further in "Running incremental updates of the implementation template file" 
  7003. later in this section. 
  7004.  
  7005. For C programmers, the SOM Compiler generates a <filestem>.c file; and for C++ 
  7006. programmers, the SOM Compiler generates a <filestem>.C  file (for AIX) or a 
  7007. <filestem>.cpp file (for OS/2). To specify whether the SOM Compiler should 
  7008. generate a C or C++ implementation template, set the value of the SMEMIT 
  7009. environment variable, or use the -s option when running the SOM Compiler. (See 
  7010. the previous section.) 
  7011.  
  7012. Note:  As this chapter describes, C++ can be used to implement a SOM class by 
  7013.        using C++ to define the instance variables introduced by the class and 
  7014.        to define the procedures that implement the overridden and introduced 
  7015.        methods of the class. This does not mean that the C++ class defined by 
  7016.        the C++ usage bindings for a SOM class (described in Chapter 3) can be 
  7017.        subclassed in C++ to create new C++ or SOM classes.  The reason why the 
  7018.        C++ implementation of a SOM class involves the definition of C++ 
  7019.        procedures (not C++ methods) to support SOM methods is that there is no 
  7020.        language-neutral way to call a C++ method. Only C++  code can call C++ 
  7021.        methods, and this calling code must be generated by the same compiler 
  7022.        that generates the method code. In contrast, the method procedures that 
  7023.        implement SOM methods must be callable from any language, without 
  7024.        knowledge on the part of the object client as to which language is used 
  7025.        to implement the resolved method procedure. 
  7026.  
  7027.  
  7028. ΓòÉΓòÉΓòÉ 6.5.1. The implementation template ΓòÉΓòÉΓòÉ
  7029.  
  7030. Consider the following IDL description of the "Hello" class: 
  7031.  
  7032.    #include <somobj.idl>
  7033.  
  7034.    interface Hello : SOMObject
  7035.    {
  7036.        void sayHello();
  7037.        // This method outputs the string "Hello, World!".
  7038.    };
  7039.  
  7040. From this IDL description, the SOM Compiler generates the following C 
  7041. implementation template, hello.c (a C++ implementation template, hello.C or 
  7042. hello.cpp, is identical except that the #included file is <hello.xih> rather 
  7043. than <hello.ih>): 
  7044.  
  7045.    #define Hello_Class_Source
  7046.    #include <hello.ih>
  7047.  
  7048.    /*
  7049.     *  This method outputs the string "Hello, World!".
  7050.     */
  7051.  
  7052.    SOM_Scope void   SOMLINK sayHello(Hello somSelf, Environment *ev)
  7053.    {
  7054.        /* HelloData *somThis = HelloGetData(somSelf); */
  7055.        HelloMethodDebug("Hello","sayHello");
  7056.    }
  7057.  
  7058. The first line defines the "Hello_Class_Source" symbol, which is used in the 
  7059. SOM-generated implementation header files for C to determine when to define 
  7060. various functions, such as "HelloNewClass."  For interfaces defined within a 
  7061. module, the directive "#define <className>_Class_Source" is replaced by the 
  7062. directive "#define SOM_Module_<moduleName>_Source". 
  7063.  
  7064. The second line (#include <hello.ih> for C, or #include <hello.xih> for C++) 
  7065. includes the SOM-generated implementation header file. This file defines a 
  7066. struct holding the class's instance variables, macros for accessing instance 
  7067. variables, macros for invoking parent methods, and so forth. 
  7068. Stub procedures for methods 
  7069.  
  7070. For each method introduced or overridden by the class, the implementation 
  7071. template includes a stub procedure--a procedure that is empty except for an 
  7072. initialization statement, a debugging statement, and possibly a return 
  7073. statement. The stub procedure for a method is preceded by any comments that 
  7074. follow the method's declaration in the IDL specification. 
  7075.  
  7076. For method "sayHello" above, the SOM Compiler generates the following prototype 
  7077. of the stub procedure: 
  7078.  
  7079.    SOM_Scope void SOMLINK sayHello(Hello somSelf, Environment *ev)
  7080.  
  7081. The "SOM_Scope" symbol is defined in the implementation header file as either 
  7082. "extern" or "static," as appropriate. The term "void" signifies the return type 
  7083. of method "sayHello". The "SOMLINK" symbol is defined by SOM; it represents the 
  7084. keyword needed to link to the C or C++ compiler, and its value is 
  7085. system-specific. Using the "SOMLINK" symbol allows the code to work with a 
  7086. variety of compilers without modification. 
  7087.  
  7088. Following the "SOMLINK" symbol is the name of the procedure that implements the 
  7089. method. If no functionprefix modifier has been specified for the class, then 
  7090. the procedure name is the same as the method name. If a functionprefix modifier 
  7091. is in effect, then the procedure name is generated by prepending the specified 
  7092. prefix to the method name. For example, if the class definition contained the 
  7093. following statement: 
  7094.  
  7095.    functionprefix = xx_;
  7096.  
  7097. then the prototype of the stub procedure for method "sayHello" would be: 
  7098.  
  7099.    SOM_Scope void SOMLINK xx_sayHello(Hello somSelf, Environment *ev)
  7100.  
  7101. The functionprefix can not be 
  7102.  
  7103.    <classname>_
  7104.  
  7105. since this is used in method invocation macros defined by the C usage bindings. 
  7106.  
  7107. Following the procedure name is the formal parameter list for the method 
  7108. procedure. Because each SOM method always receives at least one argument (a 
  7109. pointer to the SOM object that responds to the method), the first parameter 
  7110. name in the prototype of each stub procedure is called somSelf. (The macros 
  7111. defined in the implementation header file rely on this convention.) The somSelf 
  7112. parameter is a pointer to an object that is an instance of the class being 
  7113. implemented (here, class "Hello") or an instance of a class derived from it. 
  7114.  
  7115. Unless the IDL specification of the class included the callstyle=oidl modifier, 
  7116. then the formal parameter list will include one or two additional parameters 
  7117. before the parameters declared in the IDL specification: an (Environment *ev) 
  7118. input/output parameter, which permits the return of exception information, and, 
  7119. if the IDL specification of the method includes a context specification, a 
  7120. (Context *ctx) input parameter. These parameters are prescribed by the CORBA 
  7121. standard. For more information on using the Environment  and Context 
  7122. parameters, see the section entitled "Exceptions and error handling" in Chapter 
  7123. 3, "Using SOM Classes in Client Programs," and the book The Common Object 
  7124. Request Broker: Architecture and Specification, published by Object Management 
  7125. Group and X/Open. 
  7126.  
  7127. The first statement in the stub procedure for method "sayHello" is the 
  7128. statement: 
  7129.  
  7130.    /* HelloData *somThis = HelloGetData(somSelf); */
  7131.  
  7132. This statement is enclosed in comments only when the class does not introduce 
  7133. any instance variables. The purpose of this statement, for classes that do 
  7134. introduce instance variables, is to initialize a local variable (somThis) that 
  7135. points to a structure representing the instance variables introduced by the 
  7136. class. The somThis pointer is used by the macros defined in the "Hello" 
  7137. implementation header file to access those instance variables. (These macros 
  7138. are described below.)  In this example, the "Hello" class introduces no 
  7139. instance variables, so the statement is commented out. If instance variables 
  7140. are later added to a class that initially had none, then the comment characters 
  7141. can be removed if access to the variable is required. 
  7142.  
  7143. The "HelloData" type and the "HelloGetData" macro used to initialize the 
  7144. somThis pointer are defined in the implementation header file. Within a method 
  7145. procedure, class implementers can use the somThis pointer to access instance 
  7146. data, or they can use the convenience macros defined for accessing each 
  7147. instance variable, as described below. 
  7148.  
  7149. To implement a method so that it can modify a local copy of an object's 
  7150. instance data without affecting the object's real instance data, declare a 
  7151. variable of type <className>Data (for example, "HelloData") and assign to it 
  7152. the structure that somThis points to; then make the somThis pointer point to 
  7153. the copy. For example: 
  7154.  
  7155.    HelloData myCopy = *somThis;
  7156.    somThis = &myCopy;
  7157.  
  7158. Next in the stub procedure for method "sayHello" is the statement: 
  7159.  
  7160.    HelloMethodDebug("Hello", "sayHello");
  7161.  
  7162. This statement facilitates debugging. The "HelloMethodDebug" macro is defined 
  7163. in the implementation header file. It takes two arguments, a class name and a 
  7164. method name. If debugging is turned on (that is, if global variable 
  7165. SOM_TraceLevel is set to one in the calling program), the macro produces a 
  7166. message each time the method procedure is entered. (See the next Chapter 3, 
  7167. "Using SOM Classes in Client Programs," for information on debugging with SOM.) 
  7168. Debugging can be permanently disabled (regardless of the setting of 
  7169. SOM_TraceLevel in the calling program) by redefining the <className>MethodDebug 
  7170. macro to be SOM_NoTrace(c,m) following the #include directive for the 
  7171. implementation header file. (This can yield a slight performance improvement.) 
  7172. For example, to permanently disable debugging for the "Hello" class, insert the 
  7173. following lines in the hello.c implementation file following the line "#include 
  7174. hello.ih" (or "#include hello.xih," for classes implemented in C++): 
  7175.  
  7176.    #undef HelloMethodDebug
  7177.    #define HelloMethodDebug(c,m) SOM_NoTrace(c,m)
  7178.  
  7179. The way in which the stub procedure ends is determined by whether the method is 
  7180. a new or an overriding method. 
  7181.  
  7182.    o  For non-overriding (new) methods, the stub procedure ends with a return 
  7183.       statement (unless the return type of the method is void). The class 
  7184.       implementer should customize this return statement. 
  7185.  
  7186.    o  For overriding methods, the stub procedure ends by making a "parent 
  7187.       method call" for each of the class's parent classes. If the method has a 
  7188.       return type that is not void, the last of these parent method calls is 
  7189.       returned as the result of the method procedure. The class implementer can 
  7190.       customize this return statement if needed (for example, if some other 
  7191.       value is to be returned, or if the parent method calls should be made 
  7192.       before the method procedure's own processing). See the next section for a 
  7193.       discussion of parent method calls. 
  7194.  
  7195.  If a classinit modifier was specified to designate a user-defined procedure 
  7196.  that will initialize the "Hello" class object, as in the statement: 
  7197.  
  7198.      classinit = HInit;
  7199.  
  7200.  then the implementation template file would include the following stub 
  7201.  procedure for "HInit", in addition to the stub procedures for Hello's methods: 
  7202.  
  7203.      void  SOMLINK HInit(SOMClass *cls)
  7204.      {
  7205.  
  7206.      }
  7207.  
  7208.  This stub procedure is then filled in by the class implementer. If the class 
  7209.  definition specifies a functionprefix modifier, the classinit procedure name 
  7210.  is generated by prepending the specified prefix to the specified classinit 
  7211.  name, as with other stub procedures. 
  7212.  
  7213.  
  7214. ΓòÉΓòÉΓòÉ 6.5.2. Extending the implementation template ΓòÉΓòÉΓòÉ
  7215.  
  7216. To implement a method, add code to the body of the stub procedure.  In addition 
  7217. to standard C or C++ code, class implementers can also use any of the 
  7218. functions, methods, and macros SOM provides for manipulating classes and 
  7219. objects. Chapter 3, "Using SOM Classes in Client Programs," discusses these 
  7220. functions, methods, and macros. 
  7221.  
  7222. In addition to the functions, methods, and macros SOM provides for both class 
  7223. clients and class implementers, SOM provides two facilities especially for 
  7224. class implementers. They are for (1) accessing instance variables of the object 
  7225. responding to the method and (2) making parent method calls, as follows. 
  7226. Accessing internal instance variables 
  7227.  
  7228. To access internal instance variables, class implementers can use either of the 
  7229. following forms: 
  7230.  
  7231.       _variableName 
  7232.  
  7233.       somThis->variableName 
  7234.  
  7235.  To access internal instance variables "a", "b", and "c", for example, the 
  7236.  class implementer could use either _a, _b, and _c, or somThis->a, somThis->b, 
  7237.  and somThis->c. These expressions can appear on either side of an assignment 
  7238.  statement. The somThis  pointer must be properly initialized in advance using 
  7239.  the <className>GetData  procedure, as shown above. 
  7240.  
  7241.  Instance variables can be accessed only within the implementation file of the 
  7242.  class that introduces the instance variable, and not within the implementation 
  7243.  of subclasses or within client programs. (To allow access to instance data 
  7244.  from a subclass or from client programs, use an attribute rather than an 
  7245.  instance variable to represent the instance data.) For C++ programmers, the 
  7246.  _variableName form is available only if the macro  VARIABLE_MACROS is defined 
  7247.  (that is, #define VARIABLE_MACROS) in the implementation file prior to 
  7248.  including the .xih file for the class. 
  7249.  Making parent method calls 
  7250.  
  7251.  In addition to macros for accessing instance variables, the implementation 
  7252.  header file that the SOM Compiler generates also contains definitions of 
  7253.  macros for making "parent method calls." When a class overrides a method 
  7254.  defined by one or more of its parent classes, often the new implementation 
  7255.  simply needs to augment the functionality of the existing implementation(s). 
  7256.  Rather than completely re-implementing the method, the overriding method 
  7257.  procedure can conveniently invoke the procedure that one or more of the parent 
  7258.  classes uses to implement that method, then perform additional computation 
  7259.  (redefinition) as needed. The parent method call can occur anywhere within the 
  7260.  overriding method. (See Example 3 of the SOM IDL tutorial.) 
  7261.  
  7262.  The SOM-generated implementation header file defines the following macros for 
  7263.  making parent-method calls from within an overriding method: 
  7264.  
  7265.   <className>_parent_<parentClassName>_<methodName>
  7266.                (for each parent class of the class overriding the method), and
  7267.  
  7268.  <className>_parents_<methodName>. 
  7269.  
  7270.  For example, given class "Hello" with parents "File" and "Printer" and 
  7271.  overriding method somInit (the SOM method that initializes each object), the 
  7272.  SOM Compiler defines the following macros in the implementation header file 
  7273.  for "Hello": 
  7274.  
  7275.      Hello_parent_Printer_somInit
  7276.      Hello_parent_File_somInit
  7277.      Hello_parents_somInit
  7278.  
  7279.  Each macro takes the same number and type of arguments as <methodName>. The 
  7280.  <className>_parent_<parentClassName>_<methodName> macro invokes the 
  7281.  implementation of <methodName> inherited from <parentClassName>. Hence, using 
  7282.  the macro "Hello_parent_File_somInit" invokes the File's implementation of 
  7283.  somInit. 
  7284.  
  7285.  The <className>_parents_<  methodName> macro invokes the parent method for 
  7286.  each parent of the child class that supports <methodName>. That is, 
  7287.  "Hello_parents_somInit" would invoke File's implementation of somInit, 
  7288.  followed by Printer's implementation of somInit. The 
  7289.  <className>_parents_<methodName> macro is redefined in the binding file each 
  7290.  time the class interface is modified, so that if a parent class is added or 
  7291.  removed from the class definition, or if <methodName> is added to one of the 
  7292.  existing parents, the macro <className>_parents_<methodName > will be 
  7293.  redefined appropriately. 
  7294.  Converting C++ classes to SOM classes 
  7295.  
  7296.  For C++ programmers implementing SOM classes, SOM provides a macro that 
  7297.  simplifies the process of converting C++ classes to SOM classes. This macro 
  7298.  allows the implementation of one method of a class to invoke another new or 
  7299.  overriding method of the same class on the same receiving object by using the 
  7300.  following shorthand syntax: 
  7301.  
  7302.      _methodName(arg1, arg2, ...)
  7303.  
  7304.  For example, if class X introduces or overrides methods m1 and m2, then the 
  7305.  C++ implementation of method m1 can invoke method m2 on its somSelf argument 
  7306.  using _m2(arg, arg2, ...), rather than somSelf->m2(arg1, arg2, ...), as would 
  7307.  otherwise be required. (The longer form is also available.) Before the 
  7308.  shorthand form in the implementation file is used, the macro METHOD_MACROS 
  7309.  must be defined (that is, use #define METHOD_MACROS) prior to including the 
  7310.  xih file for the class. 
  7311.  Running incremental updates of the implementation template file 
  7312.  
  7313.  Refining the .idl file for a class is typically an iterative process. For 
  7314.  example, after running the IDL source file through the SOM Compiler and 
  7315.  writing some code in the implementation template file, the class implementer 
  7316.  realizes that the IDL class interface needs another method or attribute, a 
  7317.  method needs a different parameter, or any such changes. 
  7318.  
  7319.  As mentioned earlier, the SOM Compiler (when run using the c or xc emitter) 
  7320.  assists in this development by reprocessing the .idl file and making 
  7321.  incremental updates to the current implementation file. This modify-and-update 
  7322.  process may in fact be repeated several times before the class declaration 
  7323.  becomes final. Importantly, these updates do not disturb existing code for the 
  7324.  method procedures. Included in the incremental update are these changes: 
  7325.  
  7326.    o  Stub procedures are inserted into the implementation file for any new 
  7327.       methods added to the .idl file. 
  7328.  
  7329.    o  New comments in the .idl file are transferred to the implementation file, 
  7330.       reformatted appropriately. 
  7331.  
  7332.    o  If the interface to a method has changed, a new method procedure 
  7333.       prototype is placed in the implementation file. As a precaution, however, 
  7334.       the old prototype is also preserved within comments. The body of the 
  7335.       method procedure is left untouched (as are the method procedures for all 
  7336.       methods). 
  7337.  
  7338.    o  Similarly left intact are preprocessor directives, data declarations, 
  7339.       constant declarations, non-method functions, and additional comments--in 
  7340.       essence, everything else in the implementation file. 
  7341.  
  7342.  Some changes to the .idl file are not reflected automatically in the 
  7343.  implementation file after an incremental update. The class implementer must 
  7344.  manually edit the implementation file after changes such as these in the .idl 
  7345.  file: 
  7346.  
  7347.    o  Changing the name of a class or a method. 
  7348.  
  7349.    o  Changing a functionprefix class modifier statement. 
  7350.  
  7351.    o  Changing the content of a passthru statement directed to the 
  7352.       implementation (.c, .C, or cpp) file. As previously emphasized, however, 
  7353.       passthru statements are primarily recommended only for placing #include 
  7354.       statements in a binding file (.ih, xih, .h, or .xh file) used as a header 
  7355.       file in the implementation file or in a client program. 
  7356.  
  7357.    o  If the class implementer has placed "forward declarations" of the method 
  7358.       procedures in the implementation file, those are not updated. Updates 
  7359.       occur only for method prototypes that are part of the method procedures 
  7360.       themselves. 
  7361.  
  7362.  To ensure that the SOM Compiler can properly update method procedure 
  7363.  prototypes in the implementation file, class implementers should avoid editing 
  7364.  changes such as the following: 
  7365.  
  7366.    o  A method procedure name should not be enclosed in parentheses in the 
  7367.       prototype. 
  7368.  
  7369.    o  A method procedure name must appear in the first line of the prototype, 
  7370.       excluding comments and white space. Thus, a new line must not be inserted 
  7371.       before the procedure name. 
  7372.  
  7373.  Error messages occur while updating an existing implementation file if it 
  7374.  contains syntax that is not ANSI C. For example, "old style" method 
  7375.  definitions such as the example on the left generate errors: 
  7376.  
  7377.  Invalid "old" syntax     Required  ANSI C 
  7378.  void foo(x)              void foo(short x) { 
  7379.  short x;                 ... 
  7380.  { 
  7381.  ... 
  7382.  } 
  7383.  
  7384.  Similarly, error messages occur if anything in the .idl file would produce an 
  7385.  implementation file that is not syntactically valid for C/C++ (such as nested 
  7386.  comments). If update errors occur, either the .idl file or the implementation 
  7387.  file may be at fault. One way to track down the problem is to run the 
  7388.  implementation file through the C/C++ compiler. Or, move the existing 
  7389.  implementation file to another directory, generate a completely new one from 
  7390.  the .idl file, and then run it through the C/C++ compiler. One of these steps 
  7391.  should pinpoint the error, if the compiler is strict ANSI. 
  7392.  
  7393.  Conditional compilation (using #if and #ifdef directives) in the 
  7394.  implementation file can be another source of errors, because the SOM Compiler 
  7395.  does not invoke the preprocessor (it simply recognizes and ignores those 
  7396.  directives). The programmer should be careful when using conditional 
  7397.  compilation, to avoid a situation such as shown below; here, with apparently 
  7398.  two open braces and only one closing brace, the c or xc emitter would report 
  7399.  an unexpected end-of-file: 
  7400.  
  7401.  Invalid syntax           Required matching braces 
  7402.  
  7403.  #ifdef FOOBAR            #ifdef FOOBAR 
  7404.   {                        { 
  7405.  ...                      ... 
  7406.  #else                     } 
  7407.  {                        #else 
  7408.  ...                       { 
  7409.  #endif                   ... 
  7410.   }                        } 
  7411.                           #endif 
  7412.  
  7413.  
  7414. ΓòÉΓòÉΓòÉ 6.5.3. Compiling and linking ΓòÉΓòÉΓòÉ
  7415.  
  7416. After filling in the method stub procedures, the implementation template file 
  7417. can be compiled and linked with a client program as follows. (In these 
  7418. examples, the environment variable SOMBASE represents the directory in which 
  7419. SOM has been installed.) 
  7420.  
  7421. For AIX:  When the client program (main.c) and the implementation file 
  7422. (hello.c) are written in C: 
  7423.  
  7424.    > xlc -I. -I$SOMBASE/include -o hello main.c hello.c -L$SOMBASE/lib -lsomtk
  7425.  
  7426. When the client program and the implementation file are written in C++: 
  7427.  
  7428.    > xlC -I. -I$SOMBASE/include -o hello main.C hello.C -L$SOMBASE/lib -lsomtk
  7429.  
  7430. For OS/2:  When the client program (main.c) and the implementation file 
  7431. (hello.c) are in C: 
  7432.  
  7433.    > set LIB=%SOMBASE%\lib;%LIB%
  7434.    > icc -I. -I%SOMBASE%\include -Fe hello main.c hello.c somtk.lib
  7435.  
  7436. When the client program and the implementation file are written in C++: 
  7437.  
  7438.    > set LIB=%SOMBASE%\lib;%LIB%
  7439.    > icc -I. -I%SOMBASE%\include -Fe hello main.cpp hello.cpp somtk.lib
  7440.  
  7441. If the class definition (in the .idl file) changes, run the SOM Compiler again. 
  7442. This will generate new header files, and it will update the implementation file 
  7443. to include any: 
  7444.  
  7445.    o  New comments, 
  7446.  
  7447.    o  Stub procedures for any new methods, and 
  7448.  
  7449.    o  Revised method procedure prototypes for methods whose signatures have 
  7450.       been changed in the .idl file. 
  7451.  
  7452.  After rerunning the SOM Compiler, add to the implementation file the code for 
  7453.  any newly added method procedures, and recompile the implementation file with 
  7454.  the client program. 
  7455.  
  7456.  
  7457. ΓòÉΓòÉΓòÉ 6.6. Initializing and Deinitializing Objects ΓòÉΓòÉΓòÉ
  7458.  
  7459. The SOM methods somInit and somUninit  are provided in SOMObject, the ancestor 
  7460. class of all SOM classes. Whenever a new object is created in a client program 
  7461. (with an invocation of <className>New in C, the new operator in C++, or the 
  7462. somNew method), the somNew method automatically invokes somInit to initialize 
  7463. the instance variables in the object. Similarly, when somFree is called to 
  7464. release an object, somUninit is automatically invoked to deinitialize the 
  7465. instance variables. 
  7466.  
  7467. Because somInit and somUninit are invoked automatically as objects are created 
  7468. and released, class implementors can customize the way instances of the class 
  7469. are initialized and deinitialized by overriding somInit and somUninit. For 
  7470. example, if a class introduces an attribute or an instance variable, it is 
  7471. important for the class to override the default implementation of somInit to 
  7472. initialize that attribute or instance variable for a newly created instance of 
  7473. the class. (See example 3 in Chapter 2, "Tutorial for Implementing SOM 
  7474. Classes.") 
  7475.  
  7476. The somUninit method can be overridden to release resources or otherwise "clean 
  7477. up" an object before it is freed. For example, when an overriding 
  7478. implementation of somInit allocates memory to be held by the object (such as 
  7479. with SOMMalloc), then somUninit should also be overridden to free the allocated 
  7480. space just before the object itself is freed. (The somFree method frees only 
  7481. the object itself, not any additional space that has been allocated to the 
  7482. object.) 
  7483.  
  7484. The default implementations of somInit and somUninit do nothing (since 
  7485. SOMObject introduces no instance variables).  They are provided as a 
  7486. convenience to implementers so that initialization and deinitialization of 
  7487. objects can be done in a uniform way across all classes (by overriding somInit 
  7488. and somUninit). 
  7489.  
  7490. When overriding somInit and somUninit, two things are important: 
  7491.  
  7492.    1. The overriding implementation should invoke the parent method for each 
  7493.       parent, either 
  7494.  
  7495.         a. by calling the <className>_parents_<methodName> macro (which 
  7496.            automatically invokes all parent methods) or 
  7497.  
  7498.         b. by calling the <className>_parent_< parentName>_<methodName> macro 
  7499.            on each parent separately. For more information on parent method 
  7500.           calls, see the topic "Extending the Implementation Template" earlier 
  7501.           in this chapter. 
  7502.  
  7503.    2. The code should be written so that it can be executed multiple times 
  7504.       without harm on the same object. This is necessary because, under 
  7505.       multiple inheritance, parent method calls that progress up the 
  7506.       inheritance hierarchy may encounter the same ancestor class more than 
  7507.       once (where different inheritance paths "join" when the different paths 
  7508.       are followed backward). A check can be made to determine whether a 
  7509.       particular invocation of somInit is the first on a given object by 
  7510.       examining the contents of its instance variables; all the instance 
  7511.       variables of a newly created SOM object are set to zero before  somInit 
  7512.       is invoked on that object. 
  7513.  
  7514.  
  7515. ΓòÉΓòÉΓòÉ 6.6.1. An example of customizing initialization ΓòÉΓòÉΓòÉ
  7516.  
  7517. This example includes class "Animal", whose parent class is SOMObject, and 
  7518. class "Dog", a subclass of "Animal". The adjacent diagram illustrates these 
  7519. inheritance relationships and lists the methods defined by the "Animal" and 
  7520. "Dog" classes. Both classes introduce an attribute. "Animal" uses its attribute 
  7521. for the animal's name, and "Dog" uses its attribute to identify a trick the dog 
  7522. can perform. In addition, "Dog" overrides (redefines) the "print" method that 
  7523. "Animal" introduces. 
  7524.  
  7525. Because "Animal" and "Dog" introduce attributes, these classes override somInit 
  7526. to initialize these attributes when an "Animal" or "Dog" instance is created. 
  7527. Because the overriding implementation of somInit allocates memory as part of an 
  7528. initialization (here, with the SOMMalloc function), the classes also override 
  7529. the somUninit method, so that the additional memory can be freed just before 
  7530. the object holding it is freed. The following topics describe the customization 
  7531. techniques for somInit and somUninit in more detail. 
  7532. Animal class .idl file 
  7533.  
  7534. Notice in the "implementation" section below that the attribute "name" has a 
  7535. "noset" modifier. This indicates that, rather than using the standard "set" 
  7536. method that SOM normally defines automatically for an attribute, the 
  7537. implementation file will define its own "set" method. (This is necessary 
  7538. because the method needs to do more than a simple assignment of a value to an 
  7539. instance variable; it needs to do a string copy.) 
  7540.  
  7541.    #include <somobj.idl>
  7542.  
  7543.    interface Animal : SOMObject
  7544.    {
  7545.      attribute string name;
  7546.      void print();
  7547.  
  7548.    #ifdef __SOMIDL__
  7549.     implementation {
  7550.  
  7551.       somInit: override;
  7552.       somUninit: override;
  7553.  
  7554.       name: noset;
  7555.       // Define our own "set" method for name.
  7556.     };
  7557.    #endif
  7558.    };
  7559.  
  7560. Dog class .idl file 
  7561.  
  7562. In the following .idl file, observe that the "Dog" class will override the 
  7563. "print" method that it inherits from the parent class "Animal", so that "Dog" 
  7564. can add more functionality to the method. "Dog" also uses the "noset" modifier 
  7565. for the attribute "trick" it introduces. 
  7566.  
  7567.    #include <animal.idl>
  7568.  
  7569.    interface Dog : Animal
  7570.    {
  7571.        attribute string trick;
  7572.        void bark();
  7573.  
  7574.    #ifdef __SOMIDL__
  7575.     implementation {
  7576.  
  7577.        print: override;
  7578.        somInit: override;
  7579.        somUninit: override;
  7580.  
  7581.        trick: noset;
  7582.        // Define our own "set" method for trick.
  7583.     };
  7584.    #endif
  7585.    };
  7586.  
  7587. Implementation file for Animal class 
  7588.  
  7589. Here, the "_set_name" method is defined so the attribute "name" can be given a 
  7590. specified value. Observe that memory is allocated for the name (using 
  7591. SOMMalloc), and a string copy is used to store the name. The somInit method 
  7592. procedure then invokes the "_set_name" method in order to initialize the "name" 
  7593. attribute as each object of the "Animal" class is created. Notice that the 
  7594. somInit method procedure relies on the fact that a newly created SOM object has 
  7595. all data fields initialized to zero before somInit is invoked (hence, 
  7596. somThis->name will be zero the first time "_set_name" is invoked, and nonzero 
  7597. thereafter). 
  7598.  
  7599. Because the "_set_name" method allocates memory for the name, somUninit is 
  7600. redefined to free that space. Further observe for both somInit and  somUninit 
  7601. that the overriding implementations also invoke the "parent" methods of each 
  7602. method. (Method names are in bold to aid legibility.) 
  7603.  
  7604.    #define Animal_Class_Source
  7605.    #include <animal.ih>
  7606.  
  7607.    SOM_Scope void  SOMLINK  print(Animal somSelf, Environment *ev)
  7608.    {
  7609.        AnimalData *somThis = AnimalGetData(somSelf);
  7610.        AnimalMethodDebug("Animal","print");
  7611.  
  7612.        printf("My name is %s\n", __get_name(somSelf, ev));
  7613.    }
  7614.  
  7615.    SOM_Scope void  SOMLINK  _set_name(Animal somSelf, Environment *ev,
  7616.                                                      string newName)
  7617.    {
  7618.        AnimalData *somThis = AnimalGetData(somSelf);
  7619.        AnimalMethodDebug("Animal","_set_name");
  7620.  
  7621.        if (somThis->name)
  7622.           SOMFree(somThis->name);
  7623.        somThis->name = SOMMalloc(strlen(newName) + 1);
  7624.        strcpy(somThis->name, newName);
  7625.    }
  7626.  
  7627.    SOM_Scope void  SOMLINK  somInit(Animal somSelf)
  7628.    {
  7629.        AnimalData *somThis = AnimalGetData(somSelf);
  7630.        AnimalMethodDebug("Animal","somInit");
  7631.  
  7632.        __set_name(somSelf, somGetGlobalEnvironment(), "Unknown Name");
  7633.        Animal_parent_SOMObject_somInit(somSelf);
  7634.    }
  7635.  
  7636.    SOM_Scope void  SOMLINK  somUninit(Animal somSelf)
  7637.    {
  7638.        AnimalData *somThis = AnimalGetData(somSelf);
  7639.        AnimalMethodDebug("Animal","somUninit");
  7640.  
  7641.        if (somThis->name) {
  7642.           SOMFree(somThis->name);
  7643.           /* mark as freed in case somUninit gets invoked again: */
  7644.           somThis->name = 0;
  7645.        }
  7646.        Animal_parent_SOMObject_somUninit(somSelf);
  7647.    }
  7648.  
  7649. Implementation file for Dog class 
  7650.  
  7651. Notice that "Dog" has an implementation almost parallel to that of "Animal". A 
  7652. "_set_trick" method is defined and is then used within the somInit method 
  7653. procedure to set a default value for the attribute "trick". Also, since 
  7654. SOMMalloc creates memory space to hold the current "trick" value, somUninit is 
  7655. customized to free that space before the parent ("Animal") version of somUninit 
  7656. is invoked by the call to Dog_parent_Animal_somUninit. Note that this parent 
  7657. somUninit, as described above, first frees the memory holding the animal name 
  7658. and then invokes the standard somUninit that it inherits from SOMObject. 
  7659.  
  7660. The "print" method procedure here is also noteworthy, since it overrides the 
  7661. parent's method procedure. Observe that the parent method is invoked first. To 
  7662. augment functionality, the "print" redefinition then invokes the "_get_trick" 
  7663. and "bark" methods defined in the "Dog" class. 
  7664.  
  7665.    #define Dog_Class_Source
  7666.    #include <dog.ih>
  7667.  
  7668.    SOM_Scope void  SOMLINK  bark(Dog somSelf, Environment *ev)
  7669.    {
  7670.        DogData *somThis = DogGetData(somSelf);
  7671.        DogMethodDebug("Dog","bark");
  7672.  
  7673.        printf("Generic Dog Noise\n");
  7674.    }
  7675.  
  7676.    SOM_Scope void  SOMLINK  _set_trick(Dog somSelf, Environment *ev,
  7677.                                             string newTrick)
  7678.    {
  7679.        DogData *somThis = DogGetData(somSelf);
  7680.        DogMethodDebug("Dog","_set_trick");
  7681.  
  7682.        if (somThis->trick)
  7683.           SOMFree(somThis->trick);
  7684.        somThis->trick = SOMMalloc(strlen(newTrick) + 1);
  7685.        strcpy(somThis->trick, newTrick);
  7686.    }
  7687.  
  7688.    SOM_Scope void  SOMLINK  print(Dog somSelf, Environment *ev)
  7689.    {
  7690.        DogData *somThis = DogGetData(somSelf);
  7691.        DogMethodDebug("Dog","print");
  7692.  
  7693.        Dog_parent_Animal_print(somSelf, ev);
  7694.        printf("I can %s\n", __get_trick(somSelf, ev));
  7695.        printf("I say\n");
  7696.        _bark(somSelf, ev);
  7697.    }
  7698.  
  7699.    SOM_Scope void  SOMLINK  somInit(Dog somSelf)
  7700.    {
  7701.        DogData *somThis = DogGetData(somSelf);
  7702.        DogMethodDebug("Dog","somInit");
  7703.  
  7704.        Dog_parent_Animal_somInit(somSelf);
  7705.        __set_trick(somSelf, somGetGlobalEnvironment(),
  7706.                                           "unknown trick");
  7707.    }
  7708.  
  7709.    SOM_Scope void  SOMLINK  somUninit(Dog somSelf)
  7710.    {
  7711.        DogData *somThis = DogGetData(somSelf);
  7712.        DogMethodDebug("Dog","somUninit");
  7713.  
  7714.        if (somThis->trick) {
  7715.           SOMFree(somThis->trick);
  7716.           /* mark as freed in case somUninit gets invoked again: */
  7717.           somThis->trick = 0;
  7718.        }
  7719.        Dog_parent_Animal_somUninit(somSelf);
  7720.    }
  7721.  
  7722. Main program 
  7723.  
  7724.    #include <dog.h>
  7725.    main()
  7726.    {
  7727.      Dog snoopie;
  7728.  
  7729.      snoopie = DogNew();   /* create a Dog object; this also */
  7730.                            /* initializes the parent classes */
  7731.  
  7732.      _print(snoopie, ev);   /* print the default values */
  7733.  
  7734.      __set_name(snoopie, ev, "Snoopie");    /* set new values */
  7735.      __set_trick(snoopie, ev,  "roll over");
  7736.  
  7737.      _print(snoopie, ev);  /* print the new name and new trick */
  7738.  
  7739.      _somFree(snoopie);    /* free the Dog object */
  7740.  
  7741.    }
  7742.  
  7743. The "print" output occurs twice, once showing the default values and again with 
  7744. the values assigned in the main program: 
  7745.  
  7746.    My name is Unknown Name
  7747.    I can unknown trick
  7748.    I say
  7749.    Generic Dog Noise
  7750.  
  7751.    My name is Snoopie
  7752.    I can roll over
  7753.    I say
  7754.    Generic Dog Noise
  7755.  
  7756. A second main program is given below to trace method calls. As an object of the 
  7757. "Dog" class is created and freed, the following output illustrates the sequence 
  7758. in which methods are invoked and the class where each method is defined. 
  7759. [Observe that some methods defined for the classes (specifically, "print" and 
  7760. "bark") do not appear, because no code in this main program invokes them.] 
  7761.  
  7762. Arrows have been inserted in the output to show when a method was invoked from 
  7763. within another method procedure. Note that execution of the "DogNew" macro 
  7764. actually invokes somNew (which does not appear in the trace output), which in 
  7765. turn invokes the first occurrence of somInit. 
  7766.  
  7767. Code:
  7768.  
  7769.   #include <dog.h>
  7770.   int SOM_TraceLevel;
  7771.   main()
  7772.   {
  7773.     DOG tracy;
  7774.     SOM_TraceLevel = 1;      /* Trace somInit and somUninit.  */
  7775.  
  7776.  
  7777.     tracy = DogNew();        /* Create another Dog object*/
  7778.     _somFree(tracy);         /* free it      */
  7779.   }
  7780.  
  7781.  Output:                  somNew 
  7782.  
  7783.  "Dog.c": 47:             In Dog:somInit 
  7784.  "Animal.c": 34:          In Animal:somInit 
  7785.  "Animal.c": 24:          In Animal:_set_name 
  7786.  "Dog.c": 24:             In Dog:_set_trick 
  7787.  "Dog.c": 57:             In Dog:somUninit 
  7788.  "Animal.c": 44:          In Animal:somUninit 
  7789.  
  7790.  
  7791. ΓòÉΓòÉΓòÉ 6.6.2. Customizing the initialization of class objects ΓòÉΓòÉΓòÉ
  7792.  
  7793. As described previously, the somInit method can be overridden to customize the 
  7794. initialization of objects. Because classes are objects, somInit is also invoked 
  7795. on classes when they are first created (generally by invoking the somNew method 
  7796. on a metaclass). For a class object, however, somInit simply sets the name of 
  7797. the class to "unknown", and the somInitMIClass method must then be used for the 
  7798. major portion of class initialization. 
  7799.  
  7800. The somInitMIClass method is invoked on a new class object using arguments to 
  7801. indicate the class name and the parent classes from which inheritance is 
  7802. desired (among other arguments). This invocation is made by whatever routine is 
  7803. used to initialize the class. (For SOM classes using the C or C++ 
  7804. implementation bindings, this is handled by the somBuildClass procedure, which 
  7805. is called automatically.) The somInitMIClass method is normally overridden by 
  7806. its metaclass to influence the instance-method table of the new class. 
  7807. Typically, the overriding procedure begins by making parent method calls, and 
  7808. then performs the required modifications to the resulting method table. 
  7809.  
  7810. As with somInit, it is important that overriding implementations of 
  7811. somInitMIClass invoke parent methods for each parent and that the code be 
  7812. written so that it can be executed multiple times (as a result of descendent 
  7813. classes making parent method calls) without harm on the same class object. 
  7814. Note: Metaclasses can override somInit to initialize introduced class variables 
  7815. that require no arguments for their initialization. Here also, care should be 
  7816. taken to make appropriate parent calls. 
  7817.  
  7818. For an example of overriding the somInitMIClass method, see "Customizing Method 
  7819. Resolution" in chapter 5, "SOM Customization Methods." 
  7820.  
  7821. In addition to somInitMIClass, SOM provides another method, somClassReady, that 
  7822. is invoked by the routine that initializes a class (typically, from the C and 
  7823. C++ implementation bindings). The purpose of this method is to signal that the 
  7824. class is now completely initialized and ready to create instances. The default 
  7825. implementation of somClassReady simply registers the class with the 
  7826. SOMClassMgrObject. It might be appropriate, however, for other agencies besides 
  7827. the class manager to be told about some new class objects, in which case it 
  7828. would be appropriate to override somClassReady. For example, the OS/2 Workplace 
  7829. Shell (or some other environment) might have its own registration facilities 
  7830. for objects. In that case, a metaclass could override somClassReady so that the 
  7831. other necessary things can be done. 
  7832.  
  7833. As with somInit and somInitMIClass, it is important that overriding 
  7834. implementations of somClassReady invoke parent methods for each parent and that 
  7835. the code be written so that it can be executed multiple times without harm on 
  7836. the same class object. Finally, just as somInit is appropriate to all SOM 
  7837. objects, and thus to class objects as well, so too is somUninit. The 
  7838. considerations discussed in the previous section apply here as well. 
  7839.  
  7840.  
  7841. ΓòÉΓòÉΓòÉ 6.7. Creating a SOM Class Library ΓòÉΓòÉΓòÉ
  7842.  
  7843. One of the principal advantages of SOM is that it makes "black box" (or binary) 
  7844. reusability possible. Consequently, SOM classes are frequently packaged and 
  7845. distributed as class libraries. A class library holds the actual implementation 
  7846. of one or more classes and can be dynamically loaded and unloaded as needed by 
  7847. applications. Importantly, class libraries can also be replaced independently 
  7848. of the applications that use them and, provided that the class implementer 
  7849. observes simple SOM guidelines for preserving binary compatibility, can evolve 
  7850. and expand over time. 
  7851.  
  7852. Since class libraries are not programs, users cannot execute them directly. To 
  7853. enable users to make direct use of your classes, you must also provide one or 
  7854. more programs that create the classes and objects that the user will need. This 
  7855. section describes how to package your classes in a SOM class library and what 
  7856. you must do to make the contents of the library accessible to other programs. 
  7857.  
  7858. On AIX, class libraries are actually produced as AIX shared libraries, whereas 
  7859. on OS/2 they appear as dynamically-linked libraries (or DLLs). The term "DLL" 
  7860. is sometimes used to refer to either an AIX or OS/2 class library, and (by 
  7861. convention only) the file suffix ".dll" is used for SOM class libraries on both 
  7862. platforms. 
  7863.  
  7864. A program can use a class library containing a given class or classes in one of 
  7865. two ways: 
  7866.  
  7867.    1. If the programmer employs the SOM bindings to instantiate the class and 
  7868.       invoke its methods, the resulting client program contains static 
  7869.       references to the class. The operating system will automatically resolve 
  7870.       those references when the program is loaded, by also loading the 
  7871.       appropriate class library. 
  7872.  
  7873.    2. If the programmer uses only the dynamic SOM mechanisms for finding the 
  7874.       class and invoking its methods (for example, by invoking somFindClass, 
  7875.       somFindMethod, somLookupMethod, somDispatch, somResolveByName, and so 
  7876.       forth), the resulting client program does not contain any static 
  7877.       references to the class library. Thus, SOM will load the class library 
  7878.       dynamically during execution of the program. Note: For SOM to be able to 
  7879.       load the class library, the dllname  modifier must be set in the .idl 
  7880.       file. (See the topic "Modifier statements" earlier in this chapter.) 
  7881.  
  7882.  Because the provider of a class library cannot predict which of these ways a 
  7883.  class will be used, SOM class libraries must be built such that either usage 
  7884.  is possible. The first case above requires the class library to export the 
  7885.  entry points needed by the SOM bindings, whereas the second case requires the 
  7886.  library to provide an initialization function to create the classes it 
  7887.  contains. The following topics discuss each case. 
  7888.  
  7889.  
  7890. ΓòÉΓòÉΓòÉ 6.7.1. Building export files ΓòÉΓòÉΓòÉ
  7891.  
  7892. The SOM Compiler provides an "exp" emitter for AIX and a "def" emitter for OS/2 
  7893. to produce the necessary exported symbols for each class. For example, to 
  7894. generate the necessary exports for a class "A", issue the sc command with one 
  7895. of the following -s options. (For a discussion of the sc command and options, 
  7896. see "Running the SOM Compiler" earlier in this chapter.) 
  7897.  
  7898. For AIX, this command generates an "a.exp" file: 
  7899.  
  7900.    sc -sexp a.idl
  7901.  
  7902. For OS/2, this command generates an "a.def" file: 
  7903.  
  7904.    sc -sdef a.idl
  7905.  
  7906. Typically, a class library contains multiple classes. To produce an appropriate 
  7907. export file for each class that the library will contain, you can create a new 
  7908. export file for the library itself by combining the exports from each "exp" or 
  7909. "def" file into a single file. Following are examples of a combined export 
  7910. "exp" file for AIX and a combined "def" file for OS/2. Each example illustrates 
  7911. a class library composed of three classes, "A", "B", and "C". 
  7912.  
  7913. AIX "exp" file: 
  7914.  
  7915.    #! abc.dll
  7916.    ACClassData
  7917.    AClassData
  7918.    ANewClass
  7919.    BCClassData
  7920.    BClassData
  7921.    BNewClass
  7922.    CCClassData
  7923.    CClassData
  7924.    CNewClass
  7925.  
  7926. OS/2 "def" file: 
  7927.  
  7928.    LIBRARY abc INITINSTANCE
  7929.    DESCRIPTION 'abc example class library'
  7930.    PROTMODE
  7931.    DATA MULTIPLE NONSHARED LOADONCALL
  7932.    EXPORTS
  7933.      ACClassData
  7934.      AClassData
  7935.      ANewClass
  7936.      BCClassData
  7937.      BClassData
  7938.      BNewClass
  7939.      CCClassData
  7940.      CClassData
  7941.      CNewClass
  7942.  
  7943. Other symbols in addition to those generated by the "def" or "exp" emitter can 
  7944. be included if needed, but this is not required by SOM. One feature of SOM is 
  7945. that a class library needs no more than three exports per class (by contrast, 
  7946. many OOP systems require externals for every method as well). One required 
  7947. export is the name of a procedure to create the class (<className>NewClass), 
  7948. and the others are two external data structures that are referenced by the SOM 
  7949. bindings. Strictly speaking, only the <className>ClassData structure is 
  7950. required. The other, <className>CClassData, is used only by SOM 1.0 bindings, 
  7951. and is retained for backward compatibility. If you know your class will never 
  7952. be accessed by programs built with SOM 1.0, there is no need to export the 
  7953. <className>CClassData symbol. 
  7954.  
  7955.  
  7956. ΓòÉΓòÉΓòÉ 6.7.2. Specifying the initialization function ΓòÉΓòÉΓòÉ
  7957.  
  7958. An initialization function for the class library must be provided to support 
  7959. dynamic loading of the library by the SOM Class Manager. The SOM Class Manager 
  7960. expects that, whenever it loads a class library, the initialization function 
  7961. will create and register class objects for all of the classes contained in the 
  7962. library. These classes are then managed as a group (called an affinity group). 
  7963. One class in the affinity group has a privileged position--namely, the class 
  7964. that was specifically requested when the library was loaded. If that class 
  7965. (that is, the class that caused loading to occur) is subsequently unregistered, 
  7966. the SOM Class Manager will automatically unregister all of the other classes in 
  7967. the affinity group as well, and will unload the class library. Similarly, if 
  7968. the SOM Class Manager is explicitly asked to unload the class library, it will 
  7969. also automatically unregister and free all of the classes in the affinity 
  7970. group. 
  7971.  
  7972. It is the responsibility of the class-library creator to supply the 
  7973. initialization function. The interface to the initialization function is given 
  7974. by the following C/C++ prototype: 
  7975.  
  7976. #ifdef __IBMC__
  7977.   #pragma linkage (SOMInitModule, system)
  7978. #endif
  7979.  
  7980. SOMEXTERN void  SOMLINK SOMInitModule ( long majorVersion,
  7981.                                         long minorVersion,
  7982.                                         string className);
  7983.  
  7984. The parameters provided to this function are the className and the major/minor 
  7985. version numbers of the class that was requested when the library was loaded 
  7986. (that is, the class that caused loading). The initialization function is free 
  7987. to use or to disregard this information; nevertheless, if it fails to create a 
  7988. class object with the required name, the SOM Class Manager considers the load 
  7989. to have failed. As a rule of thumb, however, if the initialization function 
  7990. invokes a <className>NewClass procedure for each class in the class library, 
  7991. this condition will always be met. Consequently, the parameters supplied to the 
  7992. initialization function are not needed in most cases. 
  7993.  
  7994. Here is a typical class-library initialization function, written in C, for a 
  7995. library with three classes ("A", "B", and "C"): 
  7996.  
  7997.    #include "a.h"
  7998.    #include "b.h"
  7999.    #include "c.h"
  8000.    #ifdef __IBMC__
  8001.      #pragma linkage (SOMInitModule, system)
  8002.    #endif
  8003.  
  8004.    SOMEXTERN void  SOMLINK SOMInitModule (long majorVersion,
  8005.                              long minorVersion, string className)
  8006.    {
  8007.        SOM_IgnoreWarning (majorVersion);  /* This function makes */
  8008.        SOM_IgnoreWarning (minorVersion);  /* no use of the passed */
  8009.        SOM_IgnoreWarning (className);     /* arguments.   */
  8010.        ANewClass (A_MajorVersion, A_MinorVersion);
  8011.        BNewClass (B_MajorVersion, B_MinorVersion);
  8012.        CNewClass (C_MajorVersion, C_MinorVersion);
  8013.    }
  8014.  
  8015. The source code for the initialization function can be added to one of the 
  8016. implementation files for the classes in the library, or you can put it in a 
  8017. separate file and compile it independently. 
  8018.  
  8019.  
  8020. ΓòÉΓòÉΓòÉ 6.7.3. Creating the import library ΓòÉΓòÉΓòÉ
  8021.  
  8022. Finally, for each of your class libraries, you should create an import library 
  8023. that can be used by client programs (or by other class libraries that use your 
  8024. classes) to resolve the references to your classes. 
  8025.  
  8026. Here is an example illustrating all of the steps required to create a class 
  8027. library ("abc.dll") that contains the three classes "A", "B", and "C". 
  8028.  
  8029.    1. Compile all of the implementation files for the classes that will be 
  8030.       included in the library. Include the initialization function also. 
  8031.  
  8032.       For AIX written in C: 
  8033.  
  8034.                cc -I. -I$SOMBASE/include -c a.c
  8035.                cc -I. -I$SOMBASE/include -c b.c
  8036.                cc -I. -I$SOMBASE/include -c c.c
  8037.                cc -I. -I$SOMBASE/include -c initfunc.c
  8038.  
  8039.       For AIX written in C++: 
  8040.  
  8041.                CC -I. -I$SOMBASE/include -c a.C
  8042.                CC -I. -I$SOMBASE/include -c b.C
  8043.                CC -I. -I$SOMBASE/include -c c.C
  8044.                CC -I. -I$SOMBASE/include -c initfunc.C
  8045.  
  8046.       For OS/2 written in C: 
  8047.  
  8048.                icc -I. -I%SOMBASE%\include -c a.c
  8049.                icc -I. -I%SOMBASE%\include -c b.c
  8050.                icc -I. -I%SOMBASE%\include -c c.c
  8051.                icc -I. -I%SOMBASE%\include -c initfunc.c
  8052.                icc -I. _I%SOMBASE%\include -Ge- -c a.c
  8053.  
  8054.       Note: The "_Ge" option is used only with the IBM compiler. It indicates 
  8055.       that the object files are going into a DLL. 
  8056.  
  8057.       For OS/2 written in C++: 
  8058.  
  8059.                icc -I. -I%SOMBASE%\include -c a.cpp
  8060.                icc -I. -I%SOMBASE%\include -c b.cpp
  8061.                icc -I. -I%SOMBASE%\include -c c.cpp
  8062.                icc -I. -I%SOMBASE%\include -c initfunc.cpp
  8063.                icc -I. -I%SOMBASE%\include -Ge- -c a.c
  8064.  
  8065.       Note: The "-Ge" option is used only with the IBM compiler.  It indicates 
  8066.       that the object files are going into a DLL. 
  8067.  
  8068.    2. Produce an export file for each class. 
  8069.  
  8070.       For AIX: 
  8071.  
  8072.                sc -sexp a.idl b.idl c.idl
  8073.  
  8074.       For OS/2: 
  8075.  
  8076.                sc -sdef a.idl b.idl c.idl
  8077.  
  8078.    3. Manually combine the exported symbols into a single file. 
  8079.  
  8080.       For AIX, create a file "abc.exp" from "a.exp", "b.exp", and "c.exp". Do 
  8081.       not include the initialization function (SOMInitModule) in the export 
  8082.       list. 
  8083.  
  8084.        For OS/2, create a file "abc.def" from "a.def", "b.def", and  c.def". 
  8085.       Include the initialization function (SOMInitModule) in the export list, 
  8086.       so that all classes will be initialized automatically, unless your 
  8087.       initialization function does not need arguments and you explicitly invoke 
  8088.       it yourself from an OS/2 DLL initialization routine. 
  8089.  
  8090.    4. Using the object files and the export file, produce a binary class 
  8091.       library. 
  8092.  
  8093.       For AIX: 
  8094.  
  8095.                ld -o abc.dll -bE:abc.exp -e SOMInitModule -H512 -T512 \
  8096.                   a.o b.o c.o initfunc.o -lc -L$SOMBASE/lib -lsomtk
  8097.  
  8098.       The -o option assigns a name to the class library ("abc.dll"). The -bE: 
  8099.       option designates the file with the appropriate export list. The -e 
  8100.       option designates SOMInitModule as the initialization function. The -H 
  8101.       and -T options must be supplied as shown; they specify the necessary 
  8102.       alignment information for the text and data portions of your code. The -l 
  8103.       options name the specific libraries needed by your classes. If your 
  8104.       classes make use of classes in other class libraries, include a -l option 
  8105.       for each of these also. The ld command looks for a library named 
  8106.       "lib<x>.a", where <x> is the name provided with each -l option. The -L 
  8107.       option specifies the directory where the "somtk" library resides. 
  8108.  
  8109.       For OS/2: 
  8110.  
  8111.                set LIB=%SOMBASE%\lib;%LIB%
  8112.                link386 /noi /packd /packc /align:16 /exepack \
  8113.                    a.obj b.obj c.obj initfunc.obj, abc.dll,,os2386 somtk, \
  8114.                    abc.def
  8115.  
  8116.       If your classes make use of classes in other class libraries, include the 
  8117.       names of their import libraries immediately after "somtk" (before the 
  8118.       next comma). 
  8119.  
  8120.    5. Create an import library that corresponds to the class library, so that 
  8121.       programs and other class libraries can use (import) your classes. 
  8122.  
  8123.       For AIX: 
  8124.  
  8125.                ar ruv libabc.a abc.exp
  8126.  
  8127.       The first filename ("libabc.a") specifies the name to give to the import 
  8128.       library. It should be of the form "lib<x>.a", where <x> represents your 
  8129.       class library. The second filename ("abc.exp") specifies the exported 
  8130.       symbols to include in the import library. 
  8131.  
  8132.       Caution: Although AIX shared libraries can be placed directly into an 
  8133.       archive file ("lib<x>.a"), this is not recommended! A SOM class library 
  8134.       should have a corresponding import library constructed directly from the 
  8135.       combined export file. 
  8136.  
  8137.       For OS/2: 
  8138.  
  8139.                implib /noi abc.lib abc.def
  8140.  
  8141.       The first filename ("abc.lib") specifies the name for the import library 
  8142.       and should always have a suffix of ".lib". The second filename 
  8143.       ("abc.def") specifies the exported symbols to include in the import 
  8144.       library.  If you are using an export file that contains the symbol 
  8145.       SOMInitModule, delete it first;  SOMInitModule should not appear in your 
  8146.       import library. 
  8147.  
  8148.       Note:  SOMInitModule should be included in the <x>.dll but not in 
  8149.              <x>.lib.  If you are using an export file that contains the symbol 
  8150.              SOMInitModule, delete it first; SOMInitModule should not appear in 
  8151.              your import library because it need not be exported. 
  8152.              SOMInitModule should be included when creating your file <x>.dll 
  8153.              because all classes in the <x>.dll will be initialized. 
  8154.  
  8155.  
  8156. ΓòÉΓòÉΓòÉ 7. Implementing Classes in SOM ΓòÉΓòÉΓòÉ
  8157.  
  8158. This chapter begins with a more in-depth discussion of SOM concepts and the SOM 
  8159. run-time environment than was appropriate in Tutorial for Implementing SOM 
  8160. Classes. Subsequent sections then provide information about completing an 
  8161. implementation template file, updating the template file, compiling and 
  8162. linking, packaging classes in libraries, and other useful topics for class 
  8163. implementors. During this process, you can refer to Chapter 4, "SOM IDL and the 
  8164. SOM Compiler," if you want to read the reference information or see the full 
  8165. syntax related to topics discussed in this chapter. The current chapter ends 
  8166. with topics describing how to customize SOMobjects execution in various ways. 
  8167.  
  8168.  
  8169. ΓòÉΓòÉΓòÉ 7.1. The SOM Run-Time Environment ΓòÉΓòÉΓòÉ
  8170.  
  8171. The SOMobjects Developer Toolkit provides 
  8172.  
  8173.    o  The SOM Compiler, used when creating SOM class libraries, and 
  8174.  
  8175.    o  The SOM run-time library, for using SOM classes at execution time. 
  8176.  
  8177.  The SOM run-time library provides a set of functions used primarily for 
  8178.  creating objects and invoking methods on them. The data structures and objects 
  8179.  that are created, maintained, and used by the functions in the SOM run-time 
  8180.  library constitute the SOM run-time environment. 
  8181.  
  8182.  A distinguishing characteristic of the SOM run-time environment is that SOM 
  8183.  classes are represented by run-time objects; these objects are called class 
  8184.  objects.  By contrast, other object-oriented languages such as C++ treat 
  8185.  classes strictly as compile-time structures that have no properties at run 
  8186.  time. In SOM, however, each class has a corresponding run-time object. This 
  8187.  has three advantages:  First, application programs can access information 
  8188.  about a class at run time, including its relationships with other classes, the 
  8189.  methods it supports, the size of its instances, and so on. Second, because 
  8190.  much of the information about a class is established at run time rather than 
  8191.  at compile time, application programs needn't be recompiled when this 
  8192.  information changes. Finally, because class objects can be instances of 
  8193.  user-defined classes in SOM, users can adapt the techniques for subclassing 
  8194.  and inheritance in order to build object-oriented solutions to problems that 
  8195.  are otherwise not easily addressed within an OOP context. 
  8196.  
  8197.  
  8198. ΓòÉΓòÉΓòÉ 7.1.1. Run-time environment initialization ΓòÉΓòÉΓòÉ
  8199.  
  8200. When the SOM run-time environment is initialized, four primitive SOM objects 
  8201. are automatically created. Three of these are class objects (SOMObject, 
  8202. SOMClass, and SOMClassMgr), and one is an instance of SOMClassMgr, called the 
  8203. SOMClassMgrObject. Once loaded, application programs can invoke methods on 
  8204. these class objects to perform tasks such as creating other objects, printing 
  8205. the contents of an object, freeing objects, and the like. These four primitive 
  8206. objects are discussed below. 
  8207.  
  8208. In addition to creating the four primitive SOM objects, initialization of the 
  8209. SOM run-time environment also involves initializing global variables to hold 
  8210. data structures that maintain the state of the environment.  Other functions in 
  8211. the SOM run-time library rely on these global variables. 
  8212.  
  8213. For application programs written in C or C++ that use the language-specific 
  8214. bindings provided by SOM, the SOM run-time environment is automatically 
  8215. initialized the first time any object is created.  Programmers using other 
  8216. languages must initialize the run-time environment explicitly by calling the 
  8217. somEnvironmentNew function (provided by the SOM run-time library) before using 
  8218. any other SOM functions or methods. 
  8219. SOMObject class object 
  8220.  
  8221. SOMObject is the root class for all SOM classes. It defines the essential 
  8222. behavior common to all SOM objects.  All user-defined SOM classes are derived, 
  8223. directly or indirectly, from this class. That is, every SOM class is a subclass 
  8224. of SOMObject or of some other class derived from SOMObject. SOMObject has no 
  8225. instance variables, thus objects that inherit from SOMObject incur no size 
  8226. increase. They do inherit a suite of methods that provide the behavior required 
  8227. of all SOM objects. 
  8228. SOMClass class object 
  8229.  
  8230. Because SOM classes are run-time objects, and since all run-time objects are 
  8231. instances of some class, it follows that a SOM class object must also be an 
  8232. instance of some class. The class of a class is called a metaclass. Hence, the 
  8233. instances of an ordinary class are individuals (nonclasses), while the 
  8234. instances of a metaclass are class objects. 
  8235.  
  8236. In the same way that the class of an object defines the "instance methods" that 
  8237. the object can perform, the metaclass of a class defines the "class methods" 
  8238. that the class itself can perform. Class methods (sometimes called factory 
  8239. methods or constructors) are performed by class objects. Class methods perform 
  8240. tasks such as creating new instances of a class, maintaining a count of the 
  8241. number of instances of the class, and other operations of a "supervisory" 
  8242. nature. Also, class methods facilitate inheritance of instance methods from 
  8243. parent classes. For information on the distinction between parent classes and 
  8244. metaclasses, see the section "Parent Class vs. metaclass," later in this 
  8245. chapter. 
  8246.  
  8247. SOMClass is the root class for all SOM metaclasses.  That is, all SOM 
  8248. metaclasses must be subclasses of SOMClass or of some metaclass derived from 
  8249. SOMClass. SOMClass defines the essential behavior common to all SOM class 
  8250. objects.  In particular, SOMClass provides: 
  8251.  
  8252.    o  Six class methods for creating new class instances: somNew, somNewNoInit, 
  8253.       somRenew, somRenewNoInit, somRenewNoZero  and somRenewNoInitNoZero. 
  8254.  
  8255.    o  A number of class methods that dynamically obtain or update information 
  8256.       about a class and its methods at run time, including: 
  8257.  
  8258.         -  somInitMIClass, for implementing multiple inheritance from parent 
  8259.            classes, 
  8260.  
  8261.         -  somOverrideSMethod, for overriding inherited methods, and 
  8262.  
  8263.         -  somAddStaticMethod and somAddDynamicMethod, for including new 
  8264.            methods. 
  8265.  
  8266.  SOMClass is a subclass (or child) of SOMObject. Hence, SOM class objects can 
  8267.  also perform the same set of basic instance methods common to all SOM objects. 
  8268.  This is what allows SOM classes to be real objects in the SOM run-time 
  8269.  environment. SOMClass also has the unique distinction of being its own 
  8270.  metaclass (that is, SOMClass defines its own class methods). 
  8271.  
  8272.  A user-defined class can designate as its metaclass either SOMClass or another 
  8273.  user-written metaclass descended from SOMClass. If a metaclass is not 
  8274.  explicitly specified, SOM determines one automatically. 
  8275.  SOMClassMgr class object and SOMClassMgrObject 
  8276.  
  8277.  The third primitive SOM class is SOMClassMgr. A single instance of the 
  8278.  SOMClassMgr class is created automatically during SOM initialization. This 
  8279.  instance is referred to as the SOMClassMgrObject, because it is pointed to by 
  8280.  the global variable SOMClassMgrObject. The object SOMClassMgrObject has the 
  8281.  responsibility to 
  8282.  
  8283.    o  Maintain a registry (a run-time directory) of all SOM classes that exist 
  8284.       within the current process, and to 
  8285.  
  8286.    o  Assist in the dynamic loading and unloading of class libraries. 
  8287.  
  8288.  For C/C++ application programs using the SOM C/C++ language bindings, the 
  8289.  SOMClassMgrObject automatically loads the appropriate library file and 
  8290.  constructs a run-time object for the class the first time an instance of a 
  8291.  class is created. For programmers using other languages, SOMClassMgr provides 
  8292.  a method, somFindClass, for directing the SOMClassMgrObject to load the 
  8293.  library file for a class and create its class object. 
  8294.  
  8295.  Again, the primitive classes supplied with SOM are SOMObject, SOMClass, and 
  8296.  SOMClassMgr.  During SOM initialization, the latter class generates an 
  8297.  instance called SOMClassMgrObject. The SOMObject class is the parent class of 
  8298.  SOMClass and SOMClassMgr. The SOMClass class is the metaclass of itself, of 
  8299.  SOMObject, and of SOMClassMgr, which are all class objects at run time. 
  8300.  SOMClassMgr is the class of SOMClassMgrObject. 
  8301.  
  8302.  The SOM run-time environment provides four primitive objects, three of them 
  8303.  class objects. 
  8304.  
  8305.  
  8306. ΓòÉΓòÉΓòÉ 7.1.2. Parent class vs. metaclass ΓòÉΓòÉΓòÉ
  8307.  
  8308. There is a distinct difference between the notions of "parent" (or base) class 
  8309. and "metaclass." Both notions are related to the fact that a class defines the 
  8310. methods and variables of its instances, which are therefore called instance 
  8311. methods and instance variables. 
  8312.  
  8313. A parent of a given class is a class from which the given class is derived  by 
  8314. subclassing. (Thus, the given class is called a child or a subclass  of the 
  8315. parent.) A parent class is a class from which instance methods and instance 
  8316. variables are inherited. For example, the parent of class "Dog" might be class 
  8317. "Animal". Hence, the instance methods and variables introduced by "Animal" 
  8318. (such as methods for breathing and eating, or a variable for storing an 
  8319. animal's weight) would also apply to instances of "Dog", because "Dog" inherits 
  8320. these from "Animal", its parent class. As a result, any given dog instance 
  8321. would be able to breath and eat, and would have a weight. 
  8322.  
  8323. A metaclass is a class whose instances are class objects, and whose instance 
  8324. methods and instance variables (as described above) are therefore the methods 
  8325. and variables of class objects. For this reason, a metaclass is said to define 
  8326. class methods--the methods that a class object performs. For example, the 
  8327. metaclass of "Animal" might be "AnimalMClass", which defines the methods that 
  8328. can be invoked on class "Animal" (such as, to create Animal instances--objects 
  8329. that are not classes, like an individual pig or cat or elephant or dog). 
  8330.  
  8331. Note: It is important to distinguish the methods of a class object (that is, 
  8332. the methods that can be invoked on the class object, which are defined by its 
  8333. metaclass) from the methods that the class defines for its instances. 
  8334.  
  8335. To summarize: the parent of a class provides inherited methods that the class's 
  8336. instances can perform; the metaclass of a class provides class methods that the 
  8337. class itself can perform.  These distinctions are further summarized below: 
  8338.  
  8339. The distinctions between parent class and metaclass are summarized in the 
  8340. figure below. 
  8341.  
  8342. Any class "C" has both a metaclass and one or more parent class(es). 
  8343.  
  8344.    o  The parent class(es) of "C" provide the inherited instance methods that 
  8345.       individual instances (objects "Oi") of class "C" can perform. Instance 
  8346.       methods that an instance "Oi" performs might include (a) initializing 
  8347.       itself, (b) performing computations using its instance variables, (c) 
  8348.       printing its instance variables, or (d) returning its size. New instance 
  8349.       methods are defined by "C" itself, in addition to those inherited from 
  8350.       C's parent classes. 
  8351.  
  8352.    o  The metaclass "M"defines the class methods that class "C" can perform. 
  8353.       For example, class methods defined by metaclass "M" include those that 
  8354.       allow "C" to (a) inherit its parents' instance methods and instance 
  8355.       variables, (b) tell its own name, (c) create new instances, and (d) tell 
  8356.       how many instance methods it supports. These methods are inherited from 
  8357.       SOMClass. Additional methods supported by "M" might allow "C" to count 
  8358.       how many instances it creates. 
  8359.  
  8360.    o  Each class "C" has one or more parent classes and exactly one metaclass. 
  8361.       (The single exception is SOMObject, which has no parent class.)  Parent 
  8362.       class(es) must be explicitly identified in the IDL declaration of a 
  8363.       class. (SOMObject is given as a parent if no subsequently-derived class 
  8364.       applies.)  If a metaclass is not explicitly listed, the SOM run time will 
  8365.       determine an applicable metaclass. 
  8366.  
  8367.    o  An instance of a metaclass is always another class object. For example, 
  8368.       class "C" is an instance of metaclass "M".  SOMClass is the SOM-provided 
  8369.       metaclass from which all subsequent metaclasses are derived. 
  8370.  
  8371.  A metaclass has its own inheritance hierarchy (through its parent classes) 
  8372.  that is independent of its instances' inheritance hierarchies. For example, 
  8373.  suppose a series of classes is defined (or derived), stemming from SOMObject. 
  8374.  The child class (or subclass) at the end of this line ("C2") inherits instance 
  8375.  methods from all of its ancestor classes (here, SOMObject and "C1"). An 
  8376.  instance created by "C2" can perform any of these instance methods.  In an 
  8377.  analogous manner, a line of metaclasses can be defined, stemming from 
  8378.  SOMClass. Just as a new class is derived from an existing class (such as 
  8379.  SOMObject), a new metaclass is derived from an existing metaclass (such as 
  8380.  SOMClass). 
  8381.  
  8382.  
  8383. ΓòÉΓòÉΓòÉ 7.1.3. SOM-derived metaclasses ΓòÉΓòÉΓòÉ
  8384.  
  8385. As previously discussed, a class object can perform any of the class methods 
  8386. that its metaclass defines. New metaclasses are typically created to modify 
  8387. existing class methods or introduce new class method(s). Chapter 8, "Metaclass 
  8388. Framework," discusses metaclass programming. 
  8389.  
  8390. Three factors are essential for effective use of metaclasses in SOM: 
  8391.  
  8392.    o  First, every class in SOM is an object that is implemented by a 
  8393.       metaclass. 
  8394.  
  8395.    o  Second, programmers can define and name new metaclasses, and can use 
  8396.       these metaclasses when defining new SOM classes. 
  8397.  
  8398.    o  Finally, and most importantly, metaclasses cannot interfere with the 
  8399.       fundamental guarantee required of every OOP system: specifically, any 
  8400.       code that executes without method-resolution error on instances of a 
  8401.       given class will also execute without method-resolution errors on 
  8402.       instances of any subclass of this class. 
  8403.  
  8404.  Surprisingly, SOM is currently the only OOP system that can make this final 
  8405.  guarantee while also allowing programmers to explicitly define and use named 
  8406.  metaclasses. This is possible because SOM automatically determines an 
  8407.  appropriate metaclass that supports this guarantee, automatically deriving new 
  8408.  metaclasses by subclassing at run time when this is necessary. As an example, 
  8409.  suppose class "A" is an instance of metaclass "AMeta". 
  8410.  
  8411.  Assume that "AMeta" supports a method "bar" and that "A" supports a method 
  8412.  "foo" that uses the expression "_bar( _somGetClass(somSelf ) )." That is, 
  8413.  method "foo" invokes "bar" on the class of the object on which "foo" is 
  8414.  invoked. For example, when method "foo" is invoked on an instance of class "A" 
  8415.  (say, object "O1"), this in turn invokes "bar" on class "A" itself. 
  8416.  
  8417.  Now consider what happens if class "A" were subclassed by "B," a class that 
  8418.  has the explicit metaclass "BMeta" declared in its SOM IDL source file (and 
  8419.  assuming "BMeta" is not derived from "AMeta"). Also assume that object "O2" is 
  8420.  an instance of class "B." 
  8421.  
  8422.  Recall that "AMeta" supports method "bar" and that class "A" supports method 
  8423.  "foo" (which incorporates "bar" in its definition). Given the hierarchy 
  8424.  described above, an invocation of "foo" on "O 2" would fail, because metaclass 
  8425.  "BMeta" does not support the "bar" method. 
  8426.  
  8427.  There is only one way that "BMeta" can support this specific method--by 
  8428.  inheriting it from "AMeta" ("BMeta" could introduce another method named 
  8429.  "bar", but this would be a different method from the one introduced by 
  8430.  "AMeta"). Therefore, in this example, because "BMeta" is not a subclass of 
  8431.  "AMeta", "BMeta" cannot be allowed to be the metaclass of "B". That is, 
  8432.  "BMeta" is not compatible with the requirements placed on "B" by the 
  8433.  fundamental principle of OOP referred to above. This situation is referred to 
  8434.  as metaclass incompatibility. 
  8435.  
  8436.  SOM does not allow hierarchies with metaclass incompatibilities. Instead, SOM 
  8437.  automatically builds derived metaclasses when this is necessary. For example, 
  8438.  SOM would create a "DerivedMeta" metaclass that has both "AMeta" and "BMeta" 
  8439.  as parents. This ensures that the invocation of method "foo" on instances of 
  8440.  class "B" will not fail, and also ensures that the desired class methods 
  8441.  provided by "BMeta" will be available on class "B". 
  8442.  
  8443.  There are three important aspects of SOM's approach to derived metaclasses: 
  8444.  
  8445.    o  First, the creation of SOM-derived metaclasses is integrated with 
  8446.       programmer-specified metaclasses. If a programmer-specified metaclass 
  8447.       already supports all the class methods and variables needed by a new 
  8448.       class, then the programmer-specified metaclass will be used as is. 
  8449.  
  8450.    o  Second, if SOM must derive a different metaclass than the one explicitly 
  8451.       indicated by the programmer (in order to support all the necessary class 
  8452.       methods and variables), then the SOM-derived metaclass inherits from the 
  8453.       explicitly indicated metaclass first. As a result, the method procedures 
  8454.       defined by the specified metaclass take precedence over other 
  8455.       possibilities (see the following section on inheritance and the 
  8456.       discussion of resolution of ambiguity in the case of multiple 
  8457.       inheritance). 
  8458.  
  8459.    o  Finally, the class methods defined by the derived metaclass invoke the 
  8460.       appropriate initialization methods of its parents to ensure that the 
  8461.       class variables of its instances are correctly initialized. 
  8462.  
  8463.  As further explanation for the automatic derivation of metaclasses, consider 
  8464.  the following multiple-inheritance example. Class "C" (derived from classes 
  8465.  "A" and "B") does not have an explicit metaclass declaration in its SOM IDL, 
  8466.  yet its parents "A" and "B" do. As a result, class "C" requires a derived 
  8467.  metaclass. (If you still have trouble following the reasoning behind derived 
  8468.  metaclasses, ask yourself the following question: What class should "C" be an 
  8469.  instance of? After a bit of reflection, you will conclude that, if SOM did not 
  8470.  build the derived metaclass, you would have to do so yourself.) 
  8471.  
  8472.  In summary, SOM allows and encourages the definition and explicit use of named 
  8473.  metaclasses. With named metaclasses, programmers can not only affect the 
  8474.  behavior of class instances by choosing the parents of classes, but they can 
  8475.  also affect the behavior of the classes themselves by choosing their 
  8476.  metaclasses.  Because the behavior of classes in SOM includes the 
  8477.  implementation of inheritance itself, metaclasses in SOM provide an extremely 
  8478.  flexible and powerful capability allowing classes to package solutions to 
  8479.  problems that are otherwise very difficult to address within an OOP context. 
  8480.  
  8481.  At the same time, SOM is unique in that it relieves programmers of the 
  8482.  responsibility for avoiding metaclass incompatibility when defining a new 
  8483.  class. At first glance, this might seem to be merely a useful (though very 
  8484.  important) convenience. But, in fact, it is absolutely essential, because SOM 
  8485.  is predicated on binary compatibility with respect to changes in class 
  8486.  implementations. 
  8487.  
  8488.  A programmer might, at one point in time, know the metaclasses of all ancestor 
  8489.  classes of a new subclass, and, as a result, be able to explicitly derive an 
  8490.  appropriate metaclass for the new class. Nevertheless, SOM must guarantee that 
  8491.  this new class will still execute and perform correctly when any of its 
  8492.  ancestor class's implementations are changed (which could even include 
  8493.  specifying different metaclasses). Derived metaclasses allow SOM to make this 
  8494.  guarantee.  A SOM programmer need never worry about the problem of metaclass 
  8495.  incompatibility; SOM does this for the programmer. Instead, explicit 
  8496.  metaclasses can simply be used to "add in" whatever behavior is desired for a 
  8497.  new class. SOM automatically handles anything else that is needed. Chapter 10 
  8498.  provides useful examples of such metaclasses. A SOM programmer should find 
  8499.  numerous applications for the techniques that are illustrated there. 
  8500.  
  8501.  
  8502. ΓòÉΓòÉΓòÉ 7.2. Inheritance ΓòÉΓòÉΓòÉ
  8503.  
  8504. One of the defining aspects of an object model is its characterization of 
  8505. inheritance. This section describes SOM's model for inheritance. 
  8506.  
  8507. A class in SOM defines an implementation for objects that support a specific 
  8508. interface: 
  8509.  
  8510.    o  The interface defines the methods supported by objects of the class, and 
  8511.       is specified using SOM IDL. 
  8512.  
  8513.    o  The implementation  defines what instance variables implement an object's 
  8514.       state and what procedures implement its methods. 
  8515.  
  8516.  New classes are derived (by subclassing) from previously existing classes 
  8517.  through inheritance, specialization, and addition.  Subclasses inherit 
  8518.  interface from their parent classes: any method available on instances of a 
  8519.  class is also available on instances of any class derived from it (either 
  8520.  directly or indirectly).  Subclasses also inherit implementation (the 
  8521.  procedures that implement the methods) from their parent classes unless the 
  8522.  methods are overridden (redefined or specialized). In addition, a subclass may 
  8523.  introduce new instance methods and instance variables that will be inherited 
  8524.  by other classes derived from it. 
  8525.  
  8526.  SOM also supports multiple inheritance. That is, a class may be derived from 
  8527.  (and may inherit interface and implementation from) multiple parent classes. 
  8528.  Note: Multiple inheritance is available only to SOM classes whose interfaces 
  8529.  are specified in IDL, and not to SOM classes whose interfaces are specified in 
  8530.  SOM's earlier interface definition language, OIDL. See Appendix B for 
  8531.  information on how to automatically convert existing OIDL files to IDL. 
  8532.  
  8533.  It is possible under multiple inheritance to encounter potential conflicts or 
  8534.  ambiguities with respect to inheritance. All multiple inheritance models must 
  8535.  face these issues, and resolve the ambiguities in some way. For example, when 
  8536.  multiple inheritance is allowed, it is possible that a class will inherit the 
  8537.  same method or instance variable from different parents (because each of these 
  8538.  parents has some common ancestor that introduces the method or instance 
  8539.  variable). In this situation, a SOM subclass inherits only one implementation 
  8540.  of the method or instance variable. (The implementation of an instance 
  8541.  variable within an object is just the location where it is stored. The 
  8542.  implementation of a method is a procedure pointer, stored within a method 
  8543.  table.) The following illustration addresses the question of which method 
  8544.  implementation would be inherited. 
  8545.  
  8546.  Consider this situation: Class "W" defines a method "foo", implemented by 
  8547.  procedure "proc1". Class "W" has two subclasses, "X" and "Y". Subclass "Y" 
  8548.  overrides the implementation of "foo" with procedure "proc2". Subclass "X" 
  8549.  does not override "foo". In addition, classes "X" and "Y" share a common 
  8550.  subclass, "Z". That is, the IDL interface statement for class "Z" lists its 
  8551.  parents as "X" and "Y" in that order. (These relationships form a diamond 
  8552.  shape, with class "W" at the top.) 
  8553.  
  8554.  The question is thus: which implementation of method "foo" does class "Z" 
  8555.  inherit--procedure "proc1" defined by class "W", or procedure "proc2" defined 
  8556.  by class "Y"? The procedure for performing inheritance that is defined by 
  8557.  SOMClass resolves this ambiguity by using the left path precedence rule: when 
  8558.  the same method is inherited from multiple ancestors, the procedure used to 
  8559.  support the method is the one used by the leftmost ancestor from which the 
  8560.  method is inherited. (The ordering of parent classes is determined by the 
  8561.  order in which the class implementor lists the parents in the IDL 
  8562.  specification for the class.) 
  8563.  
  8564.  Class "Z" inherits the implementation of method "foo" defined by class "W" 
  8565.  (procedure "proc1"), rather than the implementation defined by class "Y" 
  8566.  (procedure "proc2"), because "X" is the leftmost ancestor of "Z" from which 
  8567.  the method "foo" is inherited. This rule may be interpreted as giving priority 
  8568.  to classes whose instance interfaces are mentioned first in IDL interface 
  8569.  definitions. 
  8570.  
  8571.  If a class implementor decides that the default inherited implementation is 
  8572.  not appropriate (for example, procedure "proc2" is desired), then SOM IDL 
  8573.  allows the class designer to select the parent whose implementation is 
  8574.  desired. For more information concerning this approach, see the Select 
  8575.  modifier, which is documented in the topic "Modifier statements" in Chapter 4, 
  8576.  "SOM IDL and the SOM Compiler." 
  8577.  
  8578.  Note:  Alternatively, an explicit metaclass for "Z" could be introduced to 
  8579.         change the way methods are inherited. However, this would be a fairly 
  8580.         serious step to take--it would also affect the semantics of inheritance 
  8581.         for all of Z's descendant classes. Also, this would be done by 
  8582.         overriding somInitMIClass, which is strongly discouraged until such 
  8583.         time that SOMObjects includes The Cooperative Metaclass among its 
  8584.         officially supported interfaces to the Metaclass Framework. 
  8585.  
  8586.  Another conflict that may arise with the use of multiple inheritance is when 
  8587.  two ancestors of a class define different methods (in general, with different 
  8588.  signatures) of the same name. For example, suppose Class "X" defines a method 
  8589.  "bar" with type T1, and class "Y" defines a method "bar" with type T2. Class 
  8590.  "Z" is derived from both "X" and "Y", and "Z" does not override method "bar". 
  8591.  
  8592.  This example illustrates a method name that is "overloaded"--that is, used to 
  8593.  name two entirely different methods (note that overloading is completely 
  8594.  unrelated to overriding). This is not necessarily a difficult problem to 
  8595.  handle. Indeed, the run-time SOM API allows the construction of a class that 
  8596.  supports the two different "bar" methods. (They are implemented using two 
  8597.  different method-table entries, each of which is associated with its 
  8598.  introducing class.) 
  8599.  
  8600.  However, the interface to instances of such classes can not be defined using 
  8601.  IDL. IDL specifically forbids the definition of interfaces in which method 
  8602.  names are overloaded.  Furthermore, within SOM itself, the use of such classes 
  8603.  can lead to anomalous behavior unless care is taken to avoid the use of 
  8604.  name-lookup method resolution (discussed in the following section), since, in 
  8605.  this case, a method name alone does not identify a unique method. For this 
  8606.  reason, (statically declared) multiple-inheritance classes in SOM are 
  8607.  currently restricted to those whose instance interfaces can be defined using 
  8608.  IDL. Thus, the above example cannot be constructed with the aid of the SOM 
  8609.  Compiler. 
  8610.  
  8611.  
  8612. ΓòÉΓòÉΓòÉ 7.3. Method Resolution ΓòÉΓòÉΓòÉ
  8613.  
  8614. Method resolution is the step of determining which procedure to execute in 
  8615. response to a method invocation. For example, consider this scenario: 
  8616.  
  8617.    o  Class "Dog" introduces a method "bark", and 
  8618.  
  8619.    o  A subclass of "Dog", called "BigDog", overrides "bark", and 
  8620.  
  8621.    o  A client program creates an instance of either "Dog" or "BigDog" 
  8622.       (depending on some run-time criteria) and invokes method "bark" on that 
  8623.       instance. 
  8624.  
  8625.  Method resolution is the process of determining, at run time, which method 
  8626.  procedure to execute in response to the method invocation (either the method 
  8627.  procedure for "bark" defined by "Dog", or the method procedure for "bark" 
  8628.  defined by "BigDog"). This determination depends on whether the receiver of 
  8629.  the method (the object on which it is invoked) is an instance of "Dog" or 
  8630.  "BigDog" (or perhaps depending on some other criteria). 
  8631.  
  8632.  SOM allows class implementors and client programs considerable flexibility in 
  8633.  deciding how SOM performs method resolution. In particular, SOM supports three 
  8634.  mechanisms for method resolution, described in order of increased flexibility 
  8635.  and increased computational cost: offset resolution, name-lookup resolution, 
  8636.  and dispatch-function resolution. 
  8637.  
  8638.  
  8639. ΓòÉΓòÉΓòÉ 7.3.1. Offset resolution ΓòÉΓòÉΓòÉ
  8640.  
  8641. When using SOM's C and C++ language bindings, offset resolution is the default 
  8642. way of resolving methods, because it is the fastest. For those familiar with 
  8643. C++, it is roughly equivalent to the C++ "virtual function" concept. 
  8644.  
  8645. Although offset resolution is the fastest technique for method resolution, it 
  8646. is also the most constrained. Specifically, using offset resolution requires 
  8647. these constraints: 
  8648.  
  8649.    o  The name of the method to be invoked must be known at compile time, 
  8650.  
  8651.    o  The name of the class that introduces the method must be known at compile 
  8652.       time (although not necessarily by the programmer), and 
  8653.  
  8654.    o  The method to be invoked must be part of the introducing class's static 
  8655.       (IDL) interface definition. 
  8656.  
  8657.  To perform offset method resolution, SOM first obtains a method token from a 
  8658.  global data structure associated with the class that introduced the method. 
  8659.  This data structure is called the ClassData structure. It includes a method 
  8660.  token for each method the class introduces. The method token is then used as 
  8661.  an "index" into the receiver's method table, to access the appropriate method 
  8662.  procedure. Because it is known at compile time which class introduces the 
  8663.  method and where in that class's ClassData structure the method's token is 
  8664.  stored, offset resolution is quite efficient. The cost of offset method 
  8665.  resolution is currently about twice the cost of calling a C function using a 
  8666.  pointer loaded with the function address. 
  8667.  
  8668.  An object's method table is a table of pointers to the procedures that 
  8669.  implement the methods that the object supports. This table is constructed by 
  8670.  the object's class and is shared among the class instances. The method table 
  8671.  built by class (for its instances) is referred to as the class's instance 
  8672.  method table. This is useful terminology, since, in SOM, a class is itself an 
  8673.  object with a method table (created by its metaclass) used to support method 
  8674.  calls on the class. 
  8675.  
  8676.  Usually, offset method resolution is sufficient; however, in some cases, the 
  8677.  more flexible name-lookup resolution is required. 
  8678.  
  8679.  
  8680. ΓòÉΓòÉΓòÉ 7.3.2. Name-lookup resolution ΓòÉΓòÉΓòÉ
  8681.  
  8682. Name-lookup resolution is similar to the method resolution techniques employed 
  8683. by Objective-C and Smalltalk. It is currently about five times slower than 
  8684. offset resolution. It is more flexible, however. In particular, name-lookup 
  8685. resolution, unlike offset resolution, can be used when: 
  8686.  
  8687.    o  The name of the method to be invoked isn't known until run time, or 
  8688.  
  8689.    o  The method is added to the class interface at run time, or 
  8690.  
  8691.    o  The name of the class introducing the method isn't known until run time. 
  8692.  
  8693.  For example, a client program may use two classes that define two different 
  8694.  methods of the same name, and it might not be known until run time which of 
  8695.  the two methods should be invoked (because, for example, it will not be known 
  8696.  until run time which class's instance the method will be applied to). 
  8697.  
  8698.  Name-lookup resolution is always performed by a class, so it requires a method 
  8699.  call. (Offset resolution, by contrast, requires no method calls.) To perform 
  8700.  name-lookup method resolution, the class of the intended receiver object 
  8701.  obtains a method procedure pointer for the desired method  that is appropriate 
  8702.  for its instances. In general, this will require a name-based search through 
  8703.  various data structures maintained by ancestor classes. 
  8704.  
  8705.  Offset and name-lookup resolution achieve the same net effect (that is, they 
  8706.  select the same method procedure); they just achieve it differently (via 
  8707.  different mechanisms for locating the method's method token). Offset 
  8708.  resolution is faster, because it does not require searching for the method 
  8709.  token, but name-lookup resolution is more flexible. 
  8710.  
  8711.  When defining (in SOM IDL) the interface to a class of objects, the class 
  8712.  implementor can decide, for each method, whether the SOM Compiler will 
  8713.  generate usage bindings that support name-lookup resolution for invoking the 
  8714.  method. Regardless of whether this is done, however, application programs 
  8715.  using the class can have SOM use either technique, on a per-method-call basis. 
  8716.  Chapter 3, "Using SOM Classes in Client Programs," describes how client 
  8717.  programs invoke methods. 
  8718.  
  8719.  
  8720. ΓòÉΓòÉΓòÉ 7.3.3. Dispatch-function resolution ΓòÉΓòÉΓòÉ
  8721.  
  8722. Dispatch-function resolution is the slowest, but most flexible, of the three 
  8723. method-resolution techniques. Dispatch functions permit method resolution to be 
  8724. based on arbitrary rules associated with the class of which the receiving 
  8725. object is an instance. Thus, a class implementor has complete freedom in 
  8726. determining how methods invoked on its instances are resolved. 
  8727.  
  8728. With both offset and name-lookup resolution, the net effect is the same--the 
  8729. method procedure that is ultimately selected is the one supported by the class 
  8730. of which the receiver is an instance. For example, if the receiver is an 
  8731. instance of class "Dog", then Dog's method procedure will be selected; but if 
  8732. the receiver is an instance of class "BigDog", then BigDog's method procedure 
  8733. will be selected. 
  8734.  
  8735. By contrast, dispatch-function resolution allows a class of instances to be 
  8736. defined such that the method procedure is selected using some other criteria. 
  8737. For example, the method procedure could be selected on the basis of the 
  8738. arguments to the method call, rather than on the receiver. For more information 
  8739. on dispatch-function resolution, see the description and examples for the 
  8740. somDispatch and somOverrideMTab methods in the SOMobjects Developer Toolkit: 
  8741. Programmers Reference Manual. 
  8742.  
  8743.  
  8744. ΓòÉΓòÉΓòÉ 7.3.4. Customizing Method Resolution ΓòÉΓòÉΓòÉ
  8745.  
  8746. Customizing method resolution requires the use of metaclasses that override 
  8747. SOMClass methods.  This is not recommended without use of the Cooperative 
  8748. Metaclass that guarantees correct operation of SOMobjects in conjunction with 
  8749. such metaclasses.  SOMobjects users who require this functionality should 
  8750. request access to the experimental Cooperative Metaclass used to implement the 
  8751. SOMobjects Metaclass Framework. Metaclasses implemented using the Cooperative 
  8752. Metaclass may have to be reprogrammed in the future when SOMobjects introduces 
  8753. an oficially supported Cooperative Metaclass. 
  8754.  
  8755.  
  8756. ΓòÉΓòÉΓòÉ 7.3.5. The four kinds of SOM methods ΓòÉΓòÉΓòÉ
  8757.  
  8758. SOM supports four different kinds of methods:  static methods, nonstatic 
  8759. methods, dynamic methods, and direct-call procedures. The following paragraphs 
  8760. explain these four method categories and the kinds of method resolution 
  8761. available for each. 
  8762. Static methods 
  8763.  
  8764. These are similar in concept to C++ virtual functions. Static methods are 
  8765. normally invoked using offset resolution via a method table, as described 
  8766. above, but all three kinds of method resolution are applicable to static 
  8767. methods. Each different static method available on an object is given a 
  8768. different slot in the object's method table. When SOMobjects Toolkit language 
  8769. bindings are used to implement a class, the SOM IDL method modifier can be 
  8770. specified to indicate that a given method is static; however, this modifier is 
  8771. rarely used since it is the default for SOM methods. 
  8772.  
  8773. Static methods introduced by a class can be overridden (redefined) by any 
  8774. descendant classes of the class. When SOMobjects language bindings are used to 
  8775. implement a class, the SOM IDL override modifier is specified to indicate that 
  8776. a class overrides a given inherited method. When a static method is resolved 
  8777. using offset resolution, it is not important which interface is accessing the 
  8778. method - the actual class of the object determines the method procedure that is 
  8779. selected. 
  8780.  
  8781. Note:  All SOM IDL modifiers are described in the topic "Modifier statements" 
  8782. in Chapter 4, "SOM IDL and the SOM Compiler." 
  8783. Nonstatic methods 
  8784.  
  8785. These methods are similar in concept to C++ nonstatic member functions (that 
  8786. is, C++ functions that are not virtual member functions and are not static 
  8787. member functions). Nonstatic methods are normally invoked using offset 
  8788. resolution, but all three kinds of method resolution are applicable  to 
  8789. nonstatic methods. When the SOMobjects language bindings are used to implement 
  8790. a class, the SOM IDL nonstatic modifier is used to indicate that a given method 
  8791. is nonstatic. 
  8792.  
  8793. Like static methods, nonstatic methods are given individual positions in method 
  8794. tables. However, nonstatic methods cannot be overridden. Instead, descendants 
  8795. of a class that introduces a nonstatic method can use the SOM IDL reintroduce 
  8796. modifier to "hide" the original nonstatic method with another (nonstatic or 
  8797. static) method of the same name. When a nonstatic method is resolved, selection 
  8798. of the specific method procedure is determined by the interface that is used to 
  8799. access the method. 
  8800. Dynamic methods 
  8801.  
  8802. These methods are not declared when specifying an object interface using IDL. 
  8803. Instead, they are registered with a class object at run time using the method 
  8804. somAddDynamicMethod. Because there is no way for SOM to know about dynamic 
  8805. methods before run time, offset resolution is not available for dynamic 
  8806. methods. Only name-lookup or dispatch-function resolution  can be used to 
  8807. invoke dynamic methods. Dynamic methods cannot be overridden. 
  8808. Direct-call procedures 
  8809.  
  8810. These are similar in concept to C++ static member functions. Direct-call 
  8811. procedures are not given positions in SOM method tables, but are accessed 
  8812. directly from a class's ClassData structure. Strictly speaking, none of the 
  8813. previous method-resolution approaches apply for invoking a direct-call 
  8814. procedure, although SOMobjects language bindings provide the same invocation 
  8815. syntax for direct-call procedures as for static or nonstatic methods. 
  8816. Direct-call procedures cannot be overridden, but they can be reintroduced. When 
  8817. SOMobjects language bindings are used to implement a class, the SOM IDL 
  8818. procedure modifier is used to indicate that a given method is a direct-call 
  8819. procedure. Note: Methods having the procedure modifier cannot be invoked 
  8820. remotely using DSOM. 
  8821.  
  8822.  
  8823. ΓòÉΓòÉΓòÉ 7.4. Implementing SOM Classes ΓòÉΓòÉΓòÉ
  8824.  
  8825. The interface to a class of objects contains the information that a client must 
  8826. know to use an object - namely, the signatures of its methods and the names of 
  8827. its attributes. The interface is described in a formal language independent of 
  8828. the programming language used to implement the object's methods. In SOM, the 
  8829. formal language used to define object interfaces is the Interface Definition 
  8830. Language (described in Chapter 4, "SOM IDL and the SOM Compiler"). 
  8831.  
  8832. The implementation of a class of objects  (that is, the procedures that 
  8833. implement the methods and the instance variables that store an object's state) 
  8834. is written in the implementor's preferred programming language. This language 
  8835. can be object-oriented (for instance, C++) or procedural (for instance, C). 
  8836.  
  8837. A completely implemented class definition, then, consists of two main files: 
  8838.  
  8839.    o  An IDL specification of the interface to instances of the class--the 
  8840.       interface definition file (or .idl file) and 
  8841.  
  8842.    o  Method procedures written in the implementor's language of choice--the 
  8843.       implementation file. 
  8844.  
  8845.  The SOM Compiler provides the link between those two files: To assist users in 
  8846.  implementing classes, the SOM Compiler produces a template implementation file 
  8847.  -- a type-correct guide for how the implementation of a class should look. 
  8848.  Then, the class implementor modifies this template file to fully implement the 
  8849.  class's methods.  That process is the subject of the remainder of this 
  8850.  chapter. 
  8851.  
  8852.  
  8853. ΓòÉΓòÉΓòÉ 7.5. The SOM Compiler ΓòÉΓòÉΓòÉ
  8854.  
  8855. The SOM Compiler translates the IDL definition of a SOM class into a set of 
  8856. "binding files" appropriate for the language that will implement the class's 
  8857. methods and the language(s) that will use the class. These bindings make it 
  8858. more convenient for programmers to implement and use SOM classes. The SOM 
  8859. Compiler currently produces binding files for the C and C++ languages. 
  8860.  
  8861. Important Note: C and C++ bindings can not both be generated during the same 
  8862. execution of the SOM compiler. 
  8863.  
  8864.  
  8865. ΓòÉΓòÉΓòÉ 7.5.1. Generating binding files ΓòÉΓòÉΓòÉ
  8866.  
  8867. The SOM Compiler operates in two phases: 
  8868.  
  8869.    o  A precompile phase, in which a precompiler analyzes an OIDL or IDL class 
  8870.       definition, and 
  8871.  
  8872.    o  An emission phase, in which one or more  emitter programs produce 
  8873.       binding files. 
  8874.  
  8875.  Each binding file is generated by a separate emitter program. Setting the 
  8876.  SMEMIT environment variable determines which emitters will be used, as 
  8877.  described below. Note: In the discussion below, the <filesystem> is determined 
  8878.  by default from the name of the source .idl file with the ".idl" extension 
  8879.  removed. Otherwise, a "filestem" modifier can be defined in the .idl file to 
  8880.  specify another file name (see "Modifier statements" above). 
  8881.  
  8882.  Note: If changes to definitions in the .idl file later become necessary, the 
  8883.  SOM Compiler should be rerun to update the current implementation template 
  8884.  file, provided that the c or xc emitter is specified (either with the -s 
  8885.  option or the SMEMIT environment variable, as described below). For more 
  8886.  information on generating updates, see "Running incremental updates of the 
  8887.  implementation template file" later in this chapter. 
  8888.  
  8889.  The emitters for the C language produce the following binding files: 
  8890.  
  8891.  <filestem>.c             (produced by the c emitter) 
  8892.  
  8893.                           This is a template for a C source program that 
  8894.                           implements a class's methods. This will become the 
  8895.                           primary source file for the class. (The other binding 
  8896.                           files can be generated from the .idl file as needed.) 
  8897.                           This template implementation file contains "stub" 
  8898.                           procedures for each method introduced or overridden 
  8899.                           by the class. (The stub procedures are empty of code 
  8900.                           except for required initialization and debugging 
  8901.                           statements.) 
  8902.  
  8903.                           After the class implementer has supplied the code for 
  8904.                           the method procedures, running the c emitter again 
  8905.                           will update the implementation file to reflect 
  8906.                           changes made to the class definition (in the .idl 
  8907.                           file). These updates include adding new stub 
  8908.                           procedures, adding comments, and changing method 
  8909.                           prototypes to reflect changes made to the method 
  8910.                           definitions in the IDL specification. Existing code 
  8911.                           within method procedures is not disturbed, however. 
  8912.  
  8913.                           The .c file contains an #include directive for the 
  8914.                           .ih file, described below. 
  8915.  
  8916.                           The contents of the C source template is controlled 
  8917.                           by the Emitter Framework file 
  8918.                           <SOMBASE>/include/ctm.efw. This file can be 
  8919.                           customized to change the template produced. For 
  8920.                           detailed information on changing the template file 
  8921.                           see the Emitter Framework Guide and Reference. 
  8922.  
  8923.  <filestem>.h             (produced by the h emitter) 
  8924.  
  8925.                           This is the header file to be included by C client 
  8926.                           programs (programs that use the class). It contains 
  8927.                           the C usage bindings for the class, including macros 
  8928.                           for accessing the class's methods and a macro for 
  8929.                           creating new instances of the class. This header file 
  8930.                           includes the header files for the class's parent 
  8931.                           classes and its metaclass, as well as the header file 
  8932.                           that defines SOM's generic C bindings, som.h. 
  8933.  
  8934.  <filestem>.ih            (produced by the ih emitter) 
  8935.  
  8936.                           This is the header file to be included in the 
  8937.                           implementation file (the file that implements the 
  8938.                           class's methods--the .c file). It contains the 
  8939.                           implementation bindings for the class, including: 
  8940.  
  8941.    o  a struct defining the class's instance variables, 
  8942.    o  macros for accessing instance variables, 
  8943.    o  macros for invoking parent methods the class overrides, 
  8944.    o  the <className>GetData  macro used by the method procedures in the 
  8945.       <filestem>.c file (see "Stub procedures for methods" in Section 5.4 of 
  8946.       Chapter 5.) 
  8947.    o  a <className>NewClass procedure for constructing the class object at run 
  8948.       time, and 
  8949.    o  any IDL types and constants defined in the IDL interface. 
  8950.  
  8951.  The emitters for the C++ language produce the following binding files: 
  8952.  
  8953.  <filestem>.C (for AIX) or  <filestem>.cpp (for OS/2) (produced by the xc 
  8954.                           emitter) 
  8955.  
  8956.                           This is a template for a C++ source program that 
  8957.                           implements a class's methods. This will become the 
  8958.                           primary source file for the class. (The other binding 
  8959.                           files can be generated from the .idl file as needed.) 
  8960.                           This template implementation file contains "stub" 
  8961.                           procedures for each method introduced or overridden 
  8962.                           by the class. (The stub procedures are empty of code 
  8963.                           except for required initialization and debugging 
  8964.                           statements.) 
  8965.  
  8966.                           After the class implementer has supplied the code for 
  8967.                           the method procedures, running the xc emitter again 
  8968.                           will update this file to reflect changes made to the 
  8969.                           class definition (in the .idl file). These updates 
  8970.                           include adding new stub procedures, adding comments, 
  8971.                           and changing method prototypes to reflect changes 
  8972.                           made to the method definitions in the IDL 
  8973.                           specification. Existing code within method procedures 
  8974.                           is not disturbed, however. 
  8975.  
  8976.                           The C++ implementation file contains an #include 
  8977.                           directive for the .xih file, described below. 
  8978.  
  8979.                           The contents of the C++ source template is controlled 
  8980.                           by the Emitter Framework file 
  8981.                           <SOMBASE>/include/ctm.efw. This file can be 
  8982.                           customized to change the template produced. For 
  8983.                           detailed information on changing the template file 
  8984.                           see the Emitter Framework Guide and Reference. 
  8985.  
  8986.  <filestem>.xh            (produced by the xh emitter) 
  8987.  
  8988.                           This is the header file to be included by C++ client 
  8989.                           programs that use the class. It contains the usage 
  8990.                           bindings for the class, including a C++ definition of 
  8991.                           the class, macros for accessing the class's methods, 
  8992.                           and the new operator for creating new instances of 
  8993.                           the class. This header file includes the header files 
  8994.                           for the class's parent classes and its metaclass, as 
  8995.                           well as the header file that defines SOM's generic 
  8996.                           C++ bindings, som.xh. 
  8997.  
  8998.  <filestem>.xih           (produced by the xih emitter) 
  8999.  
  9000.                           This is the header file to be included in the 
  9001.                           implementation file (the file that implements the 
  9002.                           class's methods). It contains the implementation 
  9003.                           bindings for the class, including: 
  9004.  
  9005.    o  a struct defining the class's instance variables, 
  9006.    o  macros for accessing instance variables, 
  9007.    o  macros for invoking parent methods the class overrides, 
  9008.    o  the <className>GetData  macro (see section 4.7), 
  9009.    o  a <className>NewClass procedure for constructing the class object at run 
  9010.       time, and 
  9011.    o  any IDL types and constants defined in the IDL interface. 
  9012.  
  9013.  Other files the SOM Compiler generates: 
  9014.  
  9015.  <filestem>.hh            (produced by the hh emitter) 
  9016.  
  9017.                           This file is a DirectToSOM C++ header file that 
  9018.                           describes a SOMobjects class in a way appropriate to 
  9019.                           DTS C++. When running this emitter, you must include 
  9020.                           the noqualitytypes command-line modifier for the -m 
  9021.                           option of the SOM Compiler command sc or somc. 
  9022.  
  9023.  <filestem>pdl            (produced by the pdl emitter) This file is the same 
  9024.                           as the .idl file from which it is produced except 
  9025.                           that all items within the .idl file that are marked 
  9026.                           as "private" have been removed.  (an item is marked 
  9027.                           as private by surrounding it with "#ifdef_PRIVATE_" 
  9028.                           and "#endif" directives.  Thus, the pdl (Public 
  9029.                           Definition Language) emitter can be used to generate 
  9030.                           a "public" version of the .idl file. 
  9031.  
  9032.  <filestem>.def (for OS/2) (produced by the def emitter) 
  9033.  
  9034.                           This file is used by the linker to package a class as 
  9035.                           a library. To combine several classes into a single 
  9036.                           library, you must merge the exports statements from 
  9037.                           each of their .def  files into a single .def file for 
  9038.                           the entire library. When packaging multiple classes 
  9039.                           in a single library, you must also write a simple C 
  9040.                           procedure named SOMInitModule and add it to the 
  9041.                           export list. This procedure should call the routine 
  9042.                           <className>NewClass for each class packaged in the 
  9043.                           library. The SOMInitModule procedure is called by the 
  9044.                           SOM Class Manager when the library is dynamically 
  9045.                           loaded. 
  9046.  
  9047.  <filestem>.exp  (for AIX) (produced by the exp emitter) 
  9048.  
  9049.                           This file is used by the linker to package a class as 
  9050.                           a library. To combine several classes into a single 
  9051.                           library, you must merge the exports statements from 
  9052.                           each of their .exp  files into a single .exp file for 
  9053.                           the entire library. When packaging multiple classes 
  9054.                           in a single library, you must also write a simple C 
  9055.                           procedure named SOMInitModule and add it to the 
  9056.                           export list. This procedure should call the routine 
  9057.                           <className>NewClass for each class packaged in the 
  9058.                           library The SOMInitModule procedure is called by the 
  9059.                           SOM Class Manager when the library is dynamically 
  9060.                           loaded. 
  9061.  
  9062.  The Interface Repository (produced by the ir emitter) 
  9063.  
  9064.                           See Chapter 7 for a discussion on the Interface 
  9065.                           Repository. 
  9066.  Note: The C/C++ bindings generated by the SOM Compiler have the following 
  9067.  limitation: If two classes named "ClassName" and "ClassNameC" are defined, the 
  9068.  bindings for these two classes will clash. That is, if a client program uses 
  9069.  the C/C++ bindings (includes the .h/.xh header file) for both classes, a name 
  9070.  conflict will occur. Thus, class implementers should keep this limitation in 
  9071.  mind when naming their classes. 
  9072.  
  9073.  SOM users can extend the SOM Compiler to generate additional files by writing 
  9074.  their own emitters. To assist users in extending the SOM Compiler, SOM 
  9075.  provides an Emitter Framework a collection of classes and methods useful for 
  9076.  writing object-oriented emitters that the SOM Compiler can invoke. For more 
  9077.  information, see the Emitter Framework Guide and Reference. 
  9078.  
  9079.  Note re:  porting SOM classes: The header files (binding files) that the SOM 
  9080.  Compiler generates will only work on the platform (operating system) on which 
  9081.  they were generated. Thus, when porting SOM classes from the platform where 
  9082.  they were developed to another platform, the header files must be regenerated 
  9083.  from the .idl file by the SOM Compiler on that target platform. 
  9084.  
  9085.  
  9086. ΓòÉΓòÉΓòÉ 7.5.2. Environment variables affecting the SOM Compiler ΓòÉΓòÉΓòÉ
  9087.  
  9088. To execute the SOM Compiler on one or more files that contain IDL 
  9089. specifications for one or more classes, use the command: 
  9090.  
  9091. sc [-options] files 
  9092.  
  9093. where "files" specifies one or more .idl files. 
  9094.  
  9095. Available "-options" for the command are detailed in the next topic. The 
  9096. operation of the SOM Compiler (whether it produces C binding files or C++ 
  9097. binding files, for example) is also controlled by a set of environment 
  9098. variables that can be set before the sc command is issued. The applicable 
  9099. environment variables are as follows: 
  9100.  
  9101.  SMEMIT              Determines which output files the SOM Compiler produces. 
  9102.                      Its value consists of a list of items separated by 
  9103.                      semicolons for OS/2, or by semicolons or colons for AIX. 
  9104.                      Each item designates an emitter to execute.  For example, 
  9105.                      the statement: 
  9106.  
  9107.       SET SMEMIT=c;h;ih        (for OS/2, for C binding files) 
  9108.       SET SMEMIT=xc;xh;xih     (for OS/2, for C++ binding files) 
  9109.       export SMEMIT=c;h;ih     (for AIX) 
  9110.  
  9111.                      directs the SOM Compiler to produce the C binding files 
  9112.                      "hello.c", "hello.h", and"hello.ih" from the "hello.idl" 
  9113.                      input specification. By comparison, 
  9114.  
  9115.       SET SMEMIT=xc;xh;xih     (for OS/2) 
  9116.       export SMEMIT=xc;xh;xih  (for AIX) 
  9117.  
  9118.                      directs the SOM Compiler to produce C++ binding files 
  9119.                      "hello.C" (for AIX) or "hello.cpp" (for OS/2), "hello.xh", 
  9120.                      and "hello.xih" from the "hello.idl" input specification. 
  9121.  
  9122.                      By default, all output files are placed in the same 
  9123.                      directory as the input file. If the SMEMIT environment 
  9124.                      variable is not set, then a default value of "h;ih" is 
  9125.                      assumed. 
  9126.  
  9127.                      Windows note: The SMEMIT environmental variable can be set 
  9128.                      by using the SET command before the somc command is 
  9129.                      issued.  For example: 
  9130.  
  9131.                                             SET SMEMIT="c;h;ih"             (for Windows)
  9132.  
  9133.                      If you are running the SOM Compiler from a DOS box under 
  9134.                      Windows, make sure to define SMEMIT before Windows is 
  9135.                      started. 
  9136.  
  9137.  SMINCLUDE           Specifies where the SOM Compiler should look for .idl 
  9138.                      files #included by the .idl file being compiled. Its value 
  9139.                      should be one or more directory names separated by a 
  9140.                      semicolon when using OS/2, or separated by a semicolon or 
  9141.                      colon when using AIX. Directory names can be specified 
  9142.                      with absolute or relative pathnames. For example: 
  9143.  
  9144.       SET SMINCLUDE=.;..\MYSCDIR;C:\TOOLKT20\C\INCLUDE; (for OS/2 or Windows) 
  9145.  
  9146.       export SMINCLUDE=.:myscdir:/u/som/include (for AIX) 
  9147.  
  9148.                      The default value of the SMINCLUDE environment variable is 
  9149.                      the "include" subdirectory of the directory into which SOM 
  9150.                      has been installed. 
  9151.  
  9152.  SMTMP               Specifies the directory that the SOM Compiler should use 
  9153.                      to hold intermediate output files. This directory should 
  9154.                      not coincide with the directory of the input or output 
  9155.                      files. For AIX, the default setting of SMTMP is /tmp; for 
  9156.                      OS/2, the default setting of SMTMP is the root directory 
  9157.                      of the current drive. 
  9158.  
  9159.                      OS/2 or Windows example: 
  9160.  
  9161.                                              SET SMTMP=..\MYSCDIR\GARBAGE
  9162.  
  9163.                      tells the SOM Compiler to place the temporary files in the 
  9164.                      GARBAGE directory.  Or, on OS/2 only: 
  9165.  
  9166.                                              SET SMTMP=%TMP%
  9167.  
  9168.                      tells the SOM Compiler to use the same directory for 
  9169.                      temporary files as given by the setting of the TMP 
  9170.                      environment variable (the default location for temporary 
  9171.                      system files). (On Windows, you cannot set one variable to 
  9172.                      another.) 
  9173.  
  9174.                      AIX example: 
  9175.  
  9176.                                              export SMTMP=$TMP
  9177.                                              export SMTMP=../myscdir/garbage
  9178.  
  9179.  SMKNOWNEXTS         Specifies additional emitters to which the SOM Compiler 
  9180.                      should add a header. For example, if you were to write a 
  9181.                      new emitter for Pascal, called "emitpas", then by default 
  9182.                      the SOM Compiler would not add any header comments to it. 
  9183.                      However, by setting SMKNOWNEXTS=pas, as shown: 
  9184.  
  9185.       set SMKNOWNEXTS=pas      (for OS/2 or Windows) 
  9186.  
  9187.       export SMKNOWNEXTS=pas   (for AIX) 
  9188.  
  9189.                      the SOM Compiler will add a header to files generated with 
  9190.                      the "emitpas" emitter. The "header" added is a SOM 
  9191.                      Compiler-generated message plus any comments, such as 
  9192.                      copyright statements, that appear at the head of your .idl 
  9193.                      input file. For details on writing your own emitter, see 
  9194.                      the Emitter Framework Guide and Reference. 
  9195.  
  9196.  SOMIR               Specifies the name (or list of names) of the Interface 
  9197.                      Repository file. The ir emitter, if run, creates the 
  9198.                      Interface Repository, or checks it for consistency if it 
  9199.                      already exists. If the -u option is specified when 
  9200.                      invoking the SOM Compiler, the ir emitter also updates an 
  9201.                      existing Interface Repository. 
  9202.  
  9203.  
  9204. ΓòÉΓòÉΓòÉ 7.5.3. Running the SOM Compiler ΓòÉΓòÉΓòÉ
  9205.  
  9206. The syntax of the command for running the SOM Compiler takes the forms: 
  9207.  
  9208. sc  [-options] files  somc[-options] files 
  9209.  
  9210. The "files" specified in the sc or somc command denote one or more files 
  9211. containing the IDL class definitions to be compiled. If no extension is 
  9212. specified, .idl is assumed. By default, the <filestem> of the .idl file 
  9213. determines the filestem of each emitted file. Otherwise, a "filestem" modifier 
  9214. can be defined in the .idl file to specify another name (see "Modifier 
  9215. statements" discussed earlier). 
  9216.  
  9217. Selected "-options" can be specified individually, as a string of option 
  9218. characters, or as a combination of both. Any option that takes an argument 
  9219. either must be specified individually or must appear as the final option in a 
  9220. string of option characters. Available options and their purposes are as 
  9221. follows: 
  9222.  
  9223.  -C n        Sets the maximum allowable size for a simple comment in the .idl 
  9224.              file (default: 32767). This is only needed for very large single 
  9225.              comments. 
  9226.  
  9227.  -D name[=def] Defines name as in a #define directive. The default def is 1. 
  9228.              This option is the same as the -D option for the C compiler. Note: 
  9229.              This option can be used to define __PRIVATE__ so that the SOM 
  9230.              Compiler will also compile any methods and attributes that have 
  9231.              been defined as private using the directive  #ifdef__PRIVATE__; 
  9232.              however, the -p option does the same thing more easily. 
  9233.  
  9234.  -E variable=value Sets an environment variable. (See the previous topic for a 
  9235.              discussion of the available environment variables: SMEMIT, 
  9236.              SMINCLUDE, SMTMP, and SMNOIR.) 
  9237.  
  9238.  -I dir      When looking for #included files, looks first in dir, then in the 
  9239.              standard directories (same as the C compiler -I option). 
  9240.  
  9241.  -S n        Sets the total allowable amount of unique string space used in the 
  9242.              IDL specification for names and passthru lines (default: 32767). 
  9243.              This is only needed for very large .idl files. 
  9244.  
  9245.  -U name     Removes any initial definition (via a #define preprocessor 
  9246.              directive) of symbol name. 
  9247.  
  9248.  -V          Displays version information about the SOM Compiler. 
  9249.  
  9250.  -c          Turns off comment processing. This allows comments to appear 
  9251.              anywhere within an IDL specification (rather than in restricted 
  9252.              places), and it causes comments not to be transferred to the 
  9253.              output files that the SOM Compiler produces. 
  9254.  
  9255.  -d  directory Specifies a directory where all output files should be placed. 
  9256.              If the -d option is not used, all output files are placed in the 
  9257.              same directory as the input file. 
  9258.  
  9259.  -h or -?    Produces a listing of this option list. (This option is typically 
  9260.              used in an sc or somc command that does not include a .idl file 
  9261.              name) 
  9262.  
  9263.  -i filename Specifies the name of the class definition file. Use this option 
  9264.              to override the built-in assumption that the input file will have 
  9265.              a .idl extension. Any filename supplied with the -i option is used 
  9266.              exactly as it is specified. 
  9267.  
  9268.  -m name[=value] Adds a global modifier. The currently supported global 
  9269.              modifiers are as follows: 
  9270.  
  9271.       addprefixes    Adds `functionprefixes' to the method procedure prototypes 
  9272.                      during an incremental update of the implementation 
  9273.                      template file. This option applies only when rerunning the 
  9274.                      c or xc emitter on an IDL file that previously did not 
  9275.                      specify a functionprefix. A class implementor who later 
  9276.                      decides to use prefixes should add a line in the 
  9277.                      `implementation' section of the .idl file containing the 
  9278.                      specification: 
  9279.  
  9280.                      functionprefix = prefix 
  9281.  
  9282.                      (as described earlier in the topic "Modifier statements") 
  9283.                      and then rerun the c or xc emitter using the -maddprefixes 
  9284.                      option. The method procedure prototypes in the 
  9285.                      implementation file will then be updated so that each 
  9286.                      method name includes the assigned prefix. (This option 
  9287.                      does not support changes to existing prefix names, nor 
  9288.                      does it apply for OIDL files.) 
  9289.  
  9290.       addstar        This option causes all interface references to have a `*' 
  9291.                      added to them for the C bindings. See the earlier section 
  9292.                      entitled "Class types" for further details. 
  9293.  
  9294.       comment=comment string where comment string can be either of the 
  9295.                      designations: "/*"  or "//". This option indicates that 
  9296.                      comments marked in the designated manner in the .idl file 
  9297.                      are to be completely ignored by the SOM Compiler and will 
  9298.                      not be included in the output files.  Note: Comments on 
  9299.                      lines beginning with "//#" are always ignored by the SOM 
  9300.                      Compiler. 
  9301.  
  9302.       corba          This option directs the SOM Compiler to compile the input 
  9303.                      definition according to strict CORBA-defined IDL syntax. 
  9304.                      This means, for example, that comments may appear anywhere 
  9305.                      and that pointers are not allowed. When the -mcorba option 
  9306.                      is used, parts of a .idl file surrounded by 
  9307.                      #ifdef__SOMIDL__ and #endif directives are ignored. This 
  9308.                      option can be used to determine whether all nonstandard 
  9309.                      constructs (those specific to SOM IDL) are properly 
  9310.                      protected by #ifdef__SOMIDL__ and #endif directives. 
  9311.  
  9312.       -mname[=value] (modifier options continued from the previous page) 
  9313.  
  9314.       csc            This option forces the OIDL compiler to be run. This is 
  9315.                      required only if you want to compile an OIDL file that 
  9316.                      does not have an extension of .csc or .sc. 
  9317.  
  9318.       emitappend     This option causes emitted files to be appended at the end 
  9319.                      of existing files of the same name. 
  9320.  
  9321.       noheader       This option ensures that the SOM Compiler does not add a 
  9322.                      header to the beginning of an emitted file. 
  9323.  
  9324.       noint          This option directs the SOM Compiler not to warn about the 
  9325.                      portability problems of using int's in the source. 
  9326.  
  9327.       nolock         This option causes the Interface Repository Emitter emitir 
  9328.                      (see Chapter 7, "Interface Repository Framework") to leave 
  9329.                      the IR unlocked when updates are made to it. This can 
  9330.                      improve performance on networked file systems. By not 
  9331.                      locking the IR, however, there is the risk of multiple 
  9332.                      processes attempting to write to the same IR, with 
  9333.                      unpredictable results. This option should only be used 
  9334.                      when you know that only one process is updating an IR at 
  9335.                      once. 
  9336.  
  9337.       nopp           This option directs the SOM Compiler not to run the SOM 
  9338.                      preprocessor on the .idl input file. 
  9339.  
  9340.       noqualifytypes This option prevents the use od C-scoped names in emitter 
  9341.                      output, and is used in conjunction with the .hh emitter. 
  9342.  
  9343.       notc           This option directs the SOM Compiler not to create 
  9344.                      TypeCode information when emitting files. This is required 
  9345.                      only when the .idl files contain some undeclared types. 
  9346.                      This option is typically used when compiling converted 
  9347.                      .csc files that have not had typing information added. 
  9348.  
  9349.       nouseshort     This option directs the SOM Compiler not to generate short 
  9350.                      forms for type names in the .h and .xh public header 
  9351.                      files. This can be useful to save disk space. 
  9352.  
  9353.       pp=preprocessor This option directs the SOM Compiler to use the specified 
  9354.                      preprocessor as the SOM preprocessor, rather than the 
  9355.                      default "somcpp". Any standard C/C++ preprocessor can be 
  9356.                      used as a preprocessor for IDL specifications. 
  9357.  
  9358.       tcconsts       This option directs the SOM Compiler to generate TypeCode 
  9359.                      constants in the h and .xh public header files. Please 
  9360.                      refer to the Interface Repository (described in Chapter 7) 
  9361.                      for more details. 
  9362.  
  9363.  Note: All command-line -m modifier options can be specified in the environment 
  9364.  by changing them to UPPERCASE and prepending "SM" to them. For example, if you 
  9365.  want to always set the options "-mnotc" and "-maddstar", set corresponding 
  9366.  environment variables as follows: 
  9367.  
  9368.    On OS/2: 
  9369.  
  9370.           set SMNOTC=1
  9371.           set SMADDSTAR=1
  9372.  
  9373.    On AIX: 
  9374.  
  9375.           export SMNOTC=1
  9376.           export SMADDSTAR=1
  9377.  
  9378.  -p          Causes the "private" sections of the IDL file to be included in 
  9379.              the compilation (that is, sections preceded by #ifdef __PRIVATE__ 
  9380.              that contain private methods and attributes). Note: The -p option 
  9381.              is equivalent to the earlier option -D__PRIVATE__. 
  9382.  
  9383.  -r          Checks that all names specified in the release order statement are 
  9384.              valid method names (default: FALSE). 
  9385.  
  9386.  -s string   Substitutes string in place of the contents of the SMEMIT 
  9387.              environment variable for the duration of the current sc command. 
  9388.              This determines which emitters will be run and, hence, which 
  9389.              output files will be produced. (If a list of values is given, on 
  9390.              OS/2 only the list must be enclosed in double quotes.) 
  9391.  
  9392.              The -s option is a convenient way to override the SMEMIT 
  9393.              environment variable. In OS/2 for example, the command: 
  9394.  
  9395.                              > SC -s"h;c" EXAMPLE
  9396.  
  9397.              is equivalent to the following sequence of commands: 
  9398.  
  9399.                              > SET OLDSMEMIT=%SMEMIT%
  9400.                              > SET SMEMIT=H;C
  9401.                              > SC EXAMPLE
  9402.                              > SET SMEMIT=%OLDSMEMIT%
  9403.  
  9404.              Similarly, in AIX the command: 
  9405.  
  9406.                              > sc -sh";"c example
  9407.  
  9408.              is equivalent to the following sequence of commands: 
  9409.  
  9410.                              > export OLDSMEMIT=$SMEMIT
  9411.                              > export SMEMIT=h";"c
  9412.                              > sc example
  9413.                              > export SMEMIT=$OLDSMEMIT
  9414.  
  9415.  -u          Updates the Interface Repository (default: no update). With this 
  9416.              option, the Interface Repository will be updated even if the ir 
  9417.              emitter is not explicitly requested in the SMEMIT environment 
  9418.              variable or the -s option. 
  9419.  
  9420.  -v          Uses verbose mode to display informational messages (default: 
  9421.              FALSE). This option is primarily intended for debugging purposes 
  9422.              and for writers of emitters. 
  9423.  
  9424.  -w          Suppresses warning messages (default: FALSE). 
  9425.  
  9426.  The following sample commands illustrate various options for the sc command or 
  9427.  similarly with somc): 
  9428.  
  9429.  sc -sc hello.idl         Generates file "hello.c". 
  9430.  
  9431.  sc -hV                   Generates a help message and displays the version of 
  9432.                           the SOM Compiler currently available. 
  9433.  
  9434.  sc -vsh";"ih hello.idl   Generates "hello.h" and "hello.ih" with informational 
  9435.                           messages. 
  9436.  
  9437.  sc -sxc -doutdir hello.idl Generates "hello.xc" in directory "outdir". 
  9438.  
  9439.  
  9440. ΓòÉΓòÉΓòÉ 7.6. The `pdl' Facility ΓòÉΓòÉΓòÉ
  9441.  
  9442. As discussed earlier in this chapter, the SOM Compiler provides a pdl (Public 
  9443. Definition Language) emitter. This emitter generates a file that is the same as 
  9444. the .idl file from which it is produced, except that it removes all items 
  9445. within the .idl file that are marked as "private." (An item is marked as 
  9446. private by surrounding it with "#ifdef__PRIVATE__" and "#endif" directives.) 
  9447. Thus, the pdl emitter can be used to generate a "public" version of a .idl 
  9448. file.  (Generally, client programs will need only the "public" methods and 
  9449. attributes.) 
  9450.  
  9451. The SOMobjects Toolkit also provides a separate program, pdl, which performs 
  9452. the same function, but can be invoked independently of the SOM Compiler. The 
  9453. pdl program is invoked as follows: 
  9454.  
  9455.        pdl  files 
  9456.  
  9457.  where "files" specifies one or more .idl files whose "PRIVATE" sections are to 
  9458.  be removed. Filenames must be completely specified (with the .idl extension). 
  9459.  
  9460.  The pdl command supports the following options.  (Selected options can be 
  9461.  specified individually, as a string of option characters, or as a combination 
  9462.  of both. Any option that takes an argument either must be specified 
  9463.  individually or must appear as the final option in a string of option 
  9464.  characters.) 
  9465.  
  9466.  -d dir      Specifies a directory in which the output files are to be placed. 
  9467.              (The output files are given the same name as the input files.) If 
  9468.              no directory is specified, the output files are named 
  9469.              <fileStem>.pdl (where fileStem is the file stem of the input file) 
  9470.              and are placed in the current working directory. 
  9471.  
  9472.  -f          Specifies that output files are to replace existing files with the 
  9473.              same name, even if the existing files are read-only. By default, 
  9474.              files are replaced only if they have write access. 
  9475.  
  9476.  -s smemit   Specifies that, for each specified .idl file, the pdl program is 
  9477.              to invoke the SOM Compiler with smemit as the value of the -s 
  9478.              option. 
  9479.  
  9480.  -c cmd      Specifies that, for each .idl file, the pdl program is to run the 
  9481.              specified system command. This command may contain a single 
  9482.              occurrence of the string "%s", which will be replaced with the 
  9483.              source file name before the command is executed. For example the 
  9484.              option -c"sc -sh %s" has the same effect as using the option -sh. 
  9485.  
  9486.  For example, to install public versions of the .idl files in the directory 
  9487.  "pubinclude", type: 
  9488.  
  9489.      pdl -d pubinclude *.idl
  9490.  
  9491.  
  9492. ΓòÉΓòÉΓòÉ 7.7. Implementing SOM Classes ΓòÉΓòÉΓòÉ
  9493.  
  9494. The IDL specification for a class defines only the interface to the class's 
  9495. instances. The implementation of those objects (the procedures that perform 
  9496. their methods) is defined in an implementation file. To assist users in 
  9497. implementing classes, the SOM Compiler  produces a template implementation 
  9498. file--a type-correct guide for how the implementation of a class should look. 
  9499. The class implementer then modifies this template to implement the class's 
  9500. methods. 
  9501.  
  9502. The SOM Compiler can also update the implementation file to reflect changes 
  9503. subsequently made to a class's interface definition file (the .idl file). These 
  9504. incremental updates include adding new stub procedures, adding comments, and 
  9505. changing method prototypes to reflect changes made to the method definitions in 
  9506. the IDL specification. These updates to the implementation file, however, do 
  9507. not disturb existing code in the method procedures. These updates are discussed 
  9508. further in "Running incremental updates of the implementation template file" 
  9509. later in this section. 
  9510.  
  9511. For C programmers, the SOM Compiler generates a <filestem>.c file. For C++ 
  9512. programmers, the SOM Compiler generates a <filestem>.C  file (for AIX) or a 
  9513. <filestem>.cpp file (for OS/2). To specify whether the SOM Compiler should 
  9514. generate a C or C++ implementation template, set the value of the SMEMIT 
  9515. environment variable, or use the -s option when running the SOM Compiler. (See 
  9516. "The SOM Compiler" in Chapter 4, "SOM IDL and the SOM Compiler.") 
  9517.  
  9518. Note:  As this chapter describes, a SOM class can be implemented by using C++ 
  9519.        to define the instance variables introduced by the class and to define 
  9520.        the procedures that implement the overridden and introduced methods of 
  9521.        the class. Be aware, however, that the C++ class defined by the C++ 
  9522.        usage bindings for a SOM class (described in Chapter 3) cannot be 
  9523.        subclassed in C++ to create new C++ or SOM classes.  The reason why the 
  9524.        C++ implementation of a SOM class involves the definition of C++ 
  9525.        procedures (not C++ methods) to support SOM methods is that there is no 
  9526.        language-neutral way to call a C++ method. Only C++  code can call C++ 
  9527.        methods, and this calling code must be generated by the same compiler 
  9528.        that generates the method code. In contrast, the method procedures that 
  9529.        implement SOM methods must be callable from any language, without 
  9530.        knowledge on the part of the object client as to which language is used 
  9531.        to implement the resolved method procedure. 
  9532.  
  9533.  
  9534. ΓòÉΓòÉΓòÉ 7.7.1. The implementation template ΓòÉΓòÉΓòÉ
  9535.  
  9536. Consider the following IDL description of the "Hello" class: 
  9537.  
  9538.    #include <somobj.idl>
  9539.  
  9540.    interface Hello : SOMObject
  9541.    {
  9542.        void sayHello();
  9543.        // This method outputs the string "Hello, World!".
  9544.    };
  9545.  
  9546. From this IDL description, the SOM Compiler generates the following C 
  9547. implementation template, hello.c (a C++ implementation template, hello.C or 
  9548. hello.cpp, is identical except that the #included file is <hello.xih> rather 
  9549. than <hello.ih>): 
  9550.  
  9551.    #define Hello_Class_Source
  9552.    #include <hello.ih>
  9553.  
  9554.    /*
  9555.     *  This method outputs the string "Hello, World!".
  9556.     */
  9557.  
  9558.    SOM_Scope void   SOMLINK sayHello(Hello somSelf, Environment *ev)
  9559.    {
  9560.        /* HelloData *somThis = HelloGetData(somSelf); */
  9561.        HelloMethodDebug("Hello","sayHello");
  9562.    }
  9563.  
  9564. The first line defines the "Hello_Class_Source" symbol, which is used in the 
  9565. SOM-generated implementation header files for C to determine when to define 
  9566. various functions, such as "HelloNewClass."  For interfaces defined within a 
  9567. module, the directive "#define <className>_Class_Source" is replaced by the 
  9568. directive "#define SOM_Module_<moduleName>_Source". 
  9569.  
  9570. The second line (#include <hello.ih> for C, or #include <hello.xih> for C++) 
  9571. includes the SOM-generated implementation header file. This file defines a 
  9572. struct holding the class's instance variables, macros for accessing instance 
  9573. variables, macros for invoking parent methods, and so forth. 
  9574. Stub procedures for methods 
  9575.  
  9576. For each method introduced or overridden by the class, the implementation 
  9577. template includes a stub procedure--a procedure that is empty except for an 
  9578. initialization statement, a debugging statement, and possibly a return 
  9579. statement. The stub procedure for a method is preceded by any comments that 
  9580. follow the method's declaration in the IDL specification. 
  9581.  
  9582. For method "sayHello" above, the SOM Compiler generates the following prototype 
  9583. of the stub procedure: 
  9584.  
  9585.    SOM_Scope void SOMLINK sayHello(Hello somSelf, Environment *ev)
  9586.  
  9587. The "SOM_Scope" symbol is defined in the implementation header file as either 
  9588. "extern" or "static," as appropriate. The term "void" signifies the return type 
  9589. of method "sayHello". The "SOMLINK" symbol is defined by SOM; it represents the 
  9590. keyword needed to link to the C or C++ compiler, and its value is 
  9591. system-specific. Using the "SOMLINK" symbol allows the code to work with a 
  9592. variety of compilers without modification. 
  9593.  
  9594. Following the "SOMLINK" symbol is the name of the procedure that implements the 
  9595. method. If no functionprefix modifier has been specified for the class, then 
  9596. the procedure name is the same as the method name. If a functionprefix modifier 
  9597. is in effect, then the procedure name is generated by prepending the specified 
  9598. prefix to the method name. For example, if the class definition contained the 
  9599. following statement: 
  9600.  
  9601.    functionprefix = xx_;
  9602.  
  9603. then the prototype of the stub procedure for method "sayHello" would be: 
  9604.  
  9605.    SOM_Scope void SOMLINK xx_sayHello(Hello somSelf, Environment *ev)
  9606.  
  9607. The functionprefix can not be 
  9608.  
  9609.    <classname>_
  9610.  
  9611. since this is used in method invocation macros defined by the C usage bindings. 
  9612.  
  9613. Following the procedure name is the formal parameter list for the method 
  9614. procedure. Because each SOM method always receives at least one argument (a 
  9615. pointer to the SOM object that responds to the method), the first parameter 
  9616. name in the prototype of each stub procedure is called somSelf. (The macros 
  9617. defined in the implementation header file rely on this convention.) The somSelf 
  9618. parameter is a pointer to an object that is an instance of the class being 
  9619. implemented (here, class "Hello") or an instance of a class derived from it. 
  9620.  
  9621. Unless the IDL specification of the class included the callstyle=oidl modifier, 
  9622. then the formal parameter list will include one or two additional parameters 
  9623. before the parameters declared in the IDL specification: an (Environment *ev) 
  9624. input/output parameter, which permits the return of exception information, and, 
  9625. if the IDL specification of the method includes a context specification, a 
  9626. (Context *ctx) input parameter. These parameters are prescribed by the CORBA 
  9627. standard. For more information on using the Environment  and Context 
  9628. parameters, see the section entitled "Exceptions and error handling" in Chapter 
  9629. 3, "Using SOM Classes in Client Programs," and the book The Common Object 
  9630. Request Broker: Architecture and Specification, published by Object Management 
  9631. Group and X/Open. 
  9632.  
  9633. The first statement in the stub procedure for method "sayHello" is the 
  9634. statement: 
  9635.  
  9636.    /* HelloData *somThis = HelloGetData(somSelf); */
  9637.  
  9638. This statement is enclosed in comments only when the class does not introduce 
  9639. any instance variables. The purpose of this statement, for classes that do 
  9640. introduce instance variables, is to initialize a local variable (somThis) that 
  9641. points to a structure representing the instance variables introduced by the 
  9642. class. The somThis pointer is used by the macros defined in the "Hello" 
  9643. implementation header file to access those instance variables. (These macros 
  9644. are described below.)  In this example, the "Hello" class introduces no 
  9645. instance variables, so the statement is commented out. If instance variables 
  9646. are later added to a class that initially had none, then the comment characters 
  9647. can be removed if access to the variable is required. 
  9648.  
  9649. The "HelloData" type and the "HelloGetData" macro used to initialize the 
  9650. somThis pointer are defined in the implementation header file. Within a method 
  9651. procedure, class implementers can use the somThis pointer to access instance 
  9652. data, or they can use the convenience macros defined for accessing each 
  9653. instance variable, as described below. 
  9654.  
  9655. To implement a method so that it can modify a local copy of an object's 
  9656. instance data without affecting the object's real instance data, declare a 
  9657. variable of type <className>Data (for example, "HelloData") and assign to it 
  9658. the structure that somThis points to; then make the somThis pointer point to 
  9659. the copy. For example: 
  9660.  
  9661.    HelloData myCopy = *somThis;
  9662.    somThis = &myCopy;
  9663.  
  9664. Next in the stub procedure for method "sayHello" is the statement: 
  9665.  
  9666.    HelloMethodDebug("Hello", "sayHello");
  9667.  
  9668. This statement facilitates debugging. The "HelloMethodDebug" macro is defined 
  9669. in the implementation header file. It takes two arguments, a class name and a 
  9670. method name. If debugging is turned on (that is, if global variable 
  9671. SOM_TraceLevel is set to one in the calling program), the macro produces a 
  9672. message each time the method procedure is entered. (See the next Chapter 3, 
  9673. "Using SOM Classes in Client Programs," for information on debugging with SOM.) 
  9674.  
  9675. Debugging can be permanently disabled (regardless of the setting of the 
  9676. SOM_TraceLevel setting in the calling program) by redefining the 
  9677. <className>MethodDebug macro to be SOM_NoTrace(c,m) following the #include 
  9678. directive for the implementation header file. (This can yield a slight 
  9679. performance improvement.) For example, to permanently disable debugging for the 
  9680. "Hello" class, insert the following lines in the hello.c implementation file 
  9681. following the line "#include hello.ih" (or "#include hello.xih," for classes 
  9682. implemented in C++): 
  9683.  
  9684.    #undef HelloMethodDebug
  9685.    #define HelloMethodDebug(c,m) SOM_NoTrace(c,m)
  9686.  
  9687. The way in which the stub procedure ends is determined by whether the method is 
  9688. a new or an overriding method. 
  9689.  
  9690.    o  For non-overriding (new) methods, the stub procedure ends with a return 
  9691.       statement (unless the return type of the method is void). The class 
  9692.       implementer should customize this return statement. 
  9693.  
  9694.    o  For overriding methods, the stub procedure ends by making a "parent 
  9695.       method call" for each of the class's parent classes. If the method has a 
  9696.       return type that is not void, the last of these parent method calls is 
  9697.       returned as the result of the method procedure. The class implementer can 
  9698.       customize this return statement if needed (for example, if some other 
  9699.       value is to be returned, or if the parent method calls should be made 
  9700.       before the method procedure's own processing). See the next section for a 
  9701.       discussion of parent method calls. 
  9702.  
  9703.  If a classinit modifier was specified to designate a user-defined procedure 
  9704.  that will initialize the "Hello" class object, as in the statement: 
  9705.  
  9706.      classinit = HInit;
  9707.  
  9708.  then the implementation template file would include the following stub 
  9709.  procedure for "HInit", in addition to the stub procedures for Hello's methods: 
  9710.  
  9711.      void  SOMLINK HInit(SOMClass *cls)
  9712.      {
  9713.  
  9714.      }
  9715.  
  9716.  This stub procedure is then filled in by the class implementer. If the class 
  9717.  definition specifies a functionprefix modifier, the classinit procedure name 
  9718.  is generated by prepending the specified prefix to the specified classinit 
  9719.  name, as with other stub procedures. 
  9720.  
  9721.  
  9722. ΓòÉΓòÉΓòÉ 7.7.2. Extending the implementation template ΓòÉΓòÉΓòÉ
  9723.  
  9724. To implement a method, add code to the body of the stub procedure.  In addition 
  9725. to standard C or C++ code, class implementers can also use any of the 
  9726. functions, methods, and macros SOM provides for manipulating classes and 
  9727. objects. Chapter 3, "Using SOM Classes in Client Programs," discusses these 
  9728. functions, methods, and macros. 
  9729.  
  9730. In addition to the functions, methods, and macros SOM provides for both class 
  9731. clients and class implementers, SOM provides two facilities especially for 
  9732. class implementers. They are for (1) accessing instance variables of the object 
  9733. responding to the method and (2) making parent method calls, as follows. 
  9734. Accessing internal instance variables 
  9735.  
  9736. To access internal instance variables, class implementers can use either of the 
  9737. following forms: 
  9738.  
  9739.       _variableName 
  9740.  
  9741.       somThis->variableName 
  9742.  
  9743.  To access internal instance variables "a", "b", and "c", for example, the 
  9744.  class implementer could use either _a, _b, and _c, or somThis->a, somThis->b, 
  9745.  and somThis->c. These expressions can appear on either side of an assignment 
  9746.  statement. The somThis  pointer must be properly initialized in advance using 
  9747.  the <className>GetData  procedure, as shown above. 
  9748.  
  9749.  Instance variables can be accessed only within the implementation file of the 
  9750.  class that introduces the instance variable, and not within the implementation 
  9751.  of subclasses or within client programs. (To allow access to instance data 
  9752.  from a subclass or from client programs, use an attribute rather than an 
  9753.  instance variable to represent the instance data.) For C++ programmers, the 
  9754.  _variableName form is available only if the macro  VARIABLE_MACROS is defined 
  9755.  (that is, #define VARIABLE_MACROS) in the implementation file prior to 
  9756.  including the .xih file for the class. 
  9757.  Making parent method calls 
  9758.  
  9759.  In addition to macros for accessing instance variables, the implementation 
  9760.  header file that the SOM Compiler generates also contains definitions of 
  9761.  macros for making "parent method calls." When a class overrides a method 
  9762.  defined by one or more of its parent classes, often the new implementation 
  9763.  simply needs to augment the functionality of the existing implementation(s). 
  9764.  Rather than completely re-implementing the method, the overriding method 
  9765.  procedure can conveniently invoke the procedure that one or more of the parent 
  9766.  classes uses to implement that method, then perform additional computation 
  9767.  (redefinition) as needed. The parent method call can occur anywhere within the 
  9768.  overriding method. (See Example 3 of the SOM IDL tutorial.) 
  9769.  
  9770.  The SOM-generated implementation header file defines the following macros for 
  9771.  making parent-method calls from within an overriding method: 
  9772.  
  9773.  <className>_parent_<parentClassName>_<methodName> 
  9774.               (for each parent class of the class overriding the method), and 
  9775.  
  9776.  <className>_parents_<methodName>. 
  9777.  
  9778.  For example, given class "Hello" with parents "File" and "Printer" and 
  9779.  overriding method somInit (the SOM method that initializes each object), the 
  9780.  SOM Compiler defines the following macros in the implementation header file 
  9781.  for "Hello": 
  9782.  
  9783.      Hello_parent_Printer_somInit
  9784.      Hello_parent_File_somInit
  9785.      Hello_parents_somInit
  9786.  
  9787.  Each macro takes the same number and type of arguments as <methodName>. The 
  9788.  <className>_parent_<parentClassName>_<methodName> macro invokes the 
  9789.  implementation of <methodName> inherited from <parentClassName>. Hence, using 
  9790.  the macro "Hello_parent_File_somInit" invokes the File's implementation of 
  9791.  somInit. 
  9792.  
  9793.  The <className>_parents_<  methodName> macro invokes the parent method for 
  9794.  each parent of the child class that supports <methodName>. That is, 
  9795.  "Hello_parents_somInit" would invoke File's implementation of somInit, 
  9796.  followed by Printer's implementation of somInit. The 
  9797.  <className>_parents_<methodName> macro is redefined in the binding file each 
  9798.  time the class interface is modified, so that if a parent class is added or 
  9799.  removed from the class definition, or if <methodName> is added to one of the 
  9800.  existing parents, the macro <className>_parents_<methodName > will be 
  9801.  redefined appropriately. 
  9802.  Converting C++ classes to SOM classes 
  9803.  
  9804.  For C++ programmers implementing SOM classes, SOM provides a macro that 
  9805.  simplifies the process of converting C++ classes to SOM classes. This macro 
  9806.  allows the implementation of one method of a class to invoke another new or 
  9807.  overriding method of the same class on the same receiving object by using the 
  9808.  following shorthand syntax: 
  9809.  
  9810.      _methodName(arg1, arg2, ...)
  9811.  
  9812.  For example, if class X introduces or overrides methods m1 and m2, then the 
  9813.  C++ implementation of method m1 can invoke method m2 on its somSelf argument 
  9814.  using _m2(arg, arg2, ...), rather than somSelf->m2(arg1, arg2, ...), as would 
  9815.  otherwise be required. (The longer form is also available.) Before the 
  9816.  shorthand form in the implementation file is used, the macro METHOD_MACROS 
  9817.  must be defined (that is, use #define METHOD_MACROS) prior to including the 
  9818.  xih file for the class. 
  9819.  Running incremental updates of the implementation template file 
  9820.  
  9821.  Refining the .idl file for a class is typically an iterative process. For 
  9822.  example, after running the IDL source file through the SOM Compiler and 
  9823.  writing some code in the implementation template file, the class implementer 
  9824.  realizes that the IDL class interface needs another method or attribute, a 
  9825.  method needs a different parameter, or any such changes. 
  9826.  
  9827.  As mentioned earlier, the SOM Compiler (when run using the c or xc emitter) 
  9828.  assists in this development by reprocessing the .idl file and making 
  9829.  incremental updates to the current implementation file. This modify-and-update 
  9830.  process may in fact be repeated several times before the class declaration 
  9831.  becomes final. Importantly, these updates do not disturb existing code for the 
  9832.  method procedures. Included in the incremental update are these changes: 
  9833.  
  9834.    o  Stub procedures are inserted into the implementation file for any new 
  9835.       methods added to the .idl file. 
  9836.  
  9837.    o  New comments in the .idl file are transferred to the implementation file, 
  9838.       reformatted appropriately. 
  9839.  
  9840.    o  If the interface to a method has changed, a new method procedure 
  9841.       prototype is placed in the implementation file. As a precaution, however, 
  9842.       the old prototype is also preserved within comments. The body of the 
  9843.       method procedure is left untouched (as are the method procedures for all 
  9844.       methods). 
  9845.  
  9846.    o  Similarly left intact are preprocessor directives, data declarations, 
  9847.       constant declarations, non-method functions, and additional comments--in 
  9848.       essence, everything else in the implementation file. 
  9849.  
  9850.  Some changes to the .idl file are not reflected automatically in the 
  9851.  implementation file after an incremental update. The class implementer must 
  9852.  manually edit the implementation file after changes such as these in the .idl 
  9853.  file: 
  9854.  
  9855.    o  Changing the name of a class or a method. 
  9856.  
  9857.    o  Changing the parents of a class (see also "If you change the parents of a 
  9858.       class..." later in this topic). 
  9859.  
  9860.    o  Changing a functionprefix class modifier statement. 
  9861.  
  9862.    o  Changing the content of a passthru statement directed to the 
  9863.       implementation (.c, .C, or cpp) file. As previously emphasized, however, 
  9864.       passthru statements are primarily recommended only for placing #include 
  9865.       statements in a binding file (.ih, xih, .h, or .xh file) used as a header 
  9866.       file in the implementation file or in a client program. 
  9867.  
  9868.    o  If the class implementer has placed "forward declarations" of the method 
  9869.       procedures in the implementation file, those are not updated. Updates 
  9870.       occur only for method prototypes that are part of the method procedures 
  9871.       themselves. 
  9872.  
  9873.  Considerations to ensure that updates work 
  9874.  
  9875.  To ensure that the SOM Compiler can properly update method procedure 
  9876.  prototypes in the implementation file, class implementers should avoid editing 
  9877.  changes such as the following: 
  9878.  
  9879.    o  A method procedure name should not be enclosed in parentheses in the 
  9880.       prototype. 
  9881.  
  9882.    o  A method procedure name must appear in the first line of the prototype, 
  9883.       excluding comments and white space. Thus, a new line must not be inserted 
  9884.       before the procedure name. 
  9885.  
  9886.  Error messages occur while updating an existing implementation file if it 
  9887.  contains syntax that is not ANSI C. For example, "old style" method 
  9888.  definitions such as the example on the left generate errors: 
  9889.  
  9890.  Invalid "old" syntax     Required  ANSI C 
  9891.  void foo(x)              void foo(short x) { 
  9892.  short x;                 ... 
  9893.  {                        } 
  9894.  ... 
  9895.  } 
  9896.  
  9897.  Similarly, error messages occur if anything in the .idl file would produce an 
  9898.  implementation file that is not syntactically valid for C/C++ (such as nested 
  9899.  comments). If update errors occur, either the .idl file or the implementation 
  9900.  file may be at fault. One way to track down the problem is to run the 
  9901.  implementation file through the C/C++ compiler. Or, move the existing 
  9902.  implementation file to another directory, generate a completely new one from 
  9903.  the .idl file, and then run it through the C/C++ compiler. One of these steps 
  9904.  should pinpoint the error, if the compiler is strict ANSI. 
  9905.  
  9906.  Conditional compilation (using #if and #ifdef directives) in the 
  9907.  implementation file can be another source of errors, because the SOM Compiler 
  9908.  does not invoke the preprocessor (it simply recognizes and ignores those 
  9909.  directives). The programmer should be careful when using conditional 
  9910.  compilation, to avoid a situation such as shown below; here, with apparently 
  9911.  two open braces and only one closing brace, the c or xc emitter would report 
  9912.  an unexpected end-of-file: 
  9913.  
  9914.  Invalid syntax           Required matching braces 
  9915.  
  9916.  #ifdef FOOBAR            #ifdef FOOBAR 
  9917.   {                        { 
  9918.  ...                      ... 
  9919.  #else                     } 
  9920.  {                        #else 
  9921.  ...                       { 
  9922.  #endif                   ... 
  9923.   }                        } 
  9924.                           #endif 
  9925.  
  9926.  If you change the parents of a class... 
  9927.  
  9928.  Because the implementation-file emitters never change any existing code within 
  9929.  a previously generated implementation file, changing the parents of a class 
  9930.  requires extremely careful attention by the programmer. For example, for 
  9931.  overridden methods, changing a class's parents may invalidate previous 
  9932.  parent-method calls provided by the template, and require the addition of new 
  9933.  parent-method calls. Neither of these issues is addressed by the incremental 
  9934.  update of previously generated method-procedure templates. 
  9935.  
  9936.  The greatest danger from changing the parents of a class, however, concerns 
  9937.  the ancestor-initializer calls provided in the stub procedures for initializer 
  9938.  methods. (For further information on ancestor initializer calls, see 
  9939.  "Initializing and Uninitializing Objects" later in this chapter.) Unlike 
  9940.  parent-method calls, ancestor-initializer calls are not optional--they must be 
  9941.  made to all classes specified in a directinitclasses modifier, and these calls 
  9942.  should always include the parents of the class (the default when no 
  9943.  directinitclasses modifier is given). When the parents of a class are changed, 
  9944.  however, the ancestor-initializer calls (which must be made in a specific 
  9945.  order) are not updated. 
  9946.  
  9947.  The easiest way to deal with this problem is to change the method name of the 
  9948.  previously generated initializer stub procedure in the implementation template 
  9949.  file. Then, the SOM Compiler can correctly generate a completely new 
  9950.  initializer stub procedure (while ignoring the renamed procedure). Once this 
  9951.  is done, your customization code from the renamed initializer procedure can be 
  9952.  "merged" into the newly generated one, after which the renamed initializer 
  9953.  procedure can be deleted. 
  9954.  
  9955.  
  9956. ΓòÉΓòÉΓòÉ 7.7.3. Compiling and linking ΓòÉΓòÉΓòÉ
  9957.  
  9958. After you fill in the method stub procedures, the implementation template file 
  9959. can be compiled and linked with a client program as follows. (In these 
  9960. examples, the environment variable SOMBASE represents the directory in which 
  9961. SOM has been installed.) 
  9962.  
  9963. For AIX:  When the client program (main.c) and the implementation file 
  9964. (hello.c) are written in C: 
  9965.  
  9966.    > xlc -I. -I$SOMBASE/include -o hello main.c hello.c -L$SOMBASE/lib -lsomtk
  9967.  
  9968. When the client program and the implementation file are written in C++: 
  9969.  
  9970.    > xlC -I. -I$SOMBASE/include -o hello main.C hello.C -L$SOMBASE/lib -lsomtk
  9971.  
  9972. For OS/2:  When the client program (main.c) and the implementation file 
  9973. (hello.c) are in C: 
  9974.  
  9975.    > set LIB=%SOMBASE%\lib;%LIB%
  9976.    > icc -I. -I%SOMBASE%\include -Fe hello main.c hello.c somtk.lib
  9977.  
  9978. When the client program and the implementation file are written in C++: 
  9979.  
  9980.    > set LIB=%SOMBASE%\lib;%LIB%
  9981.    > icc -I. -I%SOMBASE%\include -Fe hello main.cpp hello.cpp somtk.lib
  9982.  
  9983. If the class definition (in the .idl file) changes, run the SOM Compiler again. 
  9984. This will generate new header files, and it will update the implementation file 
  9985. to include any: 
  9986.  
  9987.    o  New comments, 
  9988.  
  9989.    o  Stub procedures for any new methods, and 
  9990.  
  9991.    o  Revised method procedure prototypes for methods whose signatures have 
  9992.       been changed in the .idl file. 
  9993.  
  9994.  After rerunning the SOM Compiler, add to the implementation file the code for 
  9995.  any newly added method procedures, and recompile the implementation file with 
  9996.  the client program. 
  9997.  
  9998.  
  9999. ΓòÉΓòÉΓòÉ 7.8. Initializing and Uninitializing Objects ΓòÉΓòÉΓòÉ
  10000.  
  10001. This section discusses the initialization and uninitialization of SOM objects. 
  10002. Subsequent topics introduce the methods and capabilities that the SOMobjects 
  10003. Developer Toolkit provides to facilitate this. 
  10004.  
  10005. Object creation is the act that enables the execution of methods on an object. 
  10006. In SOM, this means storing a pointer to a method table into a word of memory. 
  10007. This single act converts raw memory into an (uninitialized) SOM object that 
  10008. starts at the location of the method table pointer. 
  10009.  
  10010. Object initialization, on the other hand, is a separate activity from object 
  10011. creation in SOM. Initialization is a capability supported by certain methods 
  10012. available on an object. An object's class determines the implementation of the 
  10013. methods available on the object, and thus determines its initialization 
  10014. behavior. 
  10015.  
  10016. The instance variables encapsulated by a newly created object must be brought 
  10017. into a consistent state before the object can be used. This is the purpose of 
  10018. initialization methods. Because, in general, every ancestor of an object's 
  10019. class contributes instance data to an object, it is appropriate that each of 
  10020. these ancestors contribute to the initialization of the object. 
  10021.  
  10022. SOM thus recognizes initializers as a special kind of method. One advantage of 
  10023. this approach is that special metaclasses are not required for defining 
  10024. constructors (class methods) that take arguments. Furthermore, a class can 
  10025. define multiple initializer methods, thus enabling its different objects to be 
  10026. initialized supporting different characteristics or capabilities. This results 
  10027. in simpler designs and more efficient programs. 
  10028.  
  10029. The SOMobjects Toolkit provides an overall framework that class designers can 
  10030. easily exploit in order to implement default or customized initialization of 
  10031. SOM objects. This framework is fully supported by the SOM Toolkit emitters that 
  10032. produce the implementation template file. The following sections describe the 
  10033. declaration, implementation, and use of initializer (and uninitializer) 
  10034. methods. 
  10035.  
  10036. Important: All code written prior to SOMobjects Release 2.1 using documented 
  10037. guidelines for the earlier initialization approach based on the somInit method 
  10038. (as well as all existing class binaries) continues to be fully supported and 
  10039. useful. 
  10040.  
  10041.  
  10042. ΓòÉΓòÉΓòÉ 7.8.1. Initializer methods ΓòÉΓòÉΓòÉ
  10043.  
  10044. As noted above, in the SOMobjects Toolkit each ancestor of an object 
  10045. contributes to the initialization of that object. Initialization of an object 
  10046. involves a chain of ancestor-method calls that, by default, are automatically 
  10047. determined by the SOM Compiler emitters. The SOMobjects framework for 
  10048. initialization of objects is based on the following approach: 
  10049.  
  10050.    1. SOMobjects recognizes initializers as a special kind of method, and 
  10051.       supports a special mechanism for ordering the execution of 
  10052.       ancestor-initializer method procedures. The SOMObject class introduces an 
  10053.       initializer method, somDefaultInit that uses this execution mechanism. 
  10054.  
  10055.    2. The SOM Compiler's emitters provide special support for methods that are 
  10056.       declared as initializers in the .idl file. To supplement the 
  10057.       somDefaultInit method, SOM class designers can also declare additional 
  10058.       initializers in their own classes. 
  10059.  
  10060.  Two SOM IDL modifiers are provided for declaring initializer methods and 
  10061.  controlling their execution, init and directinitclasses: 
  10062.  
  10063.    o  The init modifier is required in order to designate a given method is a 
  10064.       initializer; that is, to indicate that the method both uses and supports 
  10065.       the object-initialization protocol described here. 
  10066.  
  10067.    o  The  directinitclasses modifier can be used to control the order of 
  10068.       execution of initializer method procedures provided by the different 
  10069.       ancestors of the class of an object. 
  10070.  
  10071.    o  For full definitions of init and directinitclasses, see the topic 
  10072.       "Modifier statements" in Chapter 4,"SOM IDL and the SOM Compiler." 
  10073.  
  10074.  Every SOM class has a list that defines (in sequential order) the ancestor 
  10075.  classes whose initializer method procedures the class should invoke. If a 
  10076.  class's IDL does not specify an explicit directinitclasses modifier, the 
  10077.  default for this list is simply the class's parents--in left-to-right order. 
  10078.  
  10079.  Using the directinitclasses list and the actual run-time class hierarchy above 
  10080.  itself, each class inherits from SOMClass the ability to create a data 
  10081.  structure of type somInitCtrl. This structure is used to control the execution 
  10082.  of initializers. Moreover, it represents a particular visit-ordering that 
  10083.  reaches each class in the transitive closure of directinitclasses exactly 
  10084.  once. To initialize a given object, this visit-ordering occurs as follows: 
  10085.  While recursively visiting each ancestor class whose initializer method 
  10086.  procedure should be run, SOMobjects first runs the initializer method 
  10087.  procedures of all of that class's directinitclasses if they have not already 
  10088.  been run by another class's initializers, with ancestor classes always taken 
  10089.  in left-to-right order. 
  10090.  
  10091.  The code that deals with the somInitCtrl data structure is generated 
  10092.  automatically within the implementation bindings for a class, and need not 
  10093.  concern a class implementor. 
  10094.  
  10095.  When an instance of a given class (or some descendant class) is initialized, 
  10096.  only one of the given class's initializers will be executed, and this will 
  10097.  happen exactly once (under control of the ordering determined by the class of 
  10098.  the object being initialized). 
  10099.  
  10100.  The somInitCtrl structure solves a problem originally created by the add 
  10101.  ition of multiple inheritance to SOMobjects 2.0. With multiple inheritance, 
  10102.  any class can appear at the top of a multiple inheritance diamond. Previously, 
  10103.  whenever this happened, the class could easily receive multiple initialization 
  10104.  calls. In the current version of the SOMobjects Toolkit, however, the 
  10105.  somInitCtrl structure prevents this from happening. 
  10106.  Declaring new initializers in SOM IDL 
  10107.  
  10108.  When defining SOMobjects classes, programmers can easily declare and implement 
  10109.  new initializers. Classes can have as many initializers as desired, and 
  10110.  subclassers can invoke whichever of these they want. When introducing new 
  10111.  initializers, developers must adhere to the following rules: 
  10112.  
  10113.    o  All initializer methods take a somInitCtrl data structure as an initial 
  10114.       inout parameter (its type is defined in the SOMobjects header file 
  10115.       somapi.h), and 
  10116.  
  10117.    o  All initializers return void. 
  10118.  
  10119.  Accordingly, the somDefaultInit initializer introduced by SOMObject takes a 
  10120.  somInitCtrl structure as its (only) argument, and returns void. Here is the 
  10121.  IDL syntax for this method, as declared in somobj.idl: 
  10122.  
  10123.   void  somDefaultInit (inout somInitCtrl ctrl);
  10124.  
  10125.  When introducing a new initializer, it is also necessary to specify the init 
  10126.  modifier in the implementation section. The init modifier is what tells 
  10127.  emitters that the new method is actually an initializer, so the method can be 
  10128.  properly supported from the language bindings. As described below, this 
  10129.  support includes the generation of special initializer stub procedures in the 
  10130.  implementation template file, as well as bindings containing 
  10131.  ancestor-initialization macros and object constructors that invoke the class 
  10132.  implementor's new initializers. 
  10133.  
  10134.  It is a good idea to begin the names of initializer methods with the name of 
  10135.  the class (or some other string that can be unique for the class). This is 
  10136.  important because all initializers available on a class must be newly 
  10137.  introduced by that class (that is, you cannot override initializers--except 
  10138.  for somDefaultInit). Using a class-unique name means that subclasses will not 
  10139.  be unnecessarily constrained in their choice of initializer names. 
  10140.  
  10141.  Here are two classes that introduce new initializers: 
  10142.  
  10143.   interface Example1 : SOMObject
  10144.   {
  10145.      void Example1_withName (inout somInitCtrl ctrl,in string name);
  10146.      void Example1_withSize (inout somInitCtrl ctrl,in long size);
  10147.      void Example1_withNandS(inout somInitCtrl ctrl,in string name,
  10148.                                                      in long size);
  10149.           implementation {
  10150.                   releaseorder: Example1_withName,
  10151.                                 Example1_withSize,
  10152.                                 Example1_withNandS;
  10153.                   somDefaultInit: override, init;
  10154.                   somDestruct: override;
  10155.                   Example1_withName: init;
  10156.                   Example1_withSize: init;
  10157.                   Example1_withNandS: init;
  10158.           };
  10159.   };
  10160.  
  10161.   interface Example2 : Example1
  10162.   {
  10163.      void Example2_withName(inout somInitCtrl ctrl, in string name);
  10164.      void Example2_withSize(inout somInitCtrl ctrl, in long size);
  10165.           implementation {
  10166.                   releaseorder: Example2_withName,
  10167.                                 Example2_withSize;
  10168.                   somDefaultInit: override, init;
  10169.                   somDestruct: override;
  10170.                   Example2_withName: init;
  10171.                   Example2_withSize: init;
  10172.           };
  10173.   };
  10174.  
  10175.  Here, interface "Example1" declares three new initializers. Notice the use of 
  10176.  inout somInitCtrl as the first argument of each initializer, and also note 
  10177.  that the init modifier is used in the implementation section. These two things 
  10178.  are required to declare initializers. Any number of initializers can be 
  10179.  declared by a class. "Example2" declares two initializers. 
  10180.  
  10181.  "Example1" and "Example2" both override the somDefaultInit initializerThis 
  10182.  initializer method is introduced by SOMObject and is special for two resons: 
  10183.  First, somDefaultInit is the only initializer that can be overridden And, 
  10184.  second, SOMobjects arranges that this initializer will always be available on 
  10185.  any class (as further explained below). 
  10186.  
  10187.  Historically in the SOMobjects Toolkit, object#initialization methods by 
  10188.  default have invoked the somInit method, which class implementors could 
  10189.  override to customize initialization as appropriate. SOMobjects continues to 
  10190.  support this approach, so that existing code (and class binaries) will execute 
  10191.  correctly. However, the somDefaultInit method is now the preferred form of 
  10192.  initialization because it offers greatly improved efficiency. 
  10193.  
  10194.  Even if no specialized initialization is needed for a class, you should still 
  10195.  override the somDefaultInit method in the interest of efficiency. If you do 
  10196.  not override somDefaultInit, then a generic (and therefore less efficient) 
  10197.  somDefaultInit method procedure will be used for your class. This generic 
  10198.  method procedure first invokes somDefaultInit on the appropriate ancestor 
  10199.  classes. Then (for consistency with earlier versions of SOMobjects), it checks 
  10200.  to determine if the class overrides somInit and, if so, calls any customized 
  10201.  somInit code provided by the class. 
  10202.  
  10203.  When you override somDefaultInit, the emitter's implementation template file 
  10204.  will include a stub procedure similar to those used for other initializers, 
  10205.  and you can fill it in as appropriate (or simply leave it as is). Default 
  10206.  initialization for your class will then run much faster than with the generic 
  10207.  method procedure. Examples of initializer stub procedures (and customizations) 
  10208.  are given below. 
  10209.  
  10210.  In summary, the initializers available for any class of objects are 
  10211.  somDefaultInit (which you should always override) plus any new initializers 
  10212.  explicitly declared by the class designer. Thus, "Example1" objects may be 
  10213.  initialized using any of four different initializers (the three that are 
  10214.  explicitly declared, plus somDefaultInit). Likewise, there are three 
  10215.  initializers for the "Example2" objects. Some examples of using initializers 
  10216.  are provided below. 
  10217.  
  10218.  
  10219.  Considerations re: 'somInit' initialization from earlier SOM releases 
  10220.  
  10221.  To re-emphasize: All code written prior to SOMobjects Release 2.1 using 
  10222.  documented guidelines for the earlier initialization approach based on the 
  10223.  somInit method (as well as all existing class binaries) continues to be fully 
  10224.  supported and useful. 
  10225.  
  10226.  Prior to SOMobjects 2.1, initialization was done with initializer methods that 
  10227.  would simply "chain" parent-method calls upward, thereby allowing the 
  10228.  execution of initializer method procedures contributed by all ancestors of an 
  10229.  object's class. This chaining of initializer calls was not supported in any 
  10230.  special way by the SOM API. Parent-method calls are simply one of the possible 
  10231.  idioms available to users of OOP in SOM, easily available to a SOM class 
  10232.  designer as a result of the support provided by the SOMobjects Toolkit 
  10233.  emitters for parent-method calls. 
  10234.  
  10235.  So, SOM did not constrain initialization to be done in any particular way or 
  10236.  require the use of any particular ordering of the method procedures of 
  10237.  ancestor classes.  But, SOM did provide an overall framework that class 
  10238.  designers could easily utilize in order to implement default initialization of 
  10239.  SOM objects. This framework is provided by the somInit object-initializatio 
  10240.  method introduced by the SOMobject class and supported by the SOM Toolkit 
  10241.  emitters. The emitters create an implementation template file with stub 
  10242.  procedures for overridden methods that automatically chain parent-method calls 
  10243.  upward through parent classes. Many of the class methods that perform object 
  10244.  creation called somInit automatically. 
  10245.  
  10246.  Note:  These will now call somDefaultInit, which in turn calls somInit for 
  10247.         legacy code, as described in the previous topic. 
  10248.  
  10249.  Because it takes no arguments, somInit best served the purpose of a default 
  10250.  initializer. SOM programmers also had the option of introducing additional 
  10251.  "non-default" initialization methods that took arguments. In addition, by 
  10252.  using metaclasses, they could introduce new class methods as object 
  10253.  constructors that first create an object (generally using somNewNoInit.) and 
  10254.  then invoke some non-default initializer on the new object. 
  10255.  
  10256.  For a number of reasons, the somInit framework has been augmented by 
  10257.  recognizing initializers special kind of method in SOMobjects. One advantage 
  10258.  of this approach is that special metaclasses are no longer required for 
  10259.  defining constructors that take arguments. Instead, because the init modifier 
  10260.  identifies initializers, usage-binding emitters can now provide these 
  10261.  constructors. This results in simpler designs and more efficient programs. 
  10262.  
  10263.  Although somDefaultInit replaces somInit  as the no-argument initializer used 
  10264.  for SOM objects, all previous use of somInit is still supported by the 
  10265.  SOMobjects Developers Toolkit on AIX, OS/2 and 16-bit Windows. You may 
  10266.  continue to use somInit on these systems if you like, although this is 
  10267.  somewhat less efficient than using somDefaultInit. 
  10268.  
  10269.  However, you cannot use both methods. In particular, if a class overrides both 
  10270.  somDefaultInit  and somInit, its somInit code will never be executed. It is 
  10271.  recommended that you always override  somDefaultInit for object 
  10272.  initialization. For one thing, it is likely that when SOMobjects is ported to 
  10273.  new systems, somInit (and somUninit) may not be supported on those systems. 
  10274.  Thus, code written using these (obsolete) methods will be less portable. 
  10275.  Implementing initializers 
  10276.  
  10277.  When new initializers are introduced by a class, as in the preceding examples, 
  10278.  the implementation template file generated by the SOM Toolkit C and C++ 
  10279.  emitters automatically contains an appropriate stub procedure for each 
  10280.  initializer method, for the class implementor's use. The body of an 
  10281.  initializer stub procedure consists of two main sections: 
  10282.  
  10283.    o  The first section performs calls to ancestors of the class to invoke 
  10284.       their initializers. 
  10285.  
  10286.    o  The second section is used by the programmer to perform any "local" 
  10287.       initializations appropriate to the instance data of the class being 
  10288.       defined. 
  10289.  
  10290.  In the first section, by default, the parents of the new class are the 
  10291.  ancestors whose initializers are called. When something else is desired, the 
  10292.  IDL directinitclasses modifier can be used to explicitly designate the 
  10293.  ancestors whose initializer methods should be invoked by a new class's 
  10294.  initializers. 
  10295.  
  10296.  Important:  Under no circumstances can the number or the ordering of ancestor 
  10297.  initializer calls in the first section of an initializer stub procedure be 
  10298.  changed. The control masks used by initializers are based on these orderings. 
  10299.  (If you want to change the number or ordering of ancestor initializer calls, 
  10300.  you must use the directinitclasses modifier.) The ancestor initializer calls 
  10301.  themselves can be modified as described below. 
  10302.  
  10303.  Each call to an ancestor initializer is made using a special macro (much like 
  10304.  a parent call) that is defined for this purpose within the implementation 
  10305.  bindings. These macros are defined for all possible ancestor initialization 
  10306.  calls. Initially, an initializer stub procedure invokes the default ancestor 
  10307.  initializers provided by somDefaultInit. However, a class implementor can 
  10308.  replace any of these calls with a different initializer call, as long as it 
  10309.  calls the same ancestor (see the example in the next topic). Non-default 
  10310.  initializer calls generally take other arguments in addition to the control 
  10311.  argument. 
  10312.  
  10313.  In the second section of an initializer stub procedure, the programmer 
  10314.  provides any class-specific code that may be needed for initialization. For 
  10315.  example, the "Example2_withName" stub procedure is shown below. As with all 
  10316.  stub procedures produced by the SOMobjects implementation-template emitters, 
  10317.  this code requires no modification to run correctly. 
  10318.  
  10319.   SOM_Scope void SOMLINK Example2_withName(Example2 *somSelf,
  10320.                                            Environment *ev,
  10321.                                            somInitCtrl* ctrl,
  10322.                                            string name)
  10323.   {
  10324.       Example2Data *somThis; /* set by BeginInitializer */
  10325.       somInitCtrl globalCtrl;
  10326.       somBooleanVector myMask;
  10327.       Example2MethodDebug("Example2","withName");
  10328.  
  10329.       /*
  10330.        * first section -- calls to ancestor initializers
  10331.        */
  10332.        Example2_BeginInitializer_Example2_withName;
  10333.        Example2_Init_Example1_somDefaultInit(somSelf, ctrl);
  10334.  
  10335.       /*
  10336.        * second section -- local Example2 initialization code
  10337.        */
  10338.   }
  10339.  
  10340.  In this example, notice that the "Example2_withName" initializer is an IDL 
  10341.  callstyle method, so it  receives an Environment argument. In contrast, 
  10342.  somDefaultInit is introduced by the SOMObject class (so it has an OIDL 
  10343.  callstyle initializer, without an environment). 
  10344.  
  10345.  Important: If a class is defined where multiple initializers have exactly the 
  10346.  same signature, then the C++ usage bindings will not be able to differentiate 
  10347.  among them. That is, if there are multiple initializers defined with 
  10348.  environment and long arguments, for example, then C++ clients would not be 
  10349.  able to make a call using only the class name and arguments, such as: 
  10350.  
  10351.  
  10352.   new Example2(env, 123);
  10353.  
  10354.  Rather, C++ users would be forced to first invoke the somNewNoInit method on 
  10355.  the class to create an uninitialized object, and then separately invoke the 
  10356.  desired initializer method on the object. This call would pass a zero for the 
  10357.  control argument, in addition to passing values for the other arguments. For 
  10358.  further discussion of client usage, see "Using initializers when creating new 
  10359.  objects" later in this chapter. 
  10360.  Selecting non-default ancestor initializer calls 
  10361.  
  10362.  Often, it will be appropriate (in the first section of an initializer stub 
  10363.  procedure) to change the invocation of an ancestor's somDefaultInit 
  10364.  initializer to some other initializer available on the same class. The rule 
  10365.  for making this change is simple: Replace somDefaultInit with the name of the 
  10366.  desired ancestor initializer, and add any new arguments that are required by 
  10367.  the replacement initializer. Important: Under no circumstances can you change 
  10368.  anything else in the first section. 
  10369.  
  10370.  This example shows how to change an ancestor-initializer call correctly. Since 
  10371.  there is a known "Example1_withName" initializer, the following default 
  10372.  ancestor-initializer call (produced within the stub procedure for 
  10373.  "Example2_withName") can be changed from 
  10374.  
  10375.  
  10376.   Example2_Init_Example1_somDefaultInit(somSelf, ctrl);
  10377.  
  10378.   to
  10379.  
  10380.   Example2_Init_Example1_Example1_withName(somSelf, ev, ctrl, name)
  10381.  
  10382.  Notice that the revised ancestor-initializer call includes arguments for an 
  10383.  Environment and a name, as defined by the "Example1_withname" initializer. 
  10384.  Using initializers when creating new objects 
  10385.  
  10386.  There are several ways that client programs can take advantage of the 
  10387.  somDefaultInit object initialization. If desired, clients can use the SOM API 
  10388.  directly (rather than taking advantage of the usage bindings). Also, the 
  10389.  general object constructor, somNew, can always be invoked on a class to create 
  10390.  and initialize objects. This call creates a new object and then invokes 
  10391.  somDefaultInit on it 
  10392.  
  10393.  To use the SOM API directly, the client code should first invoke the 
  10394.  somNewNoInit method on the desired class object to create a new, uninitialized 
  10395.  object. Then, the desired initializer is invoked on the new object, passing a 
  10396.  null (that is, 0) control argument in addition to whatever other arguments may 
  10397.  be required by the initializer. For example: 
  10398.  
  10399.  
  10400.   /* first make sure the Example2 class object exists */
  10401.   Example2NewClass(Example2_MajorVersion, Example2_MinorVersion);
  10402.  
  10403.  
  10404.   /* then create a new, uninitialized Example2 object */
  10405.   myObject = _somNewNoInit(_Example2);
  10406.  
  10407.   (null)
  10408.   /* then initialize it with the desired initializer */
  10409.   Example2_withName(myObject, env, 0, "MyName");
  10410.  
  10411.  Usage bindings hide the details associated with initializer use in various 
  10412.  ways and make calls more convenient for the client. For example, the C usage 
  10413.  bindings for any given class already provide a convenience macro, 
  10414.  <className>New, that first assures existence of the class object, and then 
  10415.  calls somNew on it to create and initialize a new object. As explained above, 
  10416.  somNew will use somDefaultInit to initialize the new object. 
  10417.  
  10418.  Also, the C usage bindings provide object-construction macros that use 
  10419.  somNewNoInit and then invoke non-default initializers. These  macros are named 
  10420.  using the form <className>New_<initializerName>. For example, the C usage 
  10421.  bindings for "Example2" allow using the following expression to create, 
  10422.  initialize, and return a new "Example2" object: 
  10423.  
  10424.  
  10425.   Example2New_Example2_withName(env, "AnyName");
  10426.  
  10427.  In the C++ bindings, initializers are represented as overloaded C++ 
  10428.  constructors. As a result, there is no need to specify the name of the 
  10429.  initializer method. For example, using the C++ bindings, the following 
  10430.  expressions could be used to create a new "Example2" object: 
  10431.  
  10432.  
  10433.   new Example2;                   // will use somDefaultInit
  10434.   new Example2();                 // will use somDefaultInit
  10435.   new Example2(env,"A.B.Normal"); // will use Example2_withName
  10436.   new Example2(env,123);          // will use Example2_withSize
  10437.  
  10438.  Observe that if multiple initializers in a class have exactly the same 
  10439.  signatures, the C++ usage bindings would be unable to differentiate among the 
  10440.  calls, if made using the forms illustrated above. In this case, a client could 
  10441.  use somNewNoInit first, and then invoke the specific initializer, as described 
  10442.  in the preceding paragraphs. 
  10443.  
  10444.  
  10445. ΓòÉΓòÉΓòÉ 7.8.2. Uninitialization ΓòÉΓòÉΓòÉ
  10446.  
  10447. An object should always be uninitialized before its storage is freed. This is 
  10448. important because it also allows releasing resources and freeing storage not 
  10449. contained within the body of the object.  SOMobjects handles uninitialization 
  10450. in much the same way as for initializers: An uninitializer takes a control 
  10451. argument and is supported with stub procedures in the implementation template 
  10452. file in a manner similar to initializers. 
  10453.  
  10454. Only a single uninitialization method is needed, so SOMObject introduces the 
  10455. method that provides this function: somDestruct. As with the default 
  10456. initializer method, a class designer who requires nothing special in the way of 
  10457. uninitialization need not be concerned about modifying the default somDestruct 
  10458. method procedure. However, your code will execute faster if the .idl file 
  10459. overrides somDestruct so that a non-generic stub-procedure code can be provided 
  10460. for the class. Note that somDestruct was overridden by "Example1" and 
  10461. "Example2" above No specific IDL modifiers other than override are required for 
  10462. this. 
  10463.  
  10464. Like an initializer template, the stub procedure for somDestruct consists of 
  10465. two sections: The first section is used by the programmer for performing any 
  10466. "local" uninitialization that may be required. The second section (which 
  10467. consists of a single EndDestructor macro invocation) invokes somDestruct on 
  10468. ancestors The second section must not be modified or removed by the programmer. 
  10469. It must be the final statement executed in the destructor. 
  10470. Using `somDestruct' 
  10471.  
  10472. It is rarely necessary to invoke the somDestruct method explicitly This is 
  10473. because object uninitialization is normally done just before freeing an 
  10474. object's storage, and the mechanisms provided by SOMobjects for this purpose 
  10475. will automatically invoke somDestruct. For example, if an object were created 
  10476. using somNew or somNewNoInit, or by using a convenience macro provided by the C 
  10477. languag bindings, then the somFree method can be invoked on the object to 
  10478. delete the object. This automatically calls somDestruct before freeing storage. 
  10479.  
  10480. C++ users can simply use the delete operator provided by the C++ bindings. This 
  10481. destructor calls somDestruct before the C++ delete  operator frees the object's 
  10482. storage. 
  10483.  
  10484. On the other hand, if an object is initially created by allocating memory in 
  10485. some special way and subsequently some somRenew methods are used, somFree (or 
  10486. C++ delete) is probably not appropriate. Thus, the somDestruct method should be 
  10487. explicitly called to uninitialize the object before freeing memory. 
  10488.  
  10489.  
  10490. ΓòÉΓòÉΓòÉ 7.8.3. A complete example ΓòÉΓòÉΓòÉ
  10491.  
  10492. The following example illustrates the implementation and use of initializers 
  10493. and destructors from the C++ bindings. The first part shows the IDL for three 
  10494. classes with initializers. For variety, some of the classes use callstyle OIDL 
  10495. and others use callstyle IDL. 
  10496.  
  10497. #include <somobj.idl>
  10498.  
  10499. interface A : SOMObject {
  10500.         readonly attribute long a;
  10501.         implementation {
  10502.                 releaseorder: _get_a;
  10503.                 functionprefix = A;
  10504.                 somDefaultInit: override, init;
  10505.                 somDestruct: override;
  10506.                 somPrintSelf: override;
  10507.         };
  10508. };
  10509.  
  10510.  
  10511. interface B : SOMObject {
  10512.         readonly attribute long b;
  10513.         void BwithInitialValue(inout somInitCtrl ctrl,
  10514.                                in long initialValue);
  10515.         implementation {
  10516.                 callstyle = OIDL;
  10517.                 releaseorder: _get_b, BwithInitialValue;
  10518.                 functionprefix = B;
  10519.                 BwithInitialValue: init;
  10520.                 somDefaultInit: override, init;
  10521.                 somDestruct: override;
  10522.                 somPrintSelf: override;
  10523.         };
  10524. };
  10525.  
  10526.  
  10527. interface C : A, B      {
  10528.         readonly attribute long c;
  10529.         void CwithInitialValue(inout somInitCtrl ctrl,
  10530.                                in long initialValue);
  10531.         void CwithInitialString(inout somInitCtrl ctrl,
  10532.                                 in string initialString);
  10533.         implementation {
  10534.                 releaseorder: _get_c, CwithInitialString,
  10535.                               CwithInitialValue;
  10536.                 functionprefix = C;
  10537.                 CwithInitialString: init;
  10538.                 CwithInitialValue: init;
  10539.                 somDefaultInit: override, init;
  10540.                 somDestruct: override;
  10541.                 somPrintSelf: override;
  10542.         };
  10543. };
  10544.  
  10545.  
  10546. Implementation code 
  10547.  
  10548. Based on the foregoing class definitions, the next example illustrates several 
  10549. important aspects of initializers. The following code is a completed 
  10550. implementation template and an example client program for the preceding 
  10551. classes. Code added to the original template is given in bold. 
  10552.  
  10553. /*
  10554.  *  This file generated by the SOM Compiler and Emitter Framework.
  10555.  *  Generated using:
  10556.  *      SOM Emitter emitxtm.dll: 2.22
  10557.  */
  10558.  
  10559. #define SOM_Module_ctorfullexample_Source
  10560. #define VARIABLE_MACROS
  10561. #define METHOD_MACROS
  10562. #include <ctorFullExample.xih>
  10563. #include <stdio.h>
  10564.  
  10565. SOM_Scope void SOMLINK AsomDefaultInit(A *somSelf,
  10566.                                        somInitCtrl* ctrl)
  10567. {
  10568.     AData *somThis; /* set by BeginInitializer */
  10569.     somInitCtrl globalCtrl;
  10570.     somBooleanVector myMask;
  10571.     AMethodDebug("A","somDefaultInit");
  10572.  
  10573.     A_BeginInitializer_somDefaultInit;
  10574.     A_Init_SOMObject_somDefaultInit(somSelf, ctrl);
  10575.     /*
  10576.      * local A initialization code added by programmer
  10577.      */
  10578. _a = 1;
  10579. }
  10580.  
  10581. SOM_Scope void SOMLINK AsomDestruct(A *somSelf, octet doFree,
  10582.                                     somDestructCtrl* ctrl)
  10583. {
  10584.     AData *somThis; /* set by BeginDestructor */
  10585.     somDestructCtrl globalCtrl;
  10586.     somBooleanVector myMask;
  10587.     AMethodDebug("A","somDestruct");
  10588.     A_BeginDestructor;
  10589.  
  10590.     /*
  10591.      * local A deinitialization code added by programmer
  10592.      */
  10593.     A_EndDestructor;
  10594. }
  10595.  
  10596. SOM_Scope SOMObject*  SOMLINK AsomPrintSelf(A *somSelf)
  10597. {
  10598.     AData *somThis = AGetData(somSelf);
  10599.     AMethodDebug("A","somPrintSelf");
  10600.     somPrintf("{an instance of %s at location %X with (a=%d)}\n",
  10601.              _somGetClassName(),somSelf,__get_a((Environment*)0));
  10602.     return (SOMObject*)((void*)somSelf);
  10603. }
  10604.  
  10605. SOM_Scope void SOMLINK BBwithInitialValue(B *somSelf,
  10606.                                           somInitCtrl* ctrl,
  10607.                                           long initialValue)
  10608. {
  10609.     BData *somThis; /* set by BeginInitializer */
  10610.     somInitCtrl globalCtrl;
  10611.     somBooleanVector myMask;
  10612.     BMethodDebug("B","BwithInitialValue");
  10613.  
  10614.     B_BeginInitializer_withInitialValue;
  10615.     B_Init_SOMObject_somDefaultInit(somSelf, ctrl);
  10616.  
  10617.     /*
  10618.      * local B initialization code added by programmer
  10619.      */
  10620.  _b = initialValue;
  10621. }
  10622.  
  10623. SOM_Scope void SOMLINK BsomDefaultInit(B *somSelf,
  10624.                                        somInitCtrl* ctrl)
  10625. {
  10626.     BData *somThis; /* set by BeginInitializer */
  10627.     somInitCtrl globalCtrl;
  10628.     somBooleanVector myMask;
  10629.     BMethodDebug("B","somDefaultInit");
  10630.  
  10631.     B_BeginInitializer_somDefaultInit;
  10632.     B_Init_SOMObject_somDefaultInit(somSelf, ctrl);
  10633.  
  10634.     /*
  10635.      * local B initialization code added by programmer
  10636.      */
  10637.  _b = 2;
  10638. }
  10639.  
  10640. SOM_Scope void SOMLINK BsomDestruct(B *somSelf, octet doFree,
  10641.                                     somDestructCtrl* ctrl)
  10642. {
  10643.     BData *somThis; /* set by BeginDestructor */
  10644.     somDestructCtrl globalCtrl;
  10645.     somBooleanVector myMask;
  10646.     BMethodDebug("B","somDestruct");
  10647.     B_BeginDestructor;
  10648.  
  10649.     /*
  10650.      * local B deinitialization code added by programmer
  10651.      */
  10652.  
  10653.     B_EndDestructor;
  10654. }
  10655.  
  10656. SOM_Scope SOMObject*  SOMLINK BsomPrintSelf(B *somSelf)
  10657. {
  10658.     BData *somThis = BGetData(somSelf);
  10659.     BMethodDebug("B","somPrintSelf");
  10660.     printf("{an instance of %s at location %X with (b=%d)}\n",
  10661.            _somGetClassName(),somSelf,__get_b());
  10662.     return (SOMObject*)((void*)somSelf);
  10663. }
  10664.  
  10665. Note: The following initializer for a C object accepts a string as an argument, 
  10666. converts this to an integer, and uses this for ancestor initialization of "B." 
  10667. This illustrates how a default ancestor initializer call is replaced with a 
  10668. non-default ancestor initializer call. 
  10669.  
  10670. SOM_Scope void SOMLINK CCwithInitialString(C *somSelf,
  10671.                                            Environment *ev,
  10672.                                            somInitCtrl* ctrl,
  10673.                                            string initialString)
  10674. {
  10675.     CData *somThis; /* set by BeginInitializer */
  10676.     somInitCtrl globalCtrl;
  10677.     somBooleanVector myMask;
  10678.     CMethodDebug("C","CwithInitialString");
  10679.  
  10680.     C_BeginInitializer_withInitialString;
  10681.     C_Init_A_somDefaultInit(somSelf, ctrl);
  10682.     C_Init_B_BwithInitialValue(somSelf, ctrl,
  10683.                                atoi(initialString)-11);
  10684.  
  10685.     /*
  10686.      * local C initialization code added by programmer
  10687.      */
  10688.     _c = atoi(initialString);
  10689. }
  10690.  
  10691. SOM_Scope void SOMLINK CsomDefaultInit(C *somSelf,
  10692.                                        somInitCtrl* ctrl)
  10693. {
  10694.     CData *somThis; /* set by BeginInitializer */
  10695.     somInitCtrl globalCtrl;
  10696.     somBooleanVector myMask;
  10697.     CMethodDebug("C","somDefaultInit");
  10698.  
  10699.     C_BeginInitializer_somDefaultInit;
  10700.     C_Init_A_somDefaultInit(somSelf, ctrl);
  10701.     C_Init_B_somDefaultInit(somSelf, ctrl);
  10702.  
  10703.     /*
  10704.      * local C initialization code added by programmer
  10705.      */
  10706. _c = 3;
  10707. }
  10708.  
  10709. SOM_Scope void SOMLINK CsomDestruct(C *somSelf, octet doFree,
  10710.                                     somDestructCtrl* ctrl)
  10711. {
  10712.     CData *somThis; /* set by BeginDestructor */
  10713.     somDestructCtrl globalCtrl;
  10714.     somBooleanVector myMask;
  10715.     CMethodDebug("C","somDestruct");
  10716.     C_BeginDestructor;
  10717.  
  10718.     /*
  10719.      * local C deinitialization code added by programmer
  10720.      */
  10721.  
  10722.     C_EndDestructor;
  10723. }
  10724.  
  10725.  
  10726. SOM_Scope SOMObject*  SOMLINK CsomPrintSelf(C *somSelf)
  10727. {
  10728.     CData *somThis = CGetData(somSelf);
  10729.     CMethodDebug("C","somPrintSelf");
  10730.     printf("{an instance of %s at location %X with"
  10731.            " (a=%d, b=%d, c=%d)}\n",
  10732.         _somGetClassName(),somSelf,
  10733.         __get_a((Environment*)0),
  10734.         __get_b(),
  10735.         __get_c((Environment*)0));
  10736.     return (SOMObject*)((void*)somSelf);
  10737. }
  10738.  
  10739. SOM_Scope void SOMLINK CCwithInitialValue(  C *somSelf,
  10740.                                         Environment *ev,
  10741.                                         somInitCtrl* ctrl,
  10742.                                         long initialValue)
  10743. {
  10744.     CData *somThis; /* set by BeginInitializer */
  10745.     somInitCtrl globalCtrl;
  10746.     somBooleanVector myMask;
  10747.     CMethodDebug("C","CwithInitialValue");
  10748.  
  10749.     C_BeginInitializer_withInitialValue;
  10750.     C_Init_A_somDefaultInit(somSelf, ctrl);
  10751.     C_Init_B_BwithInitialValue(somSelf, ctrl, initialValue-11);
  10752.  
  10753.     /*
  10754.      * local C initialization code added by programmer
  10755.      */
  10756.     _c = initialValue;
  10757. }
  10758.  
  10759. Here is a C++ program that creates instances of "A", "B", and "C" using the 
  10760. initializers defined above. 
  10761.  
  10762. main()
  10763. {
  10764.     SOM_TraceLevel = 1;
  10765.  
  10766.     A *a = new A;
  10767.     a->somPrintSelf();
  10768.     delete a;
  10769.     printf("\n");
  10770.  
  10771.     B *b = new B();
  10772.     b->somPrintSelf();
  10773.     delete b;
  10774.     printf("\n");
  10775.  
  10776.     b = new B(22);
  10777.     b->somPrintSelf();
  10778.     delete b;
  10779.     printf("\n");
  10780.  
  10781.     C *c = new C;
  10782.     c->somPrintSelf();
  10783.     delete c;
  10784.     printf("\n");
  10785.  
  10786.     c = new C((Environment*)0, 44);
  10787.     c->somPrintSelf();
  10788.     delete c;
  10789.     printf("\n");
  10790.  
  10791.     c = new C((Environment*)0, "66");
  10792.     c->somPrintSelf();
  10793.     delete c;
  10794. }
  10795.  
  10796. The output from the preceding program is as follows: 
  10797.  
  10798. "ctorFullExample.C": 18:        In A:somDefaultInit
  10799. "ctorFullExample.C": 48:        In A:somPrintSelf
  10800. "./ctorFullExample.xih": 292:     In A:A_get_a
  10801. {an instance of A at location 20063C38 with (a=1)}
  10802. "ctorFullExample.C": 35:        In A:somDestruct
  10803.  
  10804. "ctorFullExample.C": 79:        In B:somDefaultInit
  10805. "ctorFullExample.C": 110: In B:somPrintSelf
  10806. "./ctorFullExample.xih": 655:     In B:B_get_b
  10807. {an instance of B at location 20064578 with (b=2)}
  10808. "ctorFullExample.C": 97:        In B:somDestruct
  10809.  
  10810. "ctorFullExample.C": 62:        In B:BwithInitialValue
  10811. "ctorFullExample.C": 110: In B:somPrintSelf
  10812. "./ctorFullExample.xih": 655:     In B:B_get_b
  10813. {an instance of B at location 20064578 with (b=22)}
  10814. "ctorFullExample.C": 97:        In B:somDestruct
  10815.  
  10816. "ctorFullExample.C": 150: In C:somDefaultInit
  10817. "ctorFullExample.C": 18:        In A:somDefaultInit
  10818. "ctorFullExample.C": 79:        In B:somDefaultInit
  10819. "ctorFullExample.C": 182: In C:somPrintSelf
  10820. "./ctorFullExample.xih": 292:     In A:A_get_a
  10821. "./ctorFullExample.xih": 655:     In B:B_get_b
  10822. "./ctorFullExample.xih": 1104:    In C:C_get_c
  10823. {an instance of C at location 20065448 with (a=1, b=2, c=3)}
  10824. "ctorFullExample.C": 169: In C:somDestruct
  10825. "ctorFullExample.C": 35:        In A:somDestruct
  10826. "ctorFullExample.C": 97:        In B:somDestruct
  10827.  
  10828. "ctorFullExample.C": 196: In C:CwithInitialValue
  10829. "ctorFullExample.C": 18:        In A:somDefaultInit
  10830. "ctorFullExample.C": 62:        In B:BwithInitialValue
  10831. "ctorFullExample.C": 182: In C:somPrintSelf
  10832. "./ctorFullExample.xih": 292:     In A:A_get_a
  10833. "./ctorFullExample.xih": 655:     In B:B_get_b
  10834. "./ctorFullExample.xih": 1104:      In C:C_get_c
  10835. {an instance of C at location 20065448 with (a=1, b=33, c=44)}
  10836. "ctorFullExample.C": 169: In C:somDestruct
  10837. "ctorFullExample.C": 35:        In A:somDestruct
  10838. "ctorFullExample.C": 97:        In B:somDestruct
  10839.  
  10840.  
  10841.  
  10842. "ctorFullExample.C": 132: In C:CwithInitialString
  10843. "ctorFullExample.C": 18:        In A:somDefaultInit
  10844. "ctorFullExample.C": 62:        In B:BwithInitialValue
  10845. "ctorFullExample.C": 182: In C:somPrintSelf
  10846. "./ctorFullExample.xih": 292:     In A:A_get_a
  10847. "./ctorFullExample.xih": 655:     In B:B_get_b
  10848. "./ctorFullExample.xih": 1104:      In C:C_get_c
  10849. {an instance of C at location 20065448 with (a=1, b=55, c=66)}
  10850. "ctorFullExample.C": 169: In C:somDestruct
  10851. "ctorFullExample.C": 35:        In A:somDestruct
  10852. "ctorFullExample.C": 97:        In B:somDestruct
  10853.  
  10854.  
  10855. ΓòÉΓòÉΓòÉ 7.8.4. Customizing the initialization of class objects ΓòÉΓòÉΓòÉ
  10856.  
  10857. As described previously, the somDefaultInit method can be overridden to 
  10858. customize the initialization of objects. Because classes are objects, 
  10859. somDefaultInit is also invoked on classes when they are first created 
  10860. (generally by invoking the somNew method on a metaclass). For a class object, 
  10861. however, somDefaultInit normally just sets the name of the class to "unknown," 
  10862. after which the somInitMIClass method must be used for the major portion of 
  10863. class initialization. Of course, metaclasses can override somDefaultInit to 
  10864. initialize introduced class variables that require no arguments for their 
  10865. initialization. 
  10866.  
  10867. Note: Because somNew does not call somInitMIClass, class objects returned from 
  10868. invocations of somNew on a metaclass are not yet useful class objects. 
  10869.  
  10870. The somInitMIClass method (introduced by SOMClass) is invoked on a new class 
  10871. object using arguments to indicate the class name and the parent classes from 
  10872. which inheritance is desired (among other arguments). This invocation is made 
  10873. by whatever routine is used to initialize the class. (For SOM classes using the 
  10874. C or C++ implementation bindings, this is handled by the somBuildClass 
  10875. procedure, which is called by the implementation bindings automatically.) The 
  10876. somInitMIClass method is often overridden by a metaclass to influence 
  10877. initialization of new classes in some way. Typically, the overriding procedure 
  10878. begins by making parent method calls, and then performs additional actions 
  10879. thereafter. 
  10880.  
  10881. However, without use of the Cooperative Metaclass to guarantee correct 
  10882. operation of SOMobjects in general, none of the methods introduced by SOMClass 
  10883. should be overridden. As a result, customizing the initialization of class 
  10884. objects (other than through overriding somDefaultInit for initialization of 
  10885. class variables) is not recommended in SOMobjects 2.1.  Users whose 
  10886. applications require this should request access to the experimental Cooperative 
  10887. Metaclass used to implement the SOMobjects Metaclass Framework.  But, 
  10888. metaclasses implemented using the experimental Cooperative Metaclass may 
  10889. require reprogramming when SOMobjects introduces an officially supported 
  10890. Cooperative Metaclass. 
  10891.  
  10892.  
  10893. ΓòÉΓòÉΓòÉ 7.9. Creating a SOM Class Library ΓòÉΓòÉΓòÉ
  10894.  
  10895. One of the principal advantages of SOM is that it makes "black box" (or binary) 
  10896. reusability possible. Consequently, SOM classes are frequently packaged and 
  10897. distributed as class libraries. A class library  holds the actual 
  10898. implementation of one or more classes and can be dynamically loaded and 
  10899. unloaded as needed by applications. Importantly, class libraries can also be 
  10900. replaced independently of the applications  that use them and, provided that 
  10901. the class implementor observes simple SOM guidelines for preserving binary 
  10902. compatibility, can evolve and expand over time. 
  10903.  
  10904.  
  10905. ΓòÉΓòÉΓòÉ 7.9.1. General guidelines for class library designers ΓòÉΓòÉΓòÉ
  10906.  
  10907. One of the most important features of SOM is that it allows you to build and 
  10908. distribute class libraries in binary form. Because there is no "fragile base 
  10909. class" problem in SOM, client programs that use your libraries (by subclassing 
  10910. your classes or by invoking the methods in your classes) will not need to be 
  10911. recompiled if you later produce a subsequent version of the library, provided 
  10912. you adhere to some simple restrictions. 
  10913.  
  10914.    1. You should always maintain the syntax and the semantics of your existing 
  10915.       interfaces. This means that you cannot take away any exposed 
  10916.       capabilities, nor add or remove arguments for any of your public methods. 
  10917.  
  10918.    2. Always maintain the releaseorder list, so that it never changes except 
  10919.       for additions to the end. The releaseorder should contain all of your 
  10920.       public methods, the one or two methods that correspond to each public 
  10921.       attribute, and a placeholder for each private method (or private 
  10922.       attribute method). 
  10923.  
  10924.    3. Assign a higher minorversion number for each subsequent release of a 
  10925.       class, so that client programmers can determine whether a new feature is 
  10926.       present or not. Change the majorversion number only when you deliberately 
  10927.       wish to break binary compatibility. (See the topic "Modifier statements" 
  10928.       in Chapter 4, "SOM IDL and the SOM Compiler" for explanations of the 
  10929.       releaseorder, minorversion and majorversion modifiers.) 
  10930.  
  10931.    4. Under Windows, you should avoid the use of methods or attributes that 
  10932.       return structures. In the DOS/Windows environment, there is no 
  10933.       universally agreed upon calling convention for returning structures that 
  10934.       is observed by all popular language compilers. Instead, define attributes 
  10935.       that return pointers to structures, or define methods that take an out 
  10936.       parameter for passing a structure back to the caller. 
  10937.  
  10938.       Note that you can always avoid this problem in classes of your own 
  10939.       design. However, some of the attributes and methods in the frameworks 
  10940.       that come with the SOMobjects Toolkit do  return structures. Many of 
  10941.       these are dictated by the OMG CORBA standard, and could not be avoided. 
  10942.       For each of these methods two common calling conventions have been 
  10943.       implemented: 
  10944.  
  10945.         o  Microsoft convention, where the address of the structure is returned 
  10946.            in AX:DX, and 
  10947.  
  10948.         o  Borland convention, where the caller provides a hidden first 
  10949.            argument to receive a copy of the returned structure. 
  10950.  
  10951.           No action is needed on your part to use the Microsoft convention. To 
  10952.           use the Borland convention, you should include the file BCCSTRUC.H 
  10953.           following any other "includes" of SOM headers. 
  10954.  
  10955.    5. With each new release of your class library, you have significant degrees 
  10956.       of freedom to change much of the implementation detail. You can add to or 
  10957.       reorganize your instance variables, add new public or private methods, 
  10958.       inject new base classes into your class hierarchies, change metaclasses 
  10959.       to more derived ones, and relocate the implementation of methods upward 
  10960.       in your class hierarchies. Provided you always retain the same 
  10961.       capabilities and semantics that were present in your first release, none 
  10962.       of these changes will break the client programs that use your libraries. 
  10963.  
  10964.  
  10965. ΓòÉΓòÉΓòÉ 7.9.2. Types of class libraries ΓòÉΓòÉΓòÉ
  10966.  
  10967. Since class libraries are not programs, users cannot execute them directly. To 
  10968. enable users to make direct use of your classes, you must also provide one or 
  10969. more programs that create the classes and objects that the user will need. This 
  10970. section describes how to package your classes in a SOM class library and what 
  10971. you must do to make the contents of the library accessible to other programs. 
  10972.  
  10973. On AIX, class libraries are actually produced as AIX shared libraries, whereas 
  10974. on OS/2 or Windows they appear as dynamically-linked libraries (or DLLs). The 
  10975. term "DLL" is sometimes used to refer to either an AIX, an OS/2, or a Windows 
  10976. class library, and (by convention only) the file suffix ".dll" is used for SOM 
  10977. class libraries on all platforms. 
  10978.  
  10979. A program can use a class library containing a given class or classes in one of 
  10980. two ways: 
  10981.  
  10982.    1. If the programmer employs the SOM bindings to instantiate the class and 
  10983.       invoke its methods, the resulting client program contains static 
  10984.       references to the class. The operating system will automatically resolve 
  10985.       those references when the program is loaded, by also loading the 
  10986.       appropriate class library. 
  10987.  
  10988.    2. If the programmer uses only the dynamic SOM mechanisms for finding the 
  10989.       class and invoking its methods (for example, by invoking somFindClass, 
  10990.       somFindMethod, somLookupMethod, somDispatch, somResolveByName,and so 
  10991.       forth), the resulting client program does not contain any static 
  10992.       references to the class library. Thus, SOM will load the class library 
  10993.       dynamically during execution of the program. Note: For SOM to be able to 
  10994.       load the class library, the dllname modifier must be set in the .idl 
  10995.       file. (See the topic "Modifier statements" in Chapter 4, "SOM IDL and the 
  10996.       SOM Compiler.") 
  10997.  
  10998.  Because the provider of a class library cannot predict which of these ways a 
  10999.  class will be used, SOM class libraries must be built such that either usage 
  11000.  is possible. The first case above requires the class library to export the 
  11001.  entry points needed by the SOM bindings, whereas the second case requires the 
  11002.  library to provide an initialization function to create the classes it 
  11003.  contains. The following topics discuss each case. 
  11004.  
  11005.  
  11006. ΓòÉΓòÉΓòÉ 7.9.3. Building export files ΓòÉΓòÉΓòÉ
  11007.  
  11008. The SOM Compiler provides an "exp" emitter for AIX and a "def" emitter for OS/2 
  11009. to produce the necessary exported symbols for each class. For example, to 
  11010. generate the necessary exports for a class "A", issue the sc or somc command 
  11011. with one of the following -s options. (For a discussion of the sc or somc 
  11012. command and options, see "Running the SOM Compiler" in Chapter 4, "SOM IDL and 
  11013. the SOM Compiler.") 
  11014.  
  11015. For AIX, this command generates an "a.exp" file: 
  11016.  
  11017.    sc -sexp a.idl
  11018.  
  11019. For OS/2, this command generates an "a.def" file: 
  11020.  
  11021.    sc -sdef a.idl
  11022.  
  11023. Typically, a class library contains multiple classes. To produce an appropriate 
  11024. export file for each class that the library will contain, you can create a new 
  11025. export file for the library itself by combining the exports from each "exp" or 
  11026. "def" file into a single file. Following are examples of a combined export 
  11027. "exp" file for AIX and a combined "def" file for OS/2. Each example illustrates 
  11028. a class library composed of three classes, "A", "B", and "C". 
  11029.  
  11030. AIX "exp" file: 
  11031.  
  11032.    #! abc.dll
  11033.    ACClassData
  11034.    AClassData
  11035.    ANewClass
  11036.    BCClassData
  11037.    BClassData
  11038.    BNewClass
  11039.    CCClassData
  11040.    CClassData
  11041.    CNewClass
  11042.  
  11043. OS/2 "def" file: 
  11044.  
  11045.    LIBRARY abc INITINSTANCE
  11046.    DESCRIPTION 'abc example class library'
  11047.    PROTMODE
  11048.    DATA MULTIPLE NONSHARED LOADONCALL
  11049.    EXPORTS
  11050.      ACClassData
  11051.      AClassData
  11052.      ANewClass
  11053.      BCClassData
  11054.      BClassData
  11055.      BNewClass
  11056.      CCClassData
  11057.      CClassData
  11058.      CNewClass
  11059.  
  11060. Other symbols in addition to those generated by the "def" or "exp" emitter can 
  11061. be included if needed, but this is not required by SOM. One feature of SOM is 
  11062. that a class library needs no more than three exports per class (by contrast, 
  11063. many OOP systems require externals for every method as well). One required 
  11064. export is the name of a procedure to create the class (<className>NewClass), 
  11065. and the others are two external data structures that are referenced by the SOM 
  11066. bindings. 
  11067.  
  11068.  
  11069. ΓòÉΓòÉΓòÉ 7.9.4. Specifying the initialization function ΓòÉΓòÉΓòÉ
  11070.  
  11071. An initialization function for the class library must be provided to support 
  11072. dynamic loading of the library by the SOM Class Manager. The SOM Class Manager 
  11073. expects that, whenever it loads a class library, the initialization function 
  11074. will create and register class objects for all of the classes contained in the 
  11075. library. 
  11076.  
  11077. These classes are then managed as a group (called an affinity group). One class 
  11078. in the affinity group has a privileged position--namely, the class that was 
  11079. specifically requested when the library was loaded. If that class (that is, the 
  11080. class that caused loading to occur) is subsequently unregistered, the SOM Class 
  11081. Manager will automatically unregister all of the other classes in the affinity 
  11082. group as well, and will unload the class library. Similarly, if the SOM Class 
  11083. Manager is explicitly asked to unload the class library, it will also 
  11084. automatically unregister and free all of the classes in the affinity group. 
  11085.  
  11086. It is the responsibility of the class-library creator to supply the 
  11087. initialization function. The interface to the initialization function is given 
  11088. by the following C/C++ prototype: 
  11089.  
  11090. #ifdef __IBMC__
  11091.   #pragma linkage (SOMInitModule, system)
  11092. #endif
  11093.  
  11094. SOMEXTERN void  SOMLINK SOMInitModule ( long majorVersion,
  11095.                                         long minorVersion,
  11096.                                         string className);
  11097.  
  11098. The parameters provided to this function are the className and the major/minor 
  11099. version numbers of the class that was requested when the library was loaded 
  11100. (that is, the class that caused loading). The initialization function is free 
  11101. to use or to disregard this information; nevertheless, if it fails to create a 
  11102. class object with the required name, the SOM Class Manager considers the load 
  11103. to have failed. As a rule of thumb, however, if the initialization function 
  11104. invokes a <className>NewClass procedure for each class in the class library, 
  11105. this condition will always be met. Consequently, the parameters supplied to the 
  11106. initialization function are not needed in most cases. 
  11107.  
  11108. Here is a typical class-library initialization function, written in C, for a 
  11109. library with three classes ("A", "B", and "C"): 
  11110.  
  11111.    #include "a.h"
  11112.    #include "b.h"
  11113.    #include "c.h"
  11114.    #ifdef __IBMC__
  11115.      #pragma linkage (SOMInitModule, system)
  11116.    #endif
  11117.  
  11118.    SOMEXTERN void  SOMLINK SOMInitModule (long majorVersion,
  11119.                              long minorVersion, string className)
  11120.    {
  11121.        SOM_IgnoreWarning (majorVersion);  /* This function makes */
  11122.        SOM_IgnoreWarning (minorVersion);  /* no use of the passed */
  11123.        SOM_IgnoreWarning (className);     /* arguments.   */
  11124.        ANewClass (A_MajorVersion, A_MinorVersion);
  11125.        BNewClass (B_MajorVersion, B_MinorVersion);
  11126.        CNewClass (C_MajorVersion, C_MinorVersion);
  11127.    }
  11128.  
  11129. The source code for the initialization function can be added to one of the 
  11130. implementation files for the classes in the library, or you can put it in a 
  11131. separate file and compile it independently. 
  11132. Using Windows class libraries 
  11133.  
  11134. Some additional considerations apply for Windows class libraries: Each class 
  11135. library must also supply a Windows LibMain function. The LibMain function is 
  11136. invoked automatically whenever a Windows DLL is loaded, and is responsible for 
  11137. identifying the library and its SOMInitModule function to the SOM Kernel. Here 
  11138. is an example of a typical Windows LibMain function for a SOM class library as 
  11139. it would appear in a C or C++ program: 
  11140.  
  11141.     #include <som.h>
  11142.     SOMEXTERN void SOMLINK SOMInitModule (long majorVersion,
  11143.                                           long minorVersion,
  11144.                                           string className);
  11145.  
  11146.     #include <windows.h>
  11147.     int CALLBACK LibMain (HINSTANCE inst,
  11148.                           WORD ds,
  11149.                           WORD Heapsize,
  11150.                           LPSTR cmdLine)
  11151.     {
  11152.         SOM_IgnoreWarning (inst);
  11153.         SOM_ignoreWarning (ds);
  11154.         SOM_IgnoreWarning (heapSize);
  11155.         SOM_IgnoreWarning (cmdLine);
  11156.  
  11157.         SOM_ClassLibrary ("xyz.dll");
  11158.         return 1;  /* Indicate success to loader */
  11159.     }
  11160.  
  11161. The only operative statement in the LibMain function is the macro 
  11162. SOM_ClassLibrary, which identifies the actual file name of the library as it 
  11163. would appear in a Windows LoadLibrary call, and internally generates a 
  11164. reference to the library 's SOMInitModule function. This information is passed 
  11165. to the SOM Kernel, which in turn registers the library and schedules the 
  11166. execution of the SOMInitModule function. 
  11167.  
  11168. Typically, the SOM Kernel invokes the SOMInitModule function of each statically 
  11169. loaded class library during execution of the SOM_MainProgram macro within the 
  11170. using application; otherwise, SOMInitModule is invoked immediately upon 
  11171. completio of the dynamic loading of a class library by an already executing 
  11172. application. Regardless of the loading mechanism, the SOM Kernel guarantees 
  11173. that the SOMInitModule function executes exactly once for each class library. 
  11174.  
  11175.  
  11176. ΓòÉΓòÉΓòÉ 7.9.5. Creating the import library ΓòÉΓòÉΓòÉ
  11177.  
  11178. Finally, for each of your class libraries, you should create an import library 
  11179. that can be used by client programs (or by other class libraries that use your 
  11180. classes) to resolve the references to your classes. 
  11181.  
  11182. Here is an example illustrating all of the steps required to create a class 
  11183. library ("abc.dll") that contains the three classes "A", "B", and "C". 
  11184.  
  11185.    1. Compile all of the implementation files for the classes that will be 
  11186.       included in the library. Include the initialization function also. 
  11187.  
  11188.       For AIX written in C: 
  11189.  
  11190.               xlc -I. -I$SOMBASE/include -c a.c
  11191.               xlc -I. -I$SOMBASE/include -c b.c
  11192.               xlc -I. -I$SOMBASE/include -c c.c
  11193.               xlc -I. -I$SOMBASE/include -c initfunc.c
  11194.  
  11195.       For AIX written in C++: 
  11196.  
  11197.               xlC -I. -I$SOMBASE/include -c a.C
  11198.               xlC -I. -I$SOMBASE/include -c b.C
  11199.               xlC -I. -I$SOMBASE/include -c c.C
  11200.               xlC -I. -I$SOMBASE/include -c initfunc.C
  11201.  
  11202.       For OS/2 written in C: 
  11203.  
  11204.                icc -I. -I%SOMBASE%\include -Ge- -c a.c
  11205.                icc -I. -I%SOMBASE%\include -Ge- -c b.c
  11206.                icc -I. -I%SOMBASE%\include -Ge- -c c.c
  11207.                icc -I. -I%SOMBASE%\include -Ge- -c initfunc.c
  11208.  
  11209.       Note:  The "-GE" option is used only with the IBM compiler.  It indicates 
  11210.              that the object files will go into a DLL. 
  11211.  
  11212.       For OS/2 written in C++: 
  11213.  
  11214.                icc -I. -I%SOMBASE%\include -Ge- -c a.cpp
  11215.                icc -I. -I%SOMBASE%\include -Ge- -c b.cpp
  11216.                icc -I. -I%SOMBASE%\include -Ge- -c c.cpp
  11217.                icc -I. -I%SOMBASE%\include -Ge- -c initfunc.cpp
  11218.  
  11219.       Note:  The "-Ge" option is used only with the IBM compiler.  It indicates 
  11220.              that the object files will go into a DLL. 
  11221.  
  11222.    2. Produce an export file for each class. 
  11223.  
  11224.       For AIX: 
  11225.  
  11226.                sc -sexp a.idl b.idl c.idl
  11227.  
  11228.       For OS/2: 
  11229.  
  11230.                sc -sdef a.idl b.idl c.idl
  11231.  
  11232.    3. Manually combine the exported symbols into a single file. 
  11233.  
  11234.       For AIX, create a file "abc.exp" from "a.exp", "b.exp", and "c.exp". Do 
  11235.       not include the initialization function (SOMInitModule) in the export 
  11236.       list. 
  11237.  
  11238.        For OS/2, create a file "abc.def" from "a.def", "b.def", and  c.def". 
  11239.       Include the initialization function (SOMInitModule) in the export list, 
  11240.       so that all classes will be initialized automatically, unless your 
  11241.       initialization function does not need arguments and you explicitly invoke 
  11242.       it yourself from an OS/2 DLL initialization routine. 
  11243.  
  11244.    4. Using the object files and the export file, produce a binary class 
  11245.       library. 
  11246.  
  11247.       For AIX: 
  11248.  
  11249.                ld -o abc.dll -bE:abc.exp -e SOMInitModule -H512 -T512 \
  11250.                   a.o b.o c.o initfunc.o -lc -L$SOMBASE/lib -lsomtk
  11251.  
  11252.       The -o option assigns a name to the class library ("abc.dll"). The -bE: 
  11253.       option designates the file with the appropriate export list. The -e 
  11254.       option designates SOMInitModule as the initialization function. The -H 
  11255.       and -T options must be supplied as shown; they specify the necessary 
  11256.       alignment information for the text and data portions of your code. The -l 
  11257.       options name the specific libraries needed by your classes. If your 
  11258.       classes make use of classes in other class libraries, include a -l option 
  11259.       for each of these also. The ld command looks for a library named 
  11260.       "lib<x>.a", where <x> is the name provided with each -l option. The -L 
  11261.       option specifies the directory where the "somtk" library resides. 
  11262.  
  11263.       For OS/2: 
  11264.  
  11265.                set LIB=%SOMBASE%\lib;%LIB%
  11266.                link386 /noi /packd /packc /align:16 /exepack \
  11267.                    a.obj b.obj c.obj initfunc.obj, abc.dll,,os2386 somtk, \
  11268.                    abc.def
  11269.  
  11270.       If your classes make use of classes in other class libraries, include the 
  11271.       names of their import libraries immediately after "somtk" (before the 
  11272.       next comma). 
  11273.  
  11274.    5. Create an import library that corresponds to the class library, so that 
  11275.       programs and other class libraries can use (import) your classes. 
  11276.  
  11277.  For AIX: 
  11278.  
  11279.      ar ruv libabc.a abc.exp    Note the use of the  ".exp" file, not a ".o" file
  11280.  
  11281.  The first filename ("libabc.a") specifies the name to give to the import 
  11282.  library. It should be of the form "lib<x>.a", where <x> represents your class 
  11283.  library. The second filename ("abc.exp") specifies the exported symbols to 
  11284.  include in the import library. 
  11285.  
  11286.  Caution: Although AIX shared libraries can be placed directly into an archive 
  11287.  file ("lib<x>.a"), this is not recommended! A SOM class library should have a 
  11288.  corresponding import library constructed directly from the combined export 
  11289.  file. 
  11290.  
  11291.  For OS/2: 
  11292.  
  11293.      implib /noi abc.lib abc.def
  11294.  
  11295.  The first filename ("abc.lib") specifies the name for the import library and 
  11296.  should always have a suffix of ".lib". The second filename ("abc.def") 
  11297.  specifies the exported symbols to include in the import library. 
  11298.  
  11299.  Note:  SOMInitModule should be included in the <x>.dll but not in <x>.lib.  If 
  11300.         you are using an export file that contains the symbol SOMInitModule, 
  11301.         delete it first; SOMInitModule should not appear in your import library 
  11302.         because it need not be exported. SOMInitModule should be included when 
  11303.         creating your file <x>.dll because all classes in the <x>.dll will be 
  11304.         initialized. 
  11305.  
  11306.  
  11307. ΓòÉΓòÉΓòÉ 7.10. Customizing Memory Management ΓòÉΓòÉΓòÉ
  11308.  
  11309. SOM is designed to be policy free and highly adaptable. Most of the SOM 
  11310. behavior can be customized by subclassing the built-in classes and overriding 
  11311. their methods, or by replacing selected functions in the SOM run-time library 
  11312. with application code. This chapter contains more advanced topics describing 
  11313. how to customize the following aspects of SOM behavior: memory management, 
  11314. dynamic class loading and unloading, character output, error handling, and 
  11315. method resolution. Information on customizing Distributed SOM is provided in 
  11316. Chapter 6. 
  11317.  
  11318. The memory management functions used by the SOM run-time environment are a 
  11319. subset of those supplied in the ANSI C standard library. They have the same 
  11320. calling interface and return the equivalent types of results as their ANSI C 
  11321. counterparts, but include some supplemental error checking. Errors detected in 
  11322. these functions result in the invocation of the error-handling function to 
  11323. which SOMError points. 
  11324.  
  11325. The correspondence between the SOM memory-management function variables and 
  11326. their ANSI standard library equivalents is given in Table below. 
  11327.  
  11328. The following table contains the memory-management functions. 
  11329.  
  11330. ΓöîΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÉ
  11331. ΓöéSOM        ANSI       Return     Argument  Γöé
  11332. ΓöéFunction   Standard C type       types     Γöé
  11333. ΓöéVariable   Library                         Γöé
  11334. Γöé           Function                        Γöé
  11335. Γöé                                           Γöé
  11336. ΓöéSOMCalloc  calloc( )  somToken   size_t,   Γöé
  11337. Γöé                                 size_t    Γöé
  11338. Γöé                                           Γöé
  11339. ΓöéSOMFree    free( )    void       somToken  Γöé
  11340. Γöé                                           Γöé
  11341. ΓöéSOMMalloc  malloc( )  somToken   size_t    Γöé
  11342. Γöé                                           Γöé
  11343. ΓöéSOMRealloc realloc( ) somToken   somToken, Γöé
  11344. Γöé                                 size_t    Γöé
  11345. ΓööΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÿ
  11346.  
  11347. An application program can replace SOM's memory management functions with its 
  11348. own memory management functions to change the way SOM allocates memory (for 
  11349. example, to perform all memory allocations as suballocations in a shared memory 
  11350. heap). This replacement is possible because SOMCalloc, SOMMalloc, SOMRealloc, 
  11351. and SOMFree are actually global variables that point to SOM's default memory 
  11352. management functions, rather than being the names of the functions themselves. 
  11353. Thus, an application program can replace SOM's default memory management 
  11354. functions by assigning the entry-point address of the user-defined memory 
  11355. management function to the appropriate global variable. For example, to replace 
  11356. the default free procedure with the user-defined function MyFree (which must 
  11357. have the same signature as the ANSI C free function), an application program 
  11358. would require the following code: 
  11359.  
  11360. #include <som.h>
  11361. /* Define a replacement routine: */
  11362. void myFree (somToken memPtr)
  11363. {
  11364.      (Customized code goes here)
  11365. }
  11366. ...
  11367. SOMFree = MyFree;
  11368.  
  11369. Note:  In general, all of these routines should be replaced as a group. For 
  11370.        instance, if an application supplies a customized version of SOMMalloc, 
  11371.        it should also supply corresponding SOMCalloc, SOMFree, and SOMRealloc 
  11372.        functions that conform to this same style of memory management. 
  11373.  
  11374.  
  11375. ΓòÉΓòÉΓòÉ 7.11. Customizing Class Loading and Unloading ΓòÉΓòÉΓòÉ
  11376.  
  11377. SOM uses three routines that manage the loading and unloading of class 
  11378. libraries (referred to here as DLLs). These routines are called by the 
  11379. SOMClassMgrObject  as it dynamically loads and registers classes. If 
  11380. appropriate, the rules that govern the loading and unloading of DLLs can be 
  11381. modified, by replacing these functions with alternative implementations. 
  11382.  
  11383.  
  11384. ΓòÉΓòÉΓòÉ 7.11.1. Customizing class initialization ΓòÉΓòÉΓòÉ
  11385.  
  11386. The SOMClassInitFuncName function has the following signature: 
  11387.  
  11388. string  (*SOMClassInitFuncName) ( ); 
  11389.  
  11390. This function returns the name of the function that will initialize (create 
  11391. class objects for) all of the classes that are packaged together in a single 
  11392. class library. (This function name applies to all class libraries loaded by the 
  11393. SOMClassMgrObject.) The SOM-supplied version of SOMClassInitFuncName returns 
  11394. the string " SOMInitModule".  The interface to the library initialization 
  11395. function is described under the topic "Creating a SOM Class Library" earlier in 
  11396. this chapter. 
  11397.  
  11398.  
  11399. ΓòÉΓòÉΓòÉ 7.11.2. Customizing DLL loading ΓòÉΓòÉΓòÉ
  11400.  
  11401. To dynamically load a SOM class, the SOMClassMgrObject  calls the function 
  11402. pointed to by the global variable SOMLoadModule to load the DLL containing the 
  11403. class. The reason for making public the SOMLoadModule function (and the 
  11404. following SOMDeleteModule function) is to reveal the boundary where SOM touches 
  11405. the operating system. Explicit invocation of these functions is never required. 
  11406. However, they are provided to allow class implementors to insert their own code 
  11407. between the operating system and SOM, if desired. The  SOMLoadModule function 
  11408. has the following signature: 
  11409.  
  11410.  long  (*SOMLoadModule) 
  11411.  
  11412.                                                     ( string className,
  11413.                                                      string fileName,
  11414.                                                      string functionName,
  11415.                                                      long majorVersion,
  11416.                                                      long minorVersion,
  11417.                                                      somToken *modHandle);
  11418.  
  11419.  This function is responsible for loading the DLL containing the SOM class 
  11420.  className and returning either the value zero (for success) or a nonzero 
  11421.  system-specific error code. The output argument modHandle is used to return a 
  11422.  token that can subsequently be used by the DLL-unloading routine (described 
  11423.  below) to unload the DLL. The default DLL-loading routine returns the DLL's 
  11424.  module handle in this argument. The remaining arguments are used as follows: 
  11425.  
  11426.  Argument                 Usage 
  11427.  
  11428.  fileName                 The file name of the DLL to be loaded, which can be 
  11429.                           either a simple name or a full path name. 
  11430.  
  11431.  functionName             The name of the routine to be called after the DLL is 
  11432.                           successfully loaded by the SOMClassMgrObject. This 
  11433.                           routine is responsible for creating the class objects 
  11434.                           for the class(es) contained in the DLL. Typically, 
  11435.                           this argument has the value "SOMInitModule", which is 
  11436.                           obtained from the function SOMClassInitFuncName 
  11437.                           described above. If no SOMInitModule entry exists in 
  11438.                           the DLL, the default DLL-loading routine looks in the 
  11439.                           DLL for a procedure with the name <className>NewClass 
  11440.                           instead. If neither entry point can be found, the 
  11441.                           default DLL-loading routine fails. 
  11442.  
  11443.  majorVersion             The major version number to be passed to the class 
  11444.                           initialization function in the DLL (specified by the 
  11445.                           functionName argument). 
  11446.  
  11447.  minorVersion             The minor version number to be passed to the class 
  11448.                           initialization function in the DLL (specified by the 
  11449.                           functionName argument). 
  11450.  
  11451.  An application program can replace the default DLL-loading routine by 
  11452.  assigning the entry point address of the new DLL-loading function (such as 
  11453.  MyLoadModule) to the global variable SOMLoadModule, as follows: 
  11454.  
  11455.   #include <som.h>
  11456.   /* Define a replacement routine: */
  11457.   long myLoadModule (string className, string fileName,
  11458.                      string functionName, long majorVersion,
  11459.                      long minorVersion, somToken *modHandle)
  11460.   {
  11461.        (Customized code goes here)
  11462.   }
  11463.   ...
  11464.   SOMLoadModule = MyLoadModule;
  11465.  
  11466.  
  11467. ΓòÉΓòÉΓòÉ 7.11.3. Customizing DLL unloading ΓòÉΓòÉΓòÉ
  11468.  
  11469. To unload a SOM class, the SOMClassMgrObject calls the function pointed to by 
  11470. the global variable SOMDeleteModule. The SOMDeleteModule function has the 
  11471. following signature: 
  11472.  
  11473. long  (*SOMDeleteModule)  (in somToken modHandle); 
  11474.  
  11475. This function is responsible for unloading the DLL designated by the modHandle 
  11476. parameter and returning either zero (for success) or a nonzero system-specific 
  11477. error code. The parameter modHandle contains the value returned by the DLL 
  11478. loading routine (described above) when the DLL was loaded. 
  11479.  
  11480. An application program can replace the default DLL-unloading routine by 
  11481. assigning the entry point address of the new DLL-unloading function (such as, 
  11482. MyDeleteModule) to the global variable SOMDeleteModule, as follows: 
  11483.  
  11484. #include <som.h>
  11485. /* Define a replacement routine: */
  11486. long myDeleteModule (somToken modHandle)
  11487. {
  11488.      (Customized code goes here)
  11489. }
  11490. ...
  11491. SOMDeleteModule = MyDeleteModule;
  11492.  
  11493.  
  11494. ΓòÉΓòÉΓòÉ 7.12. Customizing Character Output ΓòÉΓòÉΓòÉ
  11495.  
  11496. The SOM character-output function is invoked by all of the SOM error-handling 
  11497. and debugging macros whenever a character must be generated (see "Debugging" 
  11498. and "Exceptions and error handling" in Using SOM Classes in Client Programs). 
  11499. The default character-output routine, pointed to by the global variable 
  11500. SOMOutCharRoutine, simply writes the character to "stdout", then returns 1 if 
  11501. successful, or 0 otherwise. 
  11502.  
  11503. For convenience, SOMOutCharRoutine is supplemented by the somSetOutChar 
  11504. function.  The somSetOutChar function enables each task to have a customized 
  11505. character output routine, thus it is often preferred for changing the output 
  11506. routine called by somPrintf (because SOMOutChrRoutine would remain in effect 
  11507. for subsequent tasks).  On Windows, the somSetOutChar function is required 
  11508. (rather than SOMOutCharRoutine); it is optional on other operating systems. 
  11509.  
  11510. An application programmer might wish to supply a customized replacement routine 
  11511. to: 
  11512.  
  11513.    o  Direct the output to stderr, 
  11514.  
  11515.    o  Record the output in a log file, 
  11516.  
  11517.    o  Collect characters and handle them in larger chunks, 
  11518.  
  11519.    o  Send the output to a window to display it, 
  11520.  
  11521.    o  Place the output in a clipboard, or 
  11522.  
  11523.    o  Some combination of these. 
  11524.  
  11525.  With SOMOutCharRoutine, an application program would use code similar to the 
  11526.  following to install the replacement routine: 
  11527.  
  11528.   #include <som.h>
  11529.   #pragma linkage(myCharacterOutputRoutine, system)
  11530.   /* Define a replacement routine: */
  11531.   int SOMLINK myCharacterOutputRoutine (char c)
  11532.   {
  11533.        (Customized code goes here)
  11534.   }
  11535.  
  11536.   /* After the next stmt all output */
  11537.   /* will be sent to the new routine   */
  11538.   SOMOutCharRoutine = myCharacterOutputRoutine;
  11539.  
  11540.  With somSetOutChar, an application program would use code similar to the 
  11541.  following to install the replacement routine: 
  11542.  
  11543.   #include <som.h>
  11544.   static int irOutChar(char c);
  11545.  
  11546.   static int irOutChar(char c)
  11547.   {
  11548.       (Customized code goes here)
  11549.   }
  11550.  
  11551.   main (...)
  11552.   {
  11553.       ...
  11554.   somSetOutChar((somTD_SOMOutCharRoutine *) irOutChar);
  11555.   }
  11556.  
  11557.  
  11558. ΓòÉΓòÉΓòÉ 7.13. Customizing Error Handling ΓòÉΓòÉΓòÉ
  11559.  
  11560. When an error occurs within any of the SOM-supplied methods or functions, an 
  11561. error-handling procedure is invoked. The default error-handling procedure 
  11562. supplied by SOM, pointed to by the global variable SOMError, has the following 
  11563. signature: 
  11564.  
  11565. void  (*SOMError) (int errorCode ,  string fileName,  int lineNum ); 
  11566.  
  11567. The default error-handling procedure inspects the  errorCode  argument and 
  11568. takes appropriate action, depending on the last decimal digit of errorCode (see 
  11569. "Exceptions and error handling" in Using SOM Classes in Client Programs for a 
  11570. discussion of error classifications). In the default error handler, fatal 
  11571. errors terminate the current process. The remaining two arguments (fileName and 
  11572. lineNum), which indicate the name of the file and the line number within the 
  11573. file where the error occurred, are used to produce an error message. 
  11574.  
  11575. An application programmer might wish to replace the default error handler with 
  11576. a customized error-handling routine to: 
  11577.  
  11578.    o  Record errors in a way appropriate to the particular application, 
  11579.  
  11580.    o  Inform the user through the application's user interface, 
  11581.  
  11582.    o  Attempt application-level recovery by restarting at a known point, or 
  11583.  
  11584.    o  Shut down the application. 
  11585.  
  11586.  An application program would use code similar to the following to install the 
  11587.  replacement routine: 
  11588.  
  11589.   #include <som.h>
  11590.   /* Define a replacement routine: */
  11591.   void myErrorHandler (int errorCode, string fileName, int lineNum)
  11592.   {
  11593.        (Customized code goes here)
  11594.   }
  11595.   ...
  11596.   /* After the next stmt all errors */
  11597.   /* will be handled by the new routine   */
  11598.   SOMError = myErrorHandler;
  11599.  
  11600.  When any error condition originates within the classes supplied with SOM, SOM 
  11601.  is left in an internally consistent state. If appropriate, an application 
  11602.  program can trap errors with a customized error-handling procedure and then 
  11603.  resume with other processing. Application programmers should be aware, 
  11604.  however, that all methods within the SOM run-time library behave atomically. 
  11605.  That is, they either succeed or fail; but if they fail, partial effects are 
  11606.  undone wherever possible. This is done so that all SOM methods remain usable 
  11607.  and can be re-executed following an error. 
  11608.  
  11609.  
  11610. ΓòÉΓòÉΓòÉ 7.14. Customizing Mutual Exclusion Services (Thread Safety) ΓòÉΓòÉΓòÉ
  11611.  
  11612. The SOM kernel and the other SOMobjects frameworks (DSOM, Persistence, 
  11613. Replication, and so on), have been made thread safe with respect to 
  11614. multi-threaded processes. As used here, "thread safe" means that the SOMobjects 
  11615. run time has been implemented using mutual exclusion semaphores to protect 
  11616. sections of the code which must only be executed by a single thread in a 
  11617. multi-threaded application process at one time. 
  11618.  
  11619. Some operating systems provide native multi-threading (for example, OS/2.) On 
  11620. other operating systems that do not support native multi-threading (such as, 
  11621. AIX 3.2), thread support may be provided as part of particular programming 
  11622. environments (like DCE) or libraries. 
  11623.  
  11624. It is vital that SOM employ the mutex services that are provided by the thread 
  11625. package used by the application. Consequently, SOM provides a mechanism for 
  11626. defining and customizing mutex services. 
  11627.  
  11628. Five mutex service functions are used to implement mutual exclusion in SOM. 
  11629. These functions are called indirectly via the global pointer variables defined 
  11630. below. A somToken parameter (called "sem" below) is used as a generic "handle 
  11631. to refer to a mutex semaphore--usually it is a pointer to a mutex semaphore 
  11632. variable or data structure. The actual representation of the mutex semaphore is 
  11633. hidden by the functions. 
  11634.  
  11635. unsigned long (*SOMCreateMutexSem)(somToken *sem);
  11636.  
  11637.       The referenced function creates a mutex semaphore, whose handle is 
  11638.       returned as an output parameter in the somToken variable identified by 
  11639.       "sem". 
  11640.  
  11641.       If the call succeeds, a 0 is returned.  Otherwise, a non-zero error code 
  11642.       is returned. 
  11643.  
  11644.   unsigned long (*SOMRequestMutexSem)(somToken sem);
  11645.  
  11646.       The referenced function requests ownership of the mutex semaphore 
  11647.       identified by the parameter, sem. If the semaphore is not currently owned 
  11648.       by another thread, ownership is assigned to the calling thread. 
  11649.       Otherwise, the calling thread is blocked until the semaphore is released 
  11650.       by the current owner. 
  11651.  
  11652.       Important: If the same thread calls SOMRequestMutexSem multiple times, a 
  11653.       reference count must be kept, so that the semaphore is released only 
  11654.       after the same number of calls to SOMReleaseMutexSem. Some, but not all, 
  11655.       thread packages provide reference counting automatically, via "counting 
  11656.       semaphores." 
  11657.  
  11658.       If the call succeeds, a 0 is returned. Otherwise,  a non-zero error code 
  11659.       is returned. 
  11660.  
  11661.   unsigned long(*SOMReleaseMutexSem)(somToken sem);
  11662.  
  11663.       The referenced function releases ownership of the mutex semaphore 
  11664.       identified by the parameter, sem. 
  11665.  
  11666.       Important: If the same thread calls SOMRequestMutexSem multiple times, a 
  11667.       reference count must be kept, so that the semaphore is released only 
  11668.       after the same number of calls to SOMReleaseMutexSem. Some, but not all, 
  11669.       thread packages provide reference counting automatically, via "counting 
  11670.       semaphores." 
  11671.  
  11672.       If the call succeeds, a 0 is returned.  Otherwise, a non-zero error code 
  11673.       is returned. 
  11674.  
  11675.   unsigned long (*SOMDestroyMutexSem)(somToken sem);
  11676.  
  11677.       The referenced function destroys the a mutex semaphore identified by the 
  11678.       parameter, sem. 
  11679.  
  11680.       If the call succeeds, a 0 is returned. Otherwise, a non-zero error code 
  11681.       is returned. 
  11682.  
  11683.   unsigned long (*SOMGetThreadId)();
  11684.  
  11685.       The referenced function returns a small integer identifier for the 
  11686.       calling thread. The ID cannot be associated with any other thread in the 
  11687.       process. The ID is used as an index for table lookups. 
  11688.  
  11689.       If threads are not supported, the function must return 0. 
  11690.  
  11691.  The actual mutex service function prototypes and global variable declarations 
  11692.  are found in file "somapi.h". 
  11693.  
  11694.  If the underlying operating system supports native multi-threading (currently, 
  11695.  only OS/2), SOM provides appropriate default mutex service function 
  11696.  implementations. On those operating systems that do not support native 
  11697.  multi-threading, the default mutex service functions have null 
  11698.  implementations. 
  11699.  
  11700.  An application may want to use threading services different from those 
  11701.  provided by the underlying operating system (if any); for example, DCE 
  11702.  applications will want to use DCE threads. In that case, the default mutex 
  11703.  service functions can be replaced by application-defined functions. 
  11704.  
  11705.  An application program would use code similar to the following to install the 
  11706.  replacement routines: 
  11707.  
  11708.   #include <som.h>
  11709.   /* Define a replacement routine: */
  11710.   unsigned long myCreateMutexSem (somToken *sem)
  11711.   {
  11712.       (Customized code goes here)
  11713.   }
  11714.   ...
  11715.   SOMCreateMutexSem= myCreateMutexSem;
  11716.  
  11717.  It is important to install custom mutex service functions before any SOM calls 
  11718.  are made. 
  11719.  
  11720.  
  11721. ΓòÉΓòÉΓòÉ 7.15. Customizing Multi-threading Services ΓòÉΓòÉΓòÉ
  11722.  
  11723. Although the SOM kernel and the other SOMobjects frameworks allow applications 
  11724. to be multi-threaded, the kernel and frameworks generally do not require or 
  11725. exploit threads themselves. But there are some exceptions: for example, 
  11726. application servers in DSOM can be configured so that each incoming request is 
  11727. executed on a separate thread. 
  11728.  
  11729. An application may choose to employ "native" multi-threading services provided 
  11730. by the underlying operating system (for example, OS/2). On other operating 
  11731. systems that do not support native multi-threading (such as, AIX 3.2), thread 
  11732. support may be provided as part of particular programming environments (like 
  11733. DCE) or libraries.  SOM provides a mechanism that allows an application to 
  11734. define and customize the multi-threading services used by SOMobjects 
  11735. frameworks. 
  11736.  
  11737. Four thread service functions are defined for use by SOMobjects frameworks. 
  11738. These functions may be called indirectly via the global pointer variables 
  11739. defined below. A somToken parameter (called "thrd" below) is used as a generic 
  11740. "handle" to refer to a thread # usually it is a pointer to a thread id or 
  11741. descriptor. The actual representation of the thread handle is hidden by the 
  11742. functions. 
  11743.  
  11744. typedef void somTD_SOMThreadProc(void * data);
  11745.  
  11746. unsigned long (*SOMStartThread)(somToken *thrd,
  11747.                                 somTD_SOMThreadProc proc,
  11748.                                 void *data,
  11749.                                 unsigned long datasz,
  11750.                                 unsigned long stacksz);
  11751.  
  11752.       The referenced function starts a thread, and returns a thread handle in 
  11753.       the somToken variable identified by "thrd".  The thread executes the 
  11754.       procedure whose address is specified by the  proc parameter; the thread 
  11755.       procedure takes a single void* argument and returns void. The data 
  11756.       parameter passed to SOMStartThread is passed on to the thread procedure; 
  11757.       the size of the data parameter, in bytes, is given by datasz.  A stack of 
  11758.       stacksz bytes will be allocated for the thread. 
  11759.  
  11760.       Note: On OS/2, the thread procedure must be compiled with _Optlink 
  11761.       linkage.) 
  11762.  
  11763.       If the call succeeds, a 0 is returned.  Otherwise, a non-zero error code 
  11764.       is returned. 
  11765.  
  11766.   unsigned long (*SOMEndThread)(void);
  11767.  
  11768.       The referenced function terminates the calling thread. 
  11769.  
  11770.       If the call succeeds, a 0 is returned. Otherwise,  a non-zero error code 
  11771.       is returned. 
  11772.  
  11773.   unsigned long (*SOMKillThread)(somToken thrd);
  11774.  
  11775.       The referenced function terminates the thread identified by the input 
  11776.       parameter thrd. 
  11777.  
  11778.       If the call succeeds, a 0 is returned.  Otherwise, a non-zero error code 
  11779.       is returned. 
  11780.  
  11781.   unsigned long (*SOMGetThreadHandle)(somToken * thrd);
  11782.  
  11783.       The referenced function returns a handle that can be used to identify the 
  11784.       calling thread. The handle is returned in the somToken variable pointed 
  11785.       to by thrd. 
  11786.  
  11787.       If the call succeeds, a 0 is returned. Otherwise, a non-zero error code 
  11788.       is returned. 
  11789.  
  11790.  The actual mutex service function prototypes and global variable declarations 
  11791.  are found in file "somthrd.h". 
  11792.  
  11793.  If the underlying operating system supports native multi-threading (currently, 
  11794.  only OS/2), SOM provides appropriate default multi-threading service function 
  11795.  implementations. On those operating systems that do not support native 
  11796.  multi-threading, the default multi-threading service functions have null 
  11797.  implementations. 
  11798.  
  11799.  An application may want to use threading services different from those 
  11800.  provided by the underlying operating system (if any); for example, DCE 
  11801.  applications will want to use DCE threads. In that case, the default 
  11802.  multi-threading service functions can be replaced by application#defined 
  11803.  functions. 
  11804.  
  11805.  An application program would use code similar to the following to install the 
  11806.  replacement routines: 
  11807.  
  11808.   #include <somthrd.h>
  11809.   /* Define a replacement routine: */
  11810.   unsigned long myStartThread (somToken *thrd,
  11811.                                somTD_SOMThreadProc proc,
  11812.                                void *data,
  11813.                                unsigned long datasz,
  11814.                                unsigned long stacksz)
  11815.   {
  11816.       (Customized code goes here)
  11817.   }
  11818.   ...
  11819.   SOMStartThread =myStartThread;
  11820.  
  11821.  It is important to install custom multi-threading service functions before any 
  11822.  SOM calls are made. 
  11823.  
  11824.  
  11825. ΓòÉΓòÉΓòÉ 8. Distributed SOM (DSOM) ΓòÉΓòÉΓòÉ
  11826.  
  11827.  
  11828. ΓòÉΓòÉΓòÉ 8.1. Introduction ΓòÉΓòÉΓòÉ
  11829.  
  11830. Note:  The SOMobject Base Toolkit provides the capability for implementing 
  11831.        Workstation Distributed System Object Module (DSOM) (distribution among 
  11832.        processes on a single machine). Implementing an application that is 
  11833.        distributed across a network of machines requires Workgroup DSOM, which 
  11834.        is available only in the full-capability SOMobjects Developer Toolkit. 
  11835.  
  11836.  
  11837. ΓòÉΓòÉΓòÉ 8.1.1. What is Distributed SOM? ΓòÉΓòÉΓòÉ
  11838.  
  11839. Whereas the power of SOM technology comes from the fact that SOM insulates the 
  11840. client of an object from the object's implementation, the power of DSOM lies in 
  11841. the fact that DSOM insulates the client of an object from the object's 
  11842. location. 
  11843.  
  11844. Distributed SOM (or DSOM) provides a framework that allows application programs 
  11845. to access objects across address spaces. That is, application programs can 
  11846. access objects in other processes, even on different machines. Both the 
  11847. location and implementation of an object are hidden from a client, and the 
  11848. client accesses the object (by way of method calls) in the same manner 
  11849. regardless of its location. 
  11850.  
  11851. DSOM currently supports two types of distribution: 
  11852.  
  11853.    1. distribution among processes on the same machine (referred to as 
  11854.       Workstation DSOM) 
  11855.  
  11856.    2. and distribution among a network of machines (referred to as Workgroup 
  11857.       DSOM). 
  11858.  DSOM runs on the AIX (Release 3.2.5 and above) and OS/2 (Release 2.0 and 
  11859.  above) operating systems. A Workstation DSOM application can run on a machine 
  11860.  in either environment using core capabilities of the SOMobjects system. Under 
  11861.  the full capability SOMobjects Developer Toolkit, Workgroup DSOM supports 
  11862.  distribution across local area networks comprised of both OS/2 and AIX 
  11863.  systems. Future releases of DSOM may support large, enterprise-wide networks. 
  11864.  
  11865.  Support for TCP/IP and NewWare IPX/SPX is provided on AIX, OS/2, and Windows. 
  11866.  NetBIOS support is provided for OS/2 and Windows. DSOM communications is 
  11867.  extensible in that an application can provide its own transport (see Appendix 
  11868.  C of the SOMobjects Base Toolkit Users Guide). 
  11869.  
  11870.  DSOM can be viewed in two ways: 
  11871.  
  11872.    1. As a System Object Model extension that allows a program to invoke 
  11873.       methods on SOM objects in other processes. 
  11874.  
  11875.    2. As an Object Request Broker (ORB); that is, a standardized "transport" 
  11876.       for distributed object interaction. In this respect, DSOM complies with 
  11877.       the Common Object Request Broker Architecture (CORBA) specification, 
  11878.       published by the Object Management Group (OMG) and x/Open. 
  11879.  
  11880.  This chapter describes DSOM from both perspectives. 
  11881.  
  11882.  
  11883. ΓòÉΓòÉΓòÉ 8.1.2. DSOM features ΓòÉΓòÉΓòÉ
  11884.  
  11885. Here is a quick summary of some of DSOM's more important features: 
  11886.  
  11887.    o  Uses the standard SOM Compiler, Interface Repository, language bindings, 
  11888.       and class libraries.  Thus, DSOM provides a growth path for 
  11889.       non-distributed SOM applications. 
  11890.  
  11891.    o  Allows an application program to access a mix of local and remote 
  11892.       objects. The fact that an object is remote is transparent to the program. 
  11893.  
  11894.    o  Provides run-time services for creating, destroying, identifying, 
  11895.       locating, and dispatching methods on remote objects. These services can 
  11896.       be overridden or augmented to suit the application. 
  11897.  
  11898.    o  Uses existing interprocess communication (IPC) facilities for Workstation 
  11899.       communication, and common local area network (LAN) transport facilities 
  11900.       for Workgroup communications. Support for TCP/IP, Netware IPX/SPX, and 
  11901.       NetBios is provided. DSOM communications is extensible in that an 
  11902.       application can provide its own transport. 
  11903.  
  11904.    o  Provides support for writing multi-threaded (on OS/2) and event-driven 
  11905.       programs. 
  11906.  
  11907.    o  Provides a default object server program, which can be easily used to 
  11908.       create SOM objects and make those objects accessible to one or more 
  11909.       client programs. If the default server program is used, SOM class 
  11910.       libraries are loaded upon demand, so no server programming or compiling 
  11911.       is necessary. 
  11912.  
  11913.    o  Complies with the CORBA 1.1 specification, which is important for 
  11914.       application portability. 
  11915.  
  11916.  
  11917. ΓòÉΓòÉΓòÉ 8.1.3. When to use DSOM ΓòÉΓòÉΓòÉ
  11918.  
  11919. DSOM should be used for those applications that require sharing of objects 
  11920. among multiple programs. The object actually exists in only one process (this 
  11921. process is known as the object's server); the other processes (known as 
  11922. clients) access the object through remote method invocations, made transparent 
  11923. by DSOM. 
  11924.  
  11925. DSOM should also be used for applications that require objects to be isolated 
  11926. from the main program. This is usually done in cases where reliability is a 
  11927. concern, either to protect the object from failures in other parts of the 
  11928. application, or to protect the application from an object. 
  11929.  
  11930. Some distributed applications may have special performance, reliability,or 
  11931. cooperative processing requirements, to which the SOM Replication framework is 
  11932. better suited. The Replication framework is oriented toward "groupware" 
  11933. (multi-party cooperative processing) applications, and has facilities for fault 
  11934. tolerance and recovery. The Replication framework is distinct from DSOM in that 
  11935. it maintains a complete replica of an object in each participant's address 
  11936. space, while DSOM establishes remote connections to shared objects. The 
  11937. Replication Framework is available only in the full-capability SOM objects 
  11938. Developer Toolkit. 
  11939.  
  11940.  
  11941. ΓòÉΓòÉΓòÉ 8.1.4. Chapter Outline ΓòÉΓòÉΓòÉ
  11942.  
  11943.  
  11944. Tutorial example 
  11945.  
  11946. First, a complete example shows how an existing SOM class implementation (a 
  11947. "stack") can be used with DSOM to create a distributed "Stack" application. 
  11948. Using the "Stack" example as a backdrop, the basic DSOM interfaces are 
  11949. introduced. 
  11950. Programming DSOM applications 
  11951.  
  11952. All DSOM applications involve three kinds of programming: 
  11953.  
  11954.    o  Client programming:  writing code that uses objects; 
  11955.  
  11956.    o  Server programming:  writing code that implements and manages objects. 
  11957.  
  11958.    o  Implementing classes:  writing code that implements objects. 
  11959.  Three sections; "Basic Client Programming", "Basic Server Programming", and 
  11960.  Implementing Classes", describe how to create DSOM applications from these 
  11961.  three points of view. In turn, the structure and services of the relevant DSOM 
  11962.  run-time environment are explained. 
  11963.  
  11964.  Note:  The three sections are presented in the order above to aid in their 
  11965.  explanation. However, the actual programming tasks are likely to be performed 
  11966.  in the opposite order. 
  11967.  
  11968.  Additional examples are provided in these sections to illustrate DSOM 
  11969.  services. 
  11970.  Configuring DSOM applications 
  11971.  
  11972.  The section "Configuring DSOM Applications" explains what is necessary to set 
  11973.  up a DSOM application, once the application has been built. 
  11974.  Running DSOM applications 
  11975.  
  11976.  The section "Running DSOM Applications" explains what is necessary to run a 
  11977.  DSOM application, once it has been built and configured. 
  11978.  DSOM and CORBA 
  11979.  
  11980.  Those readers interested in using DSOM as a CORBA-compliant ORB should read 
  11981.  the section entitled "DSOM as a CORBA compliant Object Broker." That section 
  11982.  answers the question: How are CORBA concepts implemented in DSOM? 
  11983.  Advanced topics 
  11984.  
  11985.  The section on "Advanced Topics" covers the following: 
  11986.  
  11987.    1. "Peer versus client/server processes" demonstrates how peer-to-peer 
  11988.       object interactions are supported in DSOM. 
  11989.  
  11990.    2. "Dynamic Invocation Interface" details DSOM support for the CORBA dynamic 
  11991.       invocation interface to dynamically build and invoke methods on remote 
  11992.       objects. 
  11993.  
  11994.    3. "Creating user-supplied proxy classes" describes how to override proxy 
  11995.       generation by the DSOM run time and, instead, install a proxy object 
  11996.       supplied by the user. 
  11997.  
  11998.    4. "Customizing the default base proxy class"discusses how the 
  11999.       SOMDClientProxy class can be subclassed to define a customized base class 
  12000.       that DSOM will use during dynamic proxy-class generation. 
  12001.  
  12002.    5. "Sockets class" describes how DSOM uses Sockets subclasses. 
  12003.  
  12004.  Error reporting and troubleshooting 
  12005.  
  12006.  The section on "Error Reporting and Troubleshooting" discusses facilities to 
  12007.  aid in problem diagnosis. 
  12008.  
  12009.  
  12010. ΓòÉΓòÉΓòÉ 8.2. A Simple DSOM Example ΓòÉΓòÉΓòÉ
  12011.  
  12012. A sample "Stack" application is presented in this section as a tutorial 
  12013. introduction to DSOM. It demonstrates that, for simple examples like a "Stack", 
  12014. after very little work, the class can be used to implement distributed objects 
  12015. that are accessed remotely. The example first presents the "Stack" application 
  12016. components and the steps that the implementer must perform before the 
  12017. application can be run, and then describes the run time activity that results 
  12018. from executing the application. This run-time scenario introduces several of 
  12019. the key architectural components of the DSOM run-time environment. 
  12020.  
  12021. The source code for this example is provided with the DSOM samples in the 
  12022. SOMobjects Developer Toolkit. 
  12023.  
  12024.  
  12025. ΓòÉΓòÉΓòÉ 8.2.1. The "Stack" interface ΓòÉΓòÉΓòÉ
  12026.  
  12027. The example starts with the assumption that the class implementer has 
  12028. successfully built a SOM class library DLL, called "stack.dll", in the manner 
  12029. described in Section 5.6, "Creating a SOM Class Library," of Chapter 5, 
  12030. "Implementing Classes in SOM." The DLL implements the following IDL interface. 
  12031.  
  12032. #include <somobj.idl>
  12033.  
  12034. interface Stack: SOMObject
  12035. {
  12036.     const long stackSize = 10;
  12037.     exception STACK_OVERFLOW{};
  12038.     exception STACK_UNDERFLOW{};
  12039.     boolean full();
  12040.     boolean empty();
  12041.     long top() raises(STACK_UNDERFLOW);
  12042.     long pop() raises(STACK_UNDERFLOW);
  12043.     void push(in long element) raises(STACK_OVERFLOW);
  12044.  
  12045.     #ifdef __SOMIDL__
  12046.     implementation
  12047.     {
  12048.       releaseorder: full, empty, top, pop, push;
  12049.       somDefaultInit: override;
  12050.       long stackTop;                  // top of stack index
  12051.       long stackValues[stackSize];    // stack elements
  12052.       dllname = "stack.dll";
  12053.     };
  12054.     #endif
  12055. };
  12056.  
  12057. This DLL could have been built without the knowledge that it would ever be 
  12058. accessed remotely (that is, built following the procedures in Chapter 5). Note, 
  12059. however, that some DLLs may require changes in the way their classes pass 
  12060. arguments and manage memory, in order to be used by remote clients (see the 
  12061. topic "Implementation Constraints" in section 6.5, "Implementing Classes"). 
  12062.  
  12063.  
  12064. ΓòÉΓòÉΓòÉ 8.2.2. The "Stack" class implementation ΓòÉΓòÉΓòÉ
  12065.  
  12066. #define Stack_Class_Source
  12067. #include <stack.ih>
  12068.  
  12069. SOM_Scope boolean  SOMLINK full(Stack somSelf, Environment *ev)
  12070. {
  12071.     StackData *somThis = StackGetData(somSelf);
  12072.     StackMethodDebug("Stack","full");
  12073.  
  12074.     /* Return TRUE if stack is full. */
  12075.     return (_stackTop == stackSize);
  12076. }
  12077.  
  12078. SOM_Scope boolean  SOMLINK empty(Stack somSelf, Environment *ev)
  12079. {
  12080.     StackData *somThis = StackGetData(somSelf);
  12081.     StackMethodDebug("Stack","empty");
  12082.  
  12083.     /* Return TRUE if stack is empty.*/
  12084.     return (_stackTop == 0);
  12085. }
  12086.  
  12087. SOM_Scope long  SOMLINK top(Stack somSelf, Environment *ev)
  12088. {
  12089.     StackData *somThis = StackGetData(somSelf);
  12090.     StackMethodDebug("Stack","top");
  12091.  
  12092.     if (_stackTop > 0)
  12093.     {
  12094.        /* Return top element in stack without removing it from
  12095.         * the stack.
  12096.         */
  12097.        return (_stackValues[_stackTop-1]);
  12098.     }
  12099.     else
  12100.     {
  12101.        somSetException(ev, USER_EXCEPTION,
  12102.                        ex_STACK_UNDERFLOW, NULL);
  12103.        return (-1L);
  12104.     }
  12105. }
  12106.  
  12107. SOM_Scope long  SOMLINK pop(Stack somSelf, Environment *ev)
  12108. {
  12109.     StackData *somThis = StackGetData(somSelf);
  12110.     StackMethodDebug("Stack","pop");
  12111.  
  12112.     if (_stackTop > 0)
  12113.     {
  12114.        /* Return top element in stack and remove it from the
  12115.         * stack.
  12116.         */
  12117.        _stackTop--;
  12118.        return (_stackValues[_stackTop]);
  12119.     }
  12120.     else
  12121.     {
  12122.        somSetException(ev, USER_EXCEPTION,
  12123.                        ex_STACK_UNDERFLOW, NULL);
  12124.        return (-1L);
  12125.     }
  12126. }
  12127.  
  12128. SOM_Scope void  SOMLINK push(Stack somSelf,
  12129.                              Environment *ev, long el)
  12130. {
  12131.     StackData *somThis = StackGetData(somSelf);
  12132.     StackMethodDebug("Stack","push");
  12133.  
  12134.     if (_stackTop < stackSize)
  12135.     {
  12136.       /* Add element to top of the stack. */
  12137.       _stackValues[_stackTop] = el;
  12138.       _stackTop++;
  12139.     }
  12140.     else
  12141.     {
  12142.        somSetException(ev, USER_EXCEPTION,
  12143.                        ex_STACK_OVERFLOW, NULL);
  12144.     }
  12145. }
  12146.  
  12147. SOM_Scope void  SOMLINK somDefaultInit(Stack somSelf,
  12148.                                        somInitCtrl* ctrl)
  12149. {
  12150.     StackData *somThis;
  12151.     somInitCtrl globalCtrl;
  12152.     somBooleanVector myMask;
  12153.     StackMethodDebug("Stack","somDefaultInit");
  12154.     Stack_BeginInitializer_somDefaultInit;
  12155.  
  12156.     Stack_Init_SOMObject_somDefaultInit(somSelf, ctrl);
  12157.  
  12158.     /* stackTop is index into stackValues for next pushed
  12159.      * stack element.
  12160.      * stackValues[0..(stackSize-1)] holds stack elements.
  12161.      */
  12162.     _stackTop = 0;
  12163. }
  12164.  
  12165.  
  12166. ΓòÉΓòÉΓòÉ 8.2.3. Client program using a local stack ΓòÉΓòÉΓòÉ
  12167.  
  12168. A simple client program written to use a local "Stack" object is displayed 
  12169. below. This C program is shown so that the differences between a local and 
  12170. remote client program can be highlighted. 
  12171.  
  12172. #include <stack.h>
  12173.  
  12174. boolean OperationOK(Environment *ev);
  12175.  
  12176. int main(int argc, char *argv[])
  12177. {
  12178.   Environment ev;
  12179.   Stack stk;
  12180.   long num = 100;
  12181.  
  12182.   SOM_InitEnvironment(&ev);
  12183.  
  12184.   /* The StackNewClass invocation is optional and unnecessary
  12185.    * in the client program when the class object is created in
  12186.    * the SOMInitModule function that is invoked during DLL
  12187.    * initialization.
  12188.    */
  12189.   StackNewClass(Stack_MajorVersion, Stack_MinorVersion);
  12190.   stk = StackNew();
  12191.  
  12192.   /* Verify successful object creation */
  12193.   if ( stk != NULL )
  12194.   {
  12195.      while ( !_full(stk, &ev) )
  12196.      {
  12197.         _push(stk, &ev, num);
  12198.         somPrintf("Top: %d\n", _top(stk, &ev));
  12199.         num += 100;
  12200.      }
  12201.  
  12202.      /* Test stack overflow exception */
  12203.      _push(stk, &ev, num);
  12204.      OperationOK(&ev);
  12205.  
  12206.      while ( !_empty(stk, &ev) )
  12207.      {
  12208.         somPrintf("Pop: %d\n", _pop(stk, &ev));
  12209.      }
  12210.  
  12211.      /* Test stack underflow exception */
  12212.      somPrintf("Top Underflow: %d\n", _top(stk, &ev));
  12213.      OperationOK(&ev);
  12214.      somPrintf("Pop Underflow: %d\n", _pop(stk, &ev));
  12215.      OperationOK(&ev);
  12216.  
  12217.      _push(stk, &ev, -10000);
  12218.      somPrintf("Top: %d\n", _top(stk, &ev));
  12219.      somPrintf("Pop: %d\n", _top(stk, &ev));
  12220.  
  12221.      _somFree(stk);
  12222.   }
  12223.  
  12224.   SOM_UninitEnvironment(&ev);
  12225.  
  12226.   return(0);
  12227. }
  12228.  
  12229. boolean OperationOK(Environment *ev)
  12230. {
  12231.    char *exID;
  12232.  
  12233.    switch (ev->_major)
  12234.    {
  12235.      case SYSTEM_EXCEPTION:
  12236.        exID = somExceptionId(ev);
  12237.        somPrintf("System exception: %s\n", exID);
  12238.        somdExceptionFree(ev);
  12239.        return (FALSE);
  12240.  
  12241.      case USER_EXCEPTION:
  12242.        exID = somExceptionId(ev);
  12243.        somPrintf("User exception: %s\n", exID);
  12244.        somdExceptionFree(ev);
  12245.        return (FALSE);
  12246.  
  12247.      case NO_EXCEPTION:
  12248.        return (TRUE);
  12249.  
  12250.      default:
  12251.        somPrintf("Invalid exception type in Environment.\n");
  12252.        somdExceptionFree(ev);
  12253.        return (FALSE);
  12254.    }
  12255. }
  12256.  
  12257.  
  12258. ΓòÉΓòÉΓòÉ 8.2.4. Client program using a remote stack ΓòÉΓòÉΓòÉ
  12259.  
  12260. The preceding program has been rewritten below showing how DSOM can be used to 
  12261. create and access a "Stack" object somewhere in the system. The exact location 
  12262. of the object does not matter to the application; it just wants a "Stack" 
  12263. object. Note that the stack operations of the two programs are identical. The 
  12264. main differences lie in stack creation and destruction, as highlighted below. 
  12265. (Also see "Memory management" later for more information on allocating and 
  12266. freeing memory.) 
  12267.  
  12268. #include <somd.h>
  12269. #include <stack.h>
  12270.  
  12271. int main(int argc, char *argv])
  12272. {
  12273.   Environment ev;
  12274.   Stack stk;
  12275.   long num = 100;
  12276.  
  12277.   SOM_InitEnvironment(&ev);
  12278.   SOMD_Init(&ev);
  12279.  
  12280.   /* The StackNewClass invocation is optional and unnecessary
  12281.    * in the client program when the class object is created in
  12282.    * the SOMInitModule function that is invoked during DLL
  12283.    * initialization.
  12284.    */
  12285.   StackNewClass (Stack_MajorVersion, Stack_MinorVersion);
  12286.   stk = _somdNewObject(SOMD_ObjectMgr, &ev, "Stack", "");
  12287.  
  12288.   /* Verify successful object creation */
  12289.   if ( OperationOK(&ev) )
  12290.   {
  12291.      while ( !_full(stk, &ev) )
  12292.      {
  12293.         _push(stk, &ev, num);
  12294.         somPrintf("Top: %d\n", _top(stk, &ev));
  12295.         num += 100;
  12296.      }
  12297.  
  12298.      /* Test stack overflow exception */
  12299.      _push(stk, &ev, num);
  12300.      OperationOK(&ev);
  12301.  
  12302.      while ( !_empty(stk, &ev) )
  12303.      {
  12304.         somPrintf("Pop: %d\n", _pop(stk, &ev));
  12305.      }
  12306.  
  12307.      /* Test stack underflow exception */
  12308.      somPrintf("Top Underflow: %d\n", _top(stk, &ev));
  12309.      OperationOK(&ev);
  12310.      somPrintf("Pop Underflow: %d\n", _pop(stk, &ev));
  12311.      OperationOK(&ev);
  12312.  
  12313.      _push(stk, &ev, -10000);
  12314.      somPrintf("Top: %d\n", _top(stk, &ev));
  12315.      somPrintf("Pop: %d\n", _top(stk, &ev));
  12316.  
  12317.      _somdDestroyObject(SOMD_ObjectMgr, &ev, stk);
  12318.  
  12319.      if ( OperationOK(&ev) )
  12320.      {
  12321.         somPrintf("Stack test successfully completed.\n");
  12322.      }
  12323.   }
  12324.   SOMD_Uninit(&ev);
  12325.   SOM_UninitEnvironment(&ev);
  12326.  
  12327.   return(0);
  12328. }
  12329.  
  12330. boolean OperationOK(Environment *ev)
  12331. {
  12332.    char *exID;
  12333.  
  12334.    switch (ev->_major)
  12335.    {
  12336.      case SYSTEM_EXCEPTION:
  12337.        exID = somExceptionId(ev);
  12338.        somPrintf("System exception: %s\n", exID);
  12339.        somdExceptionFree(ev);
  12340.        return (FALSE);
  12341.  
  12342.      case USER_EXCEPTION:
  12343.        exID = somExceptionId(ev);
  12344.        somPrintf("User exception: %s\n", exID);
  12345.        somdExceptionFree(ev);
  12346.        return (FALSE);
  12347.  
  12348.      case NO_EXCEPTION:
  12349.        return (TRUE);
  12350.  
  12351.      default:
  12352.        somPrintf("Invalid exception type in Environment.\n");
  12353.        somdExceptionFree(ev);
  12354.        return (FALSE);
  12355.    }
  12356. }
  12357.  
  12358. Let's step through the differences. 
  12359.  
  12360. First, every DSOM program must include the file <somd.h> (when using C ++, 
  12361. <somd.xh>). This file defines constants, global variables, and run-time 
  12362. interfaces used by DSOM. Usually, this file is sufficient to establish all 
  12363. necessary DSOM definitions. 
  12364.  
  12365. Next, DSOM requires its own initialization call. 
  12366.  
  12367.         SOMD_Init(&ev);
  12368.  
  12369. The call to SOMD_Init initializes the DSOM run-time environment SOMD_Init must 
  12370. be called before any DSOM run-time calls are made. A side effect of calling 
  12371. SOMD_Init is that a run-time object, called the DSOM Object Manager, is 
  12372. created, and a pointer to it is stored in the global variable, SOMD_ObjectMgr, 
  12373. for programming convenience. The DSOM Object Manager provides basic run-time 
  12374. support for clients to find, create, destroy, and identify objects. The Object 
  12375. Manager is discussed in detail in the section entitled "Basic Client 
  12376. Programming." 
  12377.  
  12378. Next, the local stack creation statement, 
  12379.  
  12380.         stk = StackNew();
  12381. was replaced by 
  12382.  
  12383.  
  12384.         stk = _somdNewObject(SOMD_ObjectMgr, &ev, "Stack", "");
  12385.  
  12386. The call to somdNewObject asks the DSOM Object Manager (SOMD_ObjectMgr) to 
  12387. create a "Stack" object, wherever it can find an implementation of "Stack". 
  12388. (There are other methods with which one can request specific servers.) If no 
  12389. object could be created, NULL is returned, and an exception is raised. 
  12390. Otherwise, the object returned is a "Stack" proxy. 
  12391.  
  12392. Note:  On AIX, the following call may be needed before the somdNewObject call, 
  12393.        if the "Stack" class implementation has been linked directly with the 
  12394.        program executable (vs. using a dynamic link library, or DLL). This call 
  12395.        will properly initialize the class for use by DSOM (this initialization 
  12396.        is done in SOMInitModule for DLLs):
  12397.  
  12398.              StackNewClass(Stack_MajorVersion, Stack_MinorVersion);
  12399.  
  12400.  A proxy is an object that is a local representative for a remote target 
  12401.  object. A proxy inherits the target object's interface, so it responds to the 
  12402.  same methods. Operations invoked on the proxy are not executed locally, but 
  12403.  are forwarded to the "real" target object for execution. The client program 
  12404.  always has a proxy for each remote target object on which it operates. 
  12405.  
  12406.  From this point on, the client program treats the "Stack" proxy exactly as it 
  12407.  would treat a local "Stack". The "Stack" proxy takes responsibility for 
  12408.  forwarding requests to, and yielding results from, the remote "Stack". For 
  12409.  example, 
  12410.  
  12411.           _push(stk,&ev,num);
  12412.  
  12413.  causes a message representing the method call to be sent to the server process 
  12414.  containing the remote object. The DSOM run-time in the server process decodes 
  12415.  the message and invokes the method on the target object. The result (in this 
  12416.  case, just an indication of completion) is then returned to the client process 
  12417.  in a message. The DSOM run time in the client process decodes the result 
  12418.  message and returns any result data to the caller. 
  12419.  
  12420.  At the end of the original client program, the local "Stack" was destroyed by 
  12421.  the statement, 
  12422.  
  12423.           _somFree(stk);
  12424.  
  12425.  whereas, in the client program above, the "Stack" proxy and the remote "Stack" 
  12426.  are destroyed by the statement, 
  12427.  
  12428.           _somdDestroyObject(SOMD_ObjectMgr, &ev, stk);
  12429.  
  12430.  If the client only wants to release its use of the remote object (freeing the 
  12431.  proxy) without destroying the remote object, it can call the somdReleaseObject 
  12432.  method instead of somdDestroyObject. 
  12433.  
  12434.  Finally, the client must shut down DSOM, so that any operating system 
  12435.  resources acquired by DSOM for communications or process management can be 
  12436.  returned: 
  12437.  
  12438.           SOMD_Uninit(&ev);
  12439.  This call must be made at the end of every DSOM program. 
  12440.  Using specific servers 
  12441.  
  12442.  In DSOM, the process that manages a target object is called the object's 
  12443.  server. Servers are implemented as programs that use SOM classes.  Server 
  12444.  implementations are registered with DSOM in an Implementation Repository. The 
  12445.  Implementation Repository is a database queried by clients in order to find 
  12446.  desired servers, and queried by DSOM in order to activate those servers upon 
  12447.  demand. 
  12448.  
  12449.  The example above placed no constraints on the DSOM Object Manager as to where 
  12450.  the remote "Stack" object should be created. The somdNewObject call creates a 
  12451.  remote object of a specified class in an arbitrary server that implements that 
  12452.  class. However, the DSOM Object Manager provides methods for finding specific 
  12453.  servers. 
  12454.  
  12455.  For example, the client program above can be modified slightly to find a 
  12456.  specific server named "StackServer", which has already been registered in 
  12457.  DSOM's Implementation Repository.  (Note that the programmer knew or 
  12458.  discovered that the "StackServer" server implementation supports the "Stack" 
  12459.  class.)  The highlighted lines below show the changes that were made: 
  12460.  
  12461.   #include <somd.h>
  12462.   #include <stack.h>
  12463.  
  12464.   int main(int argc, char *argv[]) {
  12465.           Stack stk;
  12466.           Environment e;
  12467.           SOMDServer server;
  12468.  
  12469.           SOM_InitEnvironment(&e);
  12470.           SOMD_Init(&e);
  12471.  
  12472.           server =
  12473.             _somdFindServerByName(SOMD_ObjectMgr, &e, "StackServer");
  12474.           stk = _somdCreateObj(server, &e, "Stack", "");
  12475.  
  12476.           _push(stk,&e,100);
  12477.           _push(stk,&e,200);
  12478.           _pop(stk,&e);
  12479.           if (!_empty(stk,&e)) somPrintf("Top: %d\n", _top(stk,&e));
  12480.  
  12481.           _somdDeleteObj(server, &e, stk);
  12482.           _somdReleaseObject(SOMD_ObjectMgr, &e, stk);
  12483.           _somdReleaseObject(SOMD_ObjectMgr, &e, server);
  12484.           SOMD_Uninit(&e);
  12485.           SOM_UninitEnvironment(&e);
  12486.  
  12487.           return(0);
  12488.   }
  12489.  
  12490.  This version of the program replaces the somdNewObject operation with calls to 
  12491.  somdFindServerByName and somdCreateObj. The somdFindServerByName method 
  12492.  consults the Implementation Repository to find the DSOM server implementation 
  12493.  whose name is "StackServer", and creates a server proxy, which provides a 
  12494.  connection to that server. Every DSOM server process has a server object that 
  12495.  defines methods to assist in the creation and management of objects in that 
  12496.  server. Server objects must be instances of SOMDServer or one of its 
  12497.  subclasses. The somdFindServerByName returns a proxy to the SOMDServer object 
  12498.  in the named server. 
  12499.  
  12500.  Once the client has the server proxy, it can create and destroy objects in 
  12501.  that server. The somdCreateObj call creates an object of the class "Stack" in 
  12502.  the server named "StackServer". 
  12503.  
  12504.  To free the remote "Stack" object, the example shows a somdDeleteObj request 
  12505.  on the stack object's server. Next, somdReleaseObject requests are made on the 
  12506.  DSOM Object Manager, to free the stack proxy and the server proxy in the 
  12507.  client. (Note that these three calls are equivalent to the somdDestroyObject 
  12508.  call in the previous example.) 
  12509.  
  12510.  
  12511. ΓòÉΓòÉΓòÉ 8.2.5. A note on finding existing objects ΓòÉΓòÉΓòÉ
  12512.  
  12513. The two examples above show how clients can create a remote, transient object 
  12514. for their exclusive use. Clients may want to find and use objects that already 
  12515. exist. In that case, the calls to somdNewObject or somdCreateObj would be 
  12516. replaced with other "lookup" calls on some directory object that would take an 
  12517. object name or identifier and return a proxy to the remote object. 
  12518.  
  12519. Such a directory object could be implemented by the application as a persistent 
  12520. SOM object, using DSOM to share it among processes. 
  12521.  
  12522. The basic mechanisms that DSOM provides for naming and locating objects will be 
  12523. discussed in section  "Basic Client Programming." 
  12524.  
  12525.  
  12526. ΓòÉΓòÉΓòÉ 8.2.6. "Stack" server implementation ΓòÉΓòÉΓòÉ
  12527.  
  12528. A server consists of three parts. First, a "main" program, when run, provides 
  12529. an address space for the objects it manages, and one or more process "threads" 
  12530. that can execute method calls. (Windows and AIX currently do not have 
  12531. multi-thread support, while OS/2 and AIX 4.1 do.) Second, a server object, 
  12532. derived from the SOMDServer class, provides methods used to manage objects in 
  12533. the server process. Third, one or more class libraries provide object 
  12534. implementations. Usually these libraries are constructed as dynamically linked 
  12535. libraries (DLLs), so they can be loaded and linked by a server program 
  12536. dynamically. 
  12537.  
  12538. In this simple example, we can use the default DSOM server program, which is 
  12539. already compiled and linked. The default server behaves as a simple server, in 
  12540. that it simply receives and executes requests continuously. The default server 
  12541. creates its server object from the class, SOMDServer. The default server will 
  12542. load any class libraries it needs upon demand. 
  12543.  
  12544. The "Stack" class library, "stack.dll", can be used without modification in the 
  12545. distributed application. This is possible because the "Stack" class is "well 
  12546. formed"; in other words, there are no methods that implicitly assume the client 
  12547. and the object are in the same address space. 
  12548.  
  12549. Thus, by using the default server and the existing class library, a simple 
  12550. "Stack" server can be provided without any additional programming! 
  12551.  
  12552. An application may require more functionality in the server program or the 
  12553. server object than the default implementations provide. A discussion on how to 
  12554. implement server programs and server objects is found later in this chapter, in 
  12555. section 6.4, "Basic Server Programming". 
  12556.  
  12557.  
  12558. ΓòÉΓòÉΓòÉ 8.2.7. Compiling the application ΓòÉΓòÉΓòÉ
  12559.  
  12560. DSOM programs and class libraries are compiled and linked like any other SOM 
  12561. program or library. The header file "somd.h" (or for C++, "somd.xh") should be 
  12562. included in any source program that uses DSOM services. DSOM run-time calls can 
  12563. be resolved by linking with the SOMobjects Toolkit library: "libsomtk.a" on AIX 
  12564. and "somtk.lib" on OS/2 or Windows. (The DSOM DLL(s)--"somd.dll", for AIX or 
  12565. OS/2, or "somd1.dll" and "somd1.dll" for Windows--will be loaded at run time.) 
  12566. For more information, see "Compiling and linking" in Chapter 3, "Using SOM 
  12567. classes in Client Programs," and the same topic in Chapter 5, "Implementing 
  12568. Classes in SOM." 
  12569.  
  12570.  
  12571. ΓòÉΓòÉΓòÉ 8.2.8. Installing the implementation ΓòÉΓòÉΓòÉ
  12572.  
  12573. Before the application can be run, certain environment variables must be set 
  12574. and the stack class and server implementations must be registered in the SOM 
  12575. Interface Repository and DSOM Implementation Repository. 
  12576. Setting environment variables 
  12577.  
  12578. Several environment variables are used by SOM and DSOM. These variables need to 
  12579. be set before registering the DSOM application in the Interface and 
  12580. Implementation Repositories. 
  12581.  
  12582. For this example, the following environment variables could be set as shown. A 
  12583. full description of the environment variables and how to set them is given in 
  12584. section 6.6, "Configuring DSOM." 
  12585.  
  12586. On AIX (in the syntax of the default shell, /bin/ksh): 
  12587.  
  12588. export HOSTNAME=machine3
  12589. export SOMIR=$SOMBASE/etc/som.ir:/u/myuserid/my.ir
  12590. export SOMDDIR=/u/myuserid/somddir
  12591. export LIBPATH=$LIBPATH:$SOMBASE/lib:/u/myuserid/lib
  12592.  
  12593. On OS/2: 
  12594.  
  12595. set USER=pat
  12596. set HOSTNAME=machine3
  12597. set SOMDDIR=c:\somddir
  12598.  
  12599. rem *** The following variables are set in CONFIG.SYS by
  12600. rem *** the install program on OS/2, assuming "c:\som" is the
  12601. rem *** value of %SOMBASE% supplied by the user.
  12602. set SOMIR=c:\som\etc\som.ir;som.ir
  12603. set LIBPATH=.;c:\som\lib;<previous LIBPATH>
  12604.  
  12605. On Windows: 
  12606.  
  12607. set USER=pat
  12608. set HOSTNAME=machine3
  12609. set SOMDDIR=c:\somddir
  12610. rem *** The following variables are usually set in AUTOEXEC.BAT
  12611. rem *** by the install program on Windows, assuming "c:\som"
  12612. rem *** is the value of %SOMBASE% supplied by the user.
  12613. set SOMIR=c:\som\etc\som.ir:som.ir
  12614. set PATH=.;c:\som\lib;<previous PATH>
  12615.  
  12616. USER identifies the user of a DSOM client application. DSOM sends the USER ID 
  12617. with every remote method call, in case the remote object wishes to perform any 
  12618. access control checking. This is discussed later in the section "Basic Server 
  12619. Programming." (Note that USER is usually set automatically by AIX when a user 
  12620. logs in.) 
  12621.  
  12622. HOSTNAME identifies the name of each machine running DSOM. 
  12623.  
  12624. SOMIR gives a list of files that together constitute the Interface Repository. 
  12625. The IR is used by DSOM to guide the construction and interpretation of request 
  12626. messages. For DSOM, it is preferable to use full pathnames in the list of IR 
  12627. files, since the IR will be shared by several programs that may not all reside 
  12628. in the same directory. 
  12629.  
  12630. SOMDDIR gives the name of a directory used to store DSOM configuration files, 
  12631. including the Implementation Repository. 
  12632.  
  12633. LIBPATH (on AIX and OS/2) or PATH (on Windows) gives a list of directories 
  12634. where DLLs can be found. 
  12635.  
  12636.  
  12637. Registering the class in the Interface Repository 
  12638.  
  12639. Before an object can be accessed remotely by DSOM, it is necessary to register 
  12640. the class's interface and implementation in the Interface Repository (IR). DSOM 
  12641. uses the interface information when transforming local method calls on proxies 
  12642. into request messages transmitted to remote objects. 
  12643.  
  12644. DSOM servers also consult the IR to find the name of the DLL for a dynamically 
  12645. loaded class. The DLL name for the "Stack" class must be specified using the 
  12646. dllname="stack.dll" modifier in the implementation statement of the "Stack" 
  12647. IDL. The Interface Repository is described in detail in Chapter 7, "The 
  12648. Interface Repository Framework." 
  12649.  
  12650. The IDL specification of "Stack" is compiled into the Interface Repository 
  12651. using the following command: 
  12652.  
  12653.         sc -u -sir stack.idl               (on AIX or OS/2)
  12654.         somc -u -sir stack.idl             (on Windows)
  12655.  
  12656. When a class has not been compiled into the Interface Repository, DSOM will 
  12657. generate a run-time error when an attempt is made to invoke a method from that 
  12658. class. The error indicates that the method's descriptor was not found in the 
  12659. IR. 
  12660. Registering the server in the Implementation Repository 
  12661.  
  12662. It is necessary to register a description of a server's implementation in the 
  12663. Implementation Repository. DSOM uses this information to assist clients in 
  12664. finding servers, and in activating server processes upon demand. 
  12665.  
  12666. For this example, where the default server is used, we need only to identify 
  12667. the server's name, and the class that the server implements. This is 
  12668. accomplished using the regimpl utility discussed in section 6.6, "Configuring 
  12669. DSOM Applications". The following commands define a default server, named 
  12670. "StackServer", which supports the Stack class: 
  12671.  
  12672.         regimpl -A -i StackServer
  12673.         regimpl -a -i StackServer -c Stack
  12674.  
  12675.  
  12676. ΓòÉΓòÉΓòÉ 8.2.9. Running the application ΓòÉΓòÉΓòÉ
  12677.  
  12678.  
  12679. Starting the DSOM daemon 
  12680.  
  12681. Before running a DSOM application, the DSOM daemon, somdd, must be started. 
  12682.  
  12683.    o  On AIX or OS/2, the daemon can be started manually from the command line, 
  12684.       or it could be started automatically from a start-up script run at boot 
  12685.       time. It may be run in the background with the commands somdd& on AIX and 
  12686.       start somdd on OS/2. (The somdd program requires no parameters. An 
  12687.       optional -q parameter can be used to set "quiet" mode, to suppress 
  12688.       messages.) 
  12689.  
  12690.    o  On Windows, the daemon can be started with the DSOM Daemon icon in the 
  12691.       SOM icon group or started in Windows from the Run option of the file 
  12692.       menu.  The DSOM Daemon icon will change colors to indicate the daemon is 
  12693.       ready,  after which client and server programs can be started. 
  12694.  
  12695.       The somdd daemon is responsible for establishing a "binding" (that is, a 
  12696.       connection) between a client process and a server.  It will activate the 
  12697.       desired server automatically, if necessary. 
  12698.  
  12699.  Running the client 
  12700.  
  12701.  Once the DSOM daemon is running, the application may be started. This is 
  12702.  accomplished by running the client program. If the StackServer is not running, 
  12703.  it will be started automatically by the DSOM daemon when the client attempts 
  12704.  to invoke a method on one of its objects. 
  12705.  
  12706.  
  12707. ΓòÉΓòÉΓòÉ 8.2.10. "Stack" example run-time scenario ΓòÉΓòÉΓòÉ
  12708.  
  12709. The following scenario steps through the actions taken by the DSOM run time in 
  12710. response to each line of code in the second "Stack" client program presented 
  12711. above. The illustration following the scenario shows the processes, and the 
  12712. objects within them, that participate in these actions. 
  12713.  
  12714.    o  Initialize an environment for error passing: 
  12715.  
  12716.             SOM_InitEnvironment(&e);
  12717.  
  12718.    o  Initialize DSOM: 
  12719.  
  12720.             SOMD_Init(&e);
  12721.  
  12722.  This causes the creation of the DSOM Object Manager (with SOMDObjectMgr 
  12723.  interface). The global variable SOMD_ObjectMgr points to this object. 
  12724.  
  12725.    o  Initialize "Stack" class object: 
  12726.  
  12727.             StackNewClass(Stack_MajorVersion, Stack_MinorVersion);
  12728.  
  12729.    o  Find the "StackServer" implementation and assign its proxy to the 
  12730.       variable server: 
  12731.  
  12732.             server = _somdFindServerByName(SOMD_ObjectMgr, &e, "StackServer");
  12733.  
  12734.  This causes the creation of the server proxy object in the client process. 
  12735.  Proxy objects are shown as shaded circles. Note that the "real" server object 
  12736.  in the server process is not created at this time. In fact, the server process 
  12737.  has not yet been started. 
  12738.  
  12739.    o  Ask the server object to create a "Stack" and assign "Stack" proxy to 
  12740.       variable stack. 
  12741.  
  12742.             stk = _somdCreateObj(server, &e, "Stack", "");
  12743.  
  12744.  This causes somdd, the DSOM daemon (which is already running) to activate the 
  12745.  stack server process (by starting the "generic" server program). The stack 
  12746.  server process, upon activation, creates the "real" SOMDServer object in the 
  12747.  server process. The SOMDServer object works with the DSOM run time to create a 
  12748.  local "Stack" object and return a "Stack" proxy to the client. (The details of 
  12749.  this procedure are deferred until section 6.4, "Basic Server Programming".) 
  12750.  
  12751.    o  Ask the "Stack" proxy to push 100 onto the remote stack: 
  12752.  
  12753.             _push(stk,&e,100);
  12754.  
  12755.  This causes a message representing the method call to be marshalled and sent 
  12756.  to the server process. In the server process, DSOM demarshals the message and, 
  12757.  with the help of the SOMDServer, locates the target "Stack" object upon which 
  12758.  it invokes the method ("push"). The result (which is void in this case) is 
  12759.  then passed back to the client process in a message. 
  12760.  
  12761.    o  Invoke more "Stack" operations on the remote stack, via the proxy: 
  12762.  
  12763.             _push(stk,&e,200);
  12764.  
  12765.             _pop(stk,&e);
  12766.  
  12767.             if (!_empty(stk,&e)) t = _top(stk,&e);
  12768.  
  12769.    o  Explicitly destroy both the remote stack, the stack proxy, and the server 
  12770.       proxy: 
  12771.  
  12772.             _somdDeleteObj(server, &e, stk);
  12773.  
  12774.             _somdReleaseObject(SOMD_ObjectMgr, &e, stk);
  12775.  
  12776.             _somdReleaseObject(SOMD_ObjectMgr, &e, server);
  12777.  
  12778.    o  Free the error-passing environment: 
  12779.  
  12780.             SOM_UninitEnvironment(&e);
  12781.  
  12782.  This scenario has introduced the key processes in a DSOM application: client, 
  12783.  server, and somdd. Also introduced are the key objects that comprise the DSOM 
  12784.  run-time environment: the SOMD_ObjectMgr in the client process and the 
  12785.  SOMD_ServerObject in the server process. 
  12786.  
  12787.  
  12788. ΓòÉΓòÉΓòÉ 8.2.11. Summary ΓòÉΓòÉΓòÉ
  12789.  
  12790. This example has introduced the key concepts of building, installing, and 
  12791. running a DSOM application. It has also introduced some of the key components 
  12792. that comprise the DSOM application run-time environment. 
  12793.  
  12794. The following sections, "Basic Client Programming," "Basic Server Programming," 
  12795. and "Implementing Classes," provide more detail on how to use, manage, and 
  12796. implement remote objects, respectively. 
  12797.  
  12798.  
  12799. ΓòÉΓòÉΓòÉ 8.3. Basic Client Programming ΓòÉΓòÉΓòÉ
  12800.  
  12801. For the most part, client programming in DSOM is exactly the same as client 
  12802. programming in SOM, since DSOM transparently hides the fact that an object is 
  12803. remote when the client accesses the object. 
  12804.  
  12805. However, a client application writer also needs to know how to create, locate, 
  12806. use, save, and destroy remote objects. (This is not done using the usual SOM 
  12807. bindings.) The DSOM run-time environment provides these services to client 
  12808. programs primarily through the DSOM Object Manager. These run-time services 
  12809. will be detailed in this section. Examples of how an application developer uses 
  12810. these services are provided throughout the section. 
  12811.  
  12812.  
  12813. ΓòÉΓòÉΓòÉ 8.3.1. DSOM Object Manager ΓòÉΓòÉΓòÉ
  12814.  
  12815. DSOM defines a DSOM Object Manager, which provides services needed by clients 
  12816. to create, find and use objects in the DSOM run-time environment. 
  12817.  
  12818. The DSOM Object Manager is derived from an abstract, generic "object manager" 
  12819. class, called ObjectMgr. This abstract ObjectMgr class defines a basic set of 
  12820. methods that support object creation, location (with implicit activation), and 
  12821. destruction. 
  12822.  
  12823. As an abstract class, ObjectMgr defines only an interface; there is no 
  12824. implementation associated with ObjectMgr. Consequently, an application should 
  12825. not create instances of the ObjectMgr class. 
  12826.  
  12827.  An abstract Object Manager class was defined under the expectation that 
  12828. applications will often need simultaneous access to objects implemented and 
  12829. controlled by a variety of object systems. Such object systems may include 
  12830. other ORBs (in addition to DSOM), persistent object managers, object-oriented 
  12831. databases, and so forth. It is likely that each object system will provide the 
  12832. same sort of basic services for object creation, location, and activation, but 
  12833. each using a different interface. 
  12834.  
  12835. Thus, the ObjectMgr abstract class defines a simple and "universal" interface 
  12836. that can be mapped to any object system. The application would only have to 
  12837. understand a single, common ObjectMgr interface. Under this scheme, specific 
  12838. object managers are defined by subclassing the ObjectMgr class and overriding 
  12839. the ObjectMgr methods to map them into the object system-specific programming 
  12840. interfaces. 
  12841.  
  12842. DSOM's Object Manager, SOMDObjectMgr, is defined as a specific class of 
  12843. ObjectMgr. It defines methods for: 
  12844.  
  12845.    o  Finding servers that implement particular kinds of objects 
  12846.  
  12847.    o  Creating objects in servers 
  12848.  
  12849.    o  Obtaining object identifiers (string IDs) 
  12850.  
  12851.    o  Finding objects, given their identifiers 
  12852.  
  12853.    o  Releasing and destroying objects 
  12854.  
  12855.  These functions will be discussed in the remainder of this section. 
  12856.  
  12857.  Note:  The OMG has standardized an "object lifecycle" service, which includes 
  12858.         support for creating and destroying distributed objects.  The DSOM 
  12859.         Object Manager may be augmented in the future with an OMG-compliant 
  12860.         lifecycle service. 
  12861.  
  12862.  
  12863. ΓòÉΓòÉΓòÉ 8.3.2. Initializing a client program ΓòÉΓòÉΓòÉ
  12864.  
  12865. A client application must declare and initialize the DSOM run time before 
  12866. attempting to create or access a remote object. The SOMD_Init procedure 
  12867. initializes all of the DSOM run time, including the  SOMDObjectMgr object. The 
  12868. global variable, SOMD_ObjectMgr is initialized to point to the local DSOM 
  12869. Object Manager. 
  12870.  
  12871. A client application must also initialize all application classes used by the 
  12872. program. For each class, the corresponding <className>NewClass call should be 
  12873. made. 
  12874.  
  12875. Note:  In non-distributed SOM programs, the <className>New macro (and the new 
  12876.        operator provided for each class by the SOM C++ bindings) implicitly 
  12877.        calls the procedure <className>NewClass when creating a new object. This 
  12878.        is not currently possible in DSOM because, when creating remote objects, 
  12879.        DSOM uses a generic method that is not class-specific. 
  12880.  
  12881.  This was shown in the "Stack" example in section 6.2. In a similar example of 
  12882.  an application that uses "Car" and "Driver" objects, the initialization code 
  12883.  might look like this: 
  12884.  
  12885.   #include <somd.h>    /* needed by all clients */
  12886.   #include <Car.h>     /* needed to access remote Car */
  12887.   #include <Driver.h>  /* needed to access remote Driver */
  12888.  
  12889.   main()
  12890.   {
  12891.       Environment ev; /* ev used for error passing */
  12892.       SOM_InitEnvironment(&ev);
  12893.  
  12894.       /* Do DSOM initialization */
  12895.       SOMD_Init(&ev);
  12896.  
  12897.       /* Initialize application classes */
  12898.       CarNewClass(Car_MajorVersion, Car_MinorVersion);
  12899.       DriverNewClass(Driver_MajorVersion, Driver_MinorVersion);
  12900.       ...
  12901.   }
  12902.  
  12903.  As shown, client programs should include the "somd.h" file (or, for C++ 
  12904.  programs, the "somd.xh" file) in order to define the DSOM run#time interfaces. 
  12905.  
  12906.  Note also that, since Environments are used for passing error results between 
  12907.  a method and its caller, an Environment variable (ev) must be declared and 
  12908.  initialized for this purpose. 
  12909.  
  12910.  The calls to "CarNewClass" and "DriverNewClass" are required if the client 
  12911.  will be creating or accessing Cars and Drivers. The procedures "CarNewClass" 
  12912.  and "DriverNewClass" create class objects for the classes "Car" and "Driver". 
  12913.  When a DSOM Object Manager method like somdNewObject is invoked to create a 
  12914.  "Car", it expects the "Car" class object to exist. If the class does not yet 
  12915.  exist, the "ClassNotFound" exception will be returned. 
  12916.  
  12917.  
  12918. ΓòÉΓòÉΓòÉ 8.3.3. Exiting a client program ΓòÉΓòÉΓòÉ
  12919.  
  12920. At the end of a client program, the SOMD_Uninit procedure must be called to 
  12921. free DSOM run-time objects, and to release system resources such as semaphores, 
  12922. shared memory segments, and so on. SOMD_Uninit should be called even if the 
  12923. client program terminates unsuccessfully; otherwise, system resources will not 
  12924. be released. 
  12925.  
  12926. For example, the exit code in the client program might look like this: 
  12927.  
  12928.     ...
  12929.     SOMD_Uninit(&e);
  12930.     SOM_UninitEnvironment(&e);
  12931. }
  12932.  
  12933. Note also the SOM_UninitEnvironment call, which frees any memory associated 
  12934. with the specified Environment structure. 
  12935.  
  12936. Note:  When a Windows DSOM client receives a WM-QUIT message while processing a 
  12937.        remote method invocation, DSOM will clean up and terminate the client 
  12938.        without returning to the client's WinProc or WinMain. 
  12939.  
  12940.  
  12941. ΓòÉΓòÉΓòÉ 8.3.4. Creating remote objects ΓòÉΓòÉΓòÉ
  12942.  
  12943. Distributed objects can be created in several different ways in DSOM. 
  12944.  
  12945.    o  The client can create an object on any server that implements that class 
  12946.       of object. 
  12947.  
  12948.    o  The client can find a specific server upon which to create an object. 
  12949.  
  12950.    o  A server can create an object and register a reference to the object in 
  12951.       some well-known directory. (An object reference contains information that 
  12952.       reliably identifies a particular object.) 
  12953.  
  12954.  The first two cases are discussed immediately below. The last case is 
  12955.  discussed near the end of this section. 
  12956.  Creating an object in an arbitrary server 
  12957.  
  12958.  Following is an example of how to create a new remote object in the case where 
  12959.  the client does not care in which server the object is created. In this 
  12960.  situation, the client defers these decisions to the DSOM Object Manager 
  12961.  (SOMD_ObjectMgr) by using the somdNewObject method call, which has this IDL 
  12962.  definition: 
  12963.  
  12964.  
  12965.     // (from file om.idl)
  12966.  
  12967.  
  12968.     SOMObject somdNewObject(in Identifier objclass, in string hints);
  12969.  
  12970.     // Returns a new object of the named class.  This is a "basic"
  12971.     // creation method, where the decisions about where and how to
  12972.     // create the object are mostly left up to the Object Manager.
  12973.     // However, the Object Manager may optionally define creation
  12974.     // "hints" which the client may specify in this call.
  12975.  
  12976.  Here is the example of how a remote "Car" would be created using 
  12977.  somdNewObject: 
  12978.  
  12979.   #include <somd.h>
  12980.   #include <Car.h>
  12981.  
  12982.   main()
  12983.   {
  12984.       Environment ev;
  12985.       Car car;
  12986.  
  12987.       SOM_InitEnvironment(&ev);
  12988.       SOMD_Init(&ev);
  12989.  
  12990.       /* create the class object */
  12991.       CarNewClass(Car_MajorVersion, Car_MinorVersion);
  12992.  
  12993.       /* create a Car object on some server, let the
  12994.          Object Manager choose which one */
  12995.       car = _somdNewObject(SOMD_ObjectMgr, &ev, "Car", "");
  12996.       ...
  12997.   }
  12998.  
  12999.  The main argument to the somdNewObject method call is a string specifying the 
  13000.  name of the class of the desired object. The last argument is a string that 
  13001.  may contain "hints" for the Object Manager when choosing a server. In this 
  13002.  example, the client is providing no hints. (Currently, the DSOM Object Manager 
  13003.  simply passes the hints to the server object in a somdCreateObj call.) 
  13004.  Proxy objects 
  13005.  
  13006.  As far as the client program is concerned, when a remote object is created, a 
  13007.  pointer to the object is returned. However, what is actually returned is a 
  13008.  pointer to a proxy object, which is a local representative for the remote 
  13009.  target object. 
  13010.  
  13011.  Proxies are responsible for ensuring that operations invoked on it get 
  13012.  forwarded to the "real" target object that it represents. The DSOM run time 
  13013.  creates proxy objects automatically, wherever an object is returned as a 
  13014.  result of some remote operation. The client program will always have a proxy 
  13015.  for each remote target object on which it operates. Proxies are described 
  13016.  further in the sections entitled "DSOM as a CORBA-compliant Object Request 
  13017.  Broker" and "Advanced Topics". 
  13018.  
  13019.  In the example above, a pointer to a "Car" proxy is returned and put in the 
  13020.  variable "car". Any subsequent methods invoked on "car" will be forwarded and 
  13021.  executed on the corresponding remote "Car" object. 
  13022.  
  13023.  Proxy objects inherit behavior from the SOMDClientProxy class. 
  13024.  Servers and server objects 
  13025.  
  13026.  In DSOM, the process that manages a target object is called the object's 
  13027.  server. Servers are implemented as programs that use SOM classes. The example 
  13028.  above placed no constraints on the DSOM Object Manager as to which server 
  13029.  should create the remote "Car" object. However, if the client desires more 
  13030.  control over distribution of objects, the DSOM Object Manager provides methods 
  13031.  for finding specific servers. 
  13032.  
  13033.  Server implementations are registered with DSOM in an Implementation 
  13034.  Repository. Server implementations are described by a unique ID, a unique 
  13035.  (user-friendly) name, the program name that implements the server, the classes 
  13036.  that are implemented by the server, the machine on which the server is 
  13037.  located, whether the server is multi-threaded, and so forth. (See section 6.6 
  13038.  for more information on registering server implementations.) A client can ask 
  13039.  the DSOM Object Manager to find a particular server: 
  13040.  
  13041.    o  By name 
  13042.  
  13043.    o  By ID 
  13044.  
  13045.    o  By a class it supports 
  13046.  
  13047.  When a client asks for a "server", it is given (a proxy to) a server object 
  13048.  that provides interfaces for managing the objects in the server. There is one 
  13049.  server object per server process. All server objects are instances of the 
  13050.  SOMDServer class, or its subclasses. The default method provided by SOMDServer 
  13051.  for creating objects is: 
  13052.  
  13053.     // (from file somdserv.idl)
  13054.  
  13055.     SOMObject somdCreateObj(in Identifier objclass, in string hints);
  13056.  
  13057.     // Creates an object of the specified class.  This method
  13058.     // may optionally define creation "hints" which the client
  13059.     // may specify in this call.  (Hints are ignored by default.)
  13060.  
  13061.  Section 6.4 explains how to create application-specific server objects, 
  13062.  derived from SOMDServer, which override SOMDServer methods and introduce their 
  13063.  own methods for object management. 
  13064.  Creating an object in a specific server 
  13065.  
  13066.  The following example demonstrates how a client application creates a new 
  13067.  object in a remote server chosen by the client. The DSOM Object Manager method 
  13068.  somdFindServerByName is used to find and create a proxy to the server object 
  13069.  for the server implementation named "myCarServer". The method somdCreateObj is 
  13070.  then invoked on the server object to create the remote "Car". A proxy to the 
  13071.  remote "Car" is returned. (The "Stack" client presented in the previous 
  13072.  section used the same methods to create a remote "Stack".) 
  13073.  
  13074.    /* find a specific Car server */
  13075.       server =
  13076.         _somdFindServerByName(SOMD_ObjectMgr, &ev, "myCarSe           rver");
  13077.  
  13078.    /* create a remote Car object on that server */
  13079.       car = _somdCreateObj(server, &ev, "Car", "");
  13080.       ...
  13081.   }
  13082.  
  13083.  Note:  If the specified server does not provide any implementation of the 
  13084.         desired class, a NULL pointer will be returned and a "ClassNotFound" 
  13085.         exception will be raised. 
  13086.  
  13087.  Three other methods can be invoked on the DSOM Object Manager to find server 
  13088.  implementations: somdFindServer, somdFindServersByClass, and 
  13089.  somdFindAnyServerByClass. The IDL declarations of these methods follow: 
  13090.  
  13091.  
  13092.   SOMDServer somdFindServer(in ImplId serverid);
  13093.  
  13094.   sequence<SOMDServer> somdFindServersByClass(in Identifier objclass);
  13095.  
  13096.   SOMDServer somdFindAnyServerByClass(in Identifier objclass);
  13097.  
  13098.  The somdFindServer method is similar to the somdFindServerByName method, 
  13099.  except that the server's implementation ID (of type ImplId) is used to 
  13100.  identify the server instead of the server's user-friendly name (or "alias"). 
  13101.  The implementation ID is a unique string generated by the Implementation 
  13102.  Repository during server registration. (See section 6.6 for more details.) 
  13103.  
  13104.  The somdFindServersByClass method, given a class name, returns a sequence of 
  13105.  all servers that support the given class. The client program may then choose 
  13106.  which server to use, based on the server's name, program, or other 
  13107.  implementation attributes (e.g., the server is multi-threaded). (See the topic 
  13108.  below, "Inquiring about a remote object's implementation.") 
  13109.  
  13110.  Finally, the somdFindAnyServerByClass method simply selects any one of the 
  13111.  server implementations registered in the Implementation Repository that 
  13112.  supports the given class, and returns a server proxy for that server. 
  13113.  
  13114.  Once the server proxy is obtained, methods like somdCreateObj, shown in the 
  13115.  example above, can be invoked upon it to create new objects. 
  13116.  Inquiring about a remote object's implementation 
  13117.  
  13118.  A client may wish to inquire about the (server) implementation of a remote 
  13119.  object. All objects in a server, including the "server object", share the same 
  13120.  implementation definition. This is common when using the 
  13121.  somdFindServersByClass call, where a sequence of server proxies is returned, 
  13122.  and some choice must be made about which to use. 
  13123.  
  13124.  When a proxy is obtained by a client, the client can inquire about the 
  13125.  underlying server implementation by obtaining its corresponding 
  13126.  ImplementationDef. An ImplementationDef object  contains a set of attributes 
  13127.  that describe a server implementation. To get the ImplementationDef associated 
  13128.  with a remote object, the get_implementation method (implemented on SOMDObject 
  13129.  and inherited by SOMDClientProxy) can be called. 
  13130.  
  13131.  For example, if a program has a proxy for a remote server object, it can get 
  13132.  the ImplementationDef for the server with method calls similar to the 
  13133.  following: 
  13134.  
  13135.  
  13136.       ImplementationDef implDef;
  13137.       SOMDServer server;
  13138.  
  13139.       ...
  13140.       implDef = _get_implementation(server, &ev);
  13141.  
  13142.  Once the ImplementationDef has been obtained, the application can access its 
  13143.  attributes using the _get_impl_xxx methods. 
  13144.  
  13145.  The ImplementationDef class is discussed further in section 6.6, "Configuring 
  13146.  DSOM." 
  13147.  
  13148.  
  13149. ΓòÉΓòÉΓòÉ 8.3.5. Destroying remote objects ΓòÉΓòÉΓòÉ
  13150.  
  13151. There are several ways of destroying objects or their proxies in DSOM, just as 
  13152. there are several ways to create objects. Remote objects can be asked to 
  13153. destroy themselves, or, the SOMDObjectMgr and the SOMDServer can participate in 
  13154. the deletion. 
  13155. Destroying objects via a proxy 
  13156.  
  13157. DSOM provides means for deleting remote objects via their proxies. For example, 
  13158. if somFree is invoked on a proxy, the somFree call gets forwarded directly to 
  13159. the target object, just like any other target method call. For example, 
  13160.  
  13161.  
  13162. _somFree(car);
  13163.  
  13164. frees the remote car.  Note that, by default, invoking somFree on the proxy 
  13165. does not free the proxy, only the remote object.  However, the following call 
  13166. can be issued as part of a client-program initialization, so that invoking 
  13167. somFree on a proxy frees both the remote object and the proxy: 
  13168.  
  13169.    __set_somd21somFree(SOMD_ObjectMgr, ev, TRUE);
  13170.  
  13171. All subsequent invocations of somFree on a proxy object will result in both the 
  13172. remote object and the proxy being freed. 
  13173.  
  13174. To be explicit about whether the proxy or the remote object is being deleted, 
  13175. the methods somdTargetFree and somdProxyFree, defined on proxies, can be used: 
  13176.  
  13177. _somdTargetFree(car, &ev);
  13178. frees the remote "Car" (but not the proxy) and 
  13179.  
  13180. _somdProxyFree(car, &ev);
  13181.  
  13182. frees the proxy (but not the remote "Car"). 
  13183.  
  13184. Note:  CORBA specifies a third method for deleting object references. (Proxies 
  13185.        are a specialized type of object reference.) The method 
  13186.  
  13187.                       _release(car, &ev);
  13188.          deletes the proxy (but not the target object). 
  13189.  
  13190.  
  13191.  Destroying objects via the DSOM Object Manager 
  13192.  
  13193.  Having created a remote object with somdNewObject or somdCreateObj, the remote 
  13194.  object and its local proxy may be destroyed by invoking the method 
  13195.  somdDestroyObject on the DSOM Object Manager using the proxy as an argument. 
  13196.  For example, 
  13197.  
  13198.  
  13199.   /* create the car */
  13200.   car = _somdNewObject(SOMD_ObjectMgr, &ev, "Car", "");
  13201.   ...
  13202.   /* destroy the car (and its proxy) */
  13203.   _somdDestroyObject(SOMD_ObjectMgr, &ev, car);
  13204.  
  13205.  If the client does not want to destroy the remote object, but is finished 
  13206.  working with it, the somdReleaseObject method should be used instead, e.g., 
  13207.  
  13208.   _somdReleaseObject(SOMD_ObjectMgr, &ev, car);
  13209.  
  13210.  This deletes the local proxy, but not the remote object. 
  13211.  
  13212.  Both somdDestroyObject and somdReleaseObject are defined on the ObjectMgr, so 
  13213.  that the Object Manager is aware of the client's actions, in case it wants to 
  13214.  do any bookkeeping. 
  13215.  
  13216.  The object passed to either the somdDestroyObject method or the 
  13217.  somdReleaseObject method can be either a local SOM object or a DSOM proxy 
  13218.  object.  When a local SOM object is passed, somdDestroyObject has the same 
  13219.  behavior as somFree. If a local SOM object is passed to somdReleaseObject, 
  13220.  however, this has no effect. 
  13221.  Destroying objects via a server object 
  13222.  
  13223.  The somdDestroyObject method described above sends a request to delete a 
  13224.  remote object to the object's server. It does so to ensure that the server has 
  13225.  an opportunity to participate in, if not perform, the deletion. The method 
  13226.  defined on the SOMDServer class for destroying objects is somdDeleteObj. If 
  13227.  the client has a proxy for the server object, it can also invoke somdDeleteObj 
  13228.  directly, instead of calling somdDestroyObject. 
  13229.  
  13230.  Destroying objects via the server object, rather than asking the object itself 
  13231.  (as in somFree or somdTargetFree), allows the server object do any clean-up 
  13232.  that is needed. For simple applications, this may not be necessary, but for 
  13233.  applications that provide their own application-tailored server objects, it 
  13234.  may be critical. See, for example, the persistent server example in section 
  13235.  6.4, entitled "Basic Server Programming." 
  13236.  
  13237.  
  13238. ΓòÉΓòÉΓòÉ 8.3.6. Creating remote objects using user-defined metaclasses ΓòÉΓòÉΓòÉ
  13239.  
  13240. An application may wish to define its own constructor methods for a particular 
  13241. class, via a user-supplied metaclass. In this case, the somdNewObject method 
  13242. should not be used, since it simply calls the default constructor method, 
  13243. somNew, defined by SOMClass. 
  13244.  
  13245. Instead, the application can obtain a proxy to the actual class object in the 
  13246. server process. It can do so via the somdGetClassObj method, invoked on the 
  13247. SOMDServer proxy returned by one of the somdFindServerXxx methods. The 
  13248. application-defined constructor method can then be invoked on the proxy for the 
  13249. remote class object. 
  13250.  
  13251. Note:  The same issues apply to destructor methods. If the application defines 
  13252.        its own destructor methods, they can be called via the class object 
  13253.        returned by somdGetClassObj, as opposed to calling somdDestroyObject. 
  13254.  
  13255.  The following example creates a new object in a remote server using an 
  13256.  application-defined constructor method, "makeCar", which is assumed to have 
  13257.  been defined in the metaclass of "Car", named "MetaCar". 
  13258.  
  13259.   #include <somd.h>
  13260.   #include <Car.h>
  13261.   main( )
  13262.   {
  13263.       Environment ev;
  13264.       SOMDServer server;
  13265.       Car car;
  13266.       MetaCar carClass;
  13267.  
  13268.       SOM_InitEnvironment(&ev);
  13269.       SOMD_Init(&ev);
  13270.  
  13271.       /* find a Car server */
  13272.       server = _somdFindAnyServerByClass(SOMD_ObjectMgr, &ev, "Car");
  13273.  
  13274.       /* get the class object for Car */
  13275.       carClass = (MetaCar) _somdGetClassObj(server, &ev, "Car");
  13276.  
  13277.       /* create the car object */
  13278.       car = _makeCar(carClass, &ev, "Red", "Toyota", "2-door");
  13279.  
  13280.       ...
  13281.   }
  13282.  
  13283.  
  13284. ΓòÉΓòÉΓòÉ 8.3.7. Saving and restoring references to objects ΓòÉΓòÉΓòÉ
  13285.  
  13286. A proxy is a kind of "object reference". An object reference contains 
  13287. information that is used to identify a target object. 
  13288.  
  13289. To enable clients to save references to remote objects (in a file system, for 
  13290. example) or exchange references to remote objects (with other application 
  13291. processes), DSOM must be able to externalize proxies. To "externalize a proxy" 
  13292. means to create a string ID for a proxy that can be used by any process to 
  13293. identify the remote target object. DSOM must also support the translation of 
  13294. string IDs back into proxies. 
  13295.  
  13296. The DSOM Object Manager defines two methods for converting between proxies and 
  13297. their string IDs: somdGetIdFromObject and somdGetObjectFromId. 
  13298.  
  13299. Here is an example client program that creates a remote "Car" object. It 
  13300. generates a string ID corresponding to the proxy, and saves the string ID to a 
  13301. file for later use. 
  13302.  
  13303. #include <stdio.h>
  13304. #include <somd.h>
  13305. #include <Car.h>
  13306. main( )
  13307. {
  13308.     Environment ev;
  13309.     Car car;
  13310.     string somdObjectId;
  13311.     FILE* file;
  13312.  
  13313.     SOM_InitEnvironment(&ev);
  13314.     SOMD_Init(&ev);
  13315.  
  13316.     /* create a remote Car object */
  13317.     car = _somdNewObject(SOMD_ObjectMgr, &ev, "Car", "");
  13318.  
  13319.     /* save the reference to the object */
  13320.     somdObjectId = _somdGetIdFromObject(SOMD_ObjectMgr, &ev, car);
  13321.     file = fopen("/u/joe/mycar", "w");
  13322.     fprintf(file, "%s", somdObjectId);
  13323. ...
  13324.  
  13325. Next is an example client program that retrieves the string ID and regenerates 
  13326. a valid proxy for the original remote "Car" object (assuming the remote "Car" 
  13327. object can still be found in the server). 
  13328.  
  13329. ...
  13330.     Environment ev;
  13331.     Car car;
  13332.     char buffer[256];
  13333.     string somdObjectId;
  13334.     FILE* file;
  13335.  
  13336. ...
  13337.     /* restore proxy from its string form */
  13338.     file = fopen("/u/joe/mycar", "r");
  13339.     somdObjectId = (string) buffer;
  13340.     fscanf(file, "%s", somdObjectId);
  13341.     car = _somdGetObjectFromId(SOMD_ObjectMgr, &ev, somdObjectId);
  13342. ...
  13343.  
  13344. Once the proxy has been regenerated, methods can be invoked on the proxy and 
  13345. they will be forwarded to the remote target object, as always. 
  13346.  
  13347. Note:  The somdGetIdFromObject and somdGetObjectFromId methods directly 
  13348.        correspond to the CORBA methods ORB_object_to_string and 
  13349.        ORB_string_to_object, defined on the ORB class. 
  13350.  
  13351.  
  13352.  Finding existing objects 
  13353.  
  13354.  The SOMDObjectMgr and SOMDServer classes support the methods described above, 
  13355.  which allow clients to create objects in servers. However, it is also likely 
  13356.  that clients will want to find and use objects that have already been created, 
  13357.  usually by the servers that implement them. For example, a print service will 
  13358.  create printer objects, and must then export them to clients. In that case, 
  13359.  the calls to somdNewObject or somdCreateObj would be replaced with other 
  13360.  "lookup" calls on some directory (server) object which would take an object 
  13361.  name or identifier and return a proxy to a corresponding remote object. 
  13362.  Likewise, the server that owns the object would register the exported object 
  13363.  in the directory. 
  13364.  
  13365.  It is important to understand that DSOM does not provide a directory service 
  13366.  such as the one described. But such a directory object could be implemented by 
  13367.  the application, where a table or collection object maps object names to 
  13368.  proxies. The string IDs for the proxies in the directory object could be saved 
  13369.  using a file (as above) or a persistent object (via the Persistence Framework 
  13370.  of SOMobject Developer Toolkit). A directory server implemented using DSOM 
  13371.  could be used to share the directory among processes. 
  13372.  
  13373.  Upon a lookup call, the directory server could find the corresponding proxy 
  13374.  (or its string ID) in the directory, and return it to the caller. 
  13375.  
  13376.  
  13377. ΓòÉΓòÉΓòÉ 8.3.8. Finding server objects ΓòÉΓòÉΓòÉ
  13378.  
  13379. The DSOM Object Manager can be used to find server object proxies using the 
  13380. somdFindServerXxx methods. However, it is important to point out that an 
  13381. application can also augment those services, by managing server proxies itself. 
  13382. Server proxies can be maintained in an application-specific directory, stored 
  13383. in a file, or passed from process to process, just as any other proxies. 
  13384.  
  13385.  
  13386. ΓòÉΓòÉΓòÉ 8.3.9. Invoking methods on remote objects ΓòÉΓòÉΓòÉ
  13387.  
  13388. As described earlier, DSOM proxies are local representatives of remote objects, 
  13389. and as such, they can be treated like the target objects themselves. Method 
  13390. calls are invoked in exactly the same manner as if the object is local. This is 
  13391. true both for method calls using the static bindings (as most of our examples 
  13392. have shown), as well as for dynamic dispatching calls, where SOM facilities 
  13393. (such as the somDispatch method) are used to construct method calls at run 
  13394. time. 
  13395.  
  13396. CORBA 1.1 also defines a dynamic invocation interface that is implemented by 
  13397. DSOM. It is described later in section 6.9, "Advanced Topics". 
  13398.  
  13399. The DSOM run time is responsible for transporting any input method argument 
  13400. values supplied by the caller (defined by legal IDL types) to the target object 
  13401. in a remote call. Likewise, the DSOM run time transports the return value and 
  13402. any output argument values back to the caller following the method call. 
  13403.  
  13404. Note:  DSOM uses the Interface Repository (IR) to discover the "signature" of a 
  13405.        method (that is, the method's prototype). It is important that the 
  13406.        contents of the IR match the method bindings used by the application 
  13407.        program (i.e. the same IDL file is used to update the IR and to generate 
  13408.        bindings). 
  13409.  
  13410.  
  13411.  Determining memory allocation and ownership 
  13412.  
  13413.  When a method is invoked that returns a result of type string, sequence, or 
  13414.  array, DSOM will allocate memory in the client's address space for the result. 
  13415.  Ownership of this memory becomes the responsibility of the client program. 
  13416.  When the client program has finished using it,  the client should free the 
  13417.  memory using the ORBfree function, rather than using free or SOMFree.  (This 
  13418.  is because the memory has been allocated by DSOM using special memory 
  13419.  management techniques; therefore, the client should ask DSOM to also free the 
  13420.  memory.) 
  13421.  
  13422.  When invoking a method using DSOM, the client program is responsible for 
  13423.  providing storage for all inarguments and for all inout/out arguments,  with 
  13424.  the following exceptions: DSOM will allocate storage for a String or for the 
  13425.  _buffer field of a sequence when used as an out  argument, and will allocate 
  13426.  storage for the _value field of an any when used as an inout or  out argument. 
  13427.  This storage becomes the responsibility of the client program and should later 
  13428.  be freed using ORBfree. For a string or sequence used as an  inout argument, 
  13429.  the out result is constrained to be no larger than the size of the in argument 
  13430.  allocated by the client. 
  13431.  
  13432.  DSOM can make remote invocations only of methods whose parameter types are 
  13433.  among the following IDL types:  basic types (short, long, unsigned short, 
  13434.  unsigned long, float, double, char, boolean, octet), enum, struct, union, 
  13435.  sequence, string, array, any, and object. The members of a struct, union, 
  13436.  sequence, or array and the value of an any, must also be from the above list 
  13437.  of supported DSOM types. 
  13438.  
  13439.  In addition to the preceding types, DSOM also supports method parameters of 
  13440.  type pointer to one of the above types (for example, long*) Pointers to 
  13441.  pointers are not supported, however, and pointers embedded within one of the 
  13442.  above types (for example, a pointer within a struct) are not supported The 
  13443.  "void *" type is also not supported. Currently, DSOM has the limitation that 
  13444.  NULL pointer values cannot be returned as inout or out method arguments 
  13445.  although it is expected that this limitation will be addressed in a future 
  13446.  release. 
  13447.  
  13448.  Types declared as SOMFOREIGN types are not currently supported by DSOM. 
  13449.  Because the SOM somI is declared as a SOMFOREIGN type, this implies that any 
  13450.  method having a parameter of type somId cannot be invoked remotely using DSOM. 
  13451.  This restriction includes the  SOM methods: somRespondsTo, somSupportsMethod, 
  13452.  somGetMethodDescriptor, somGetMethodIndex, and somGetNthMethodInfo. 
  13453.  
  13454.  When a method parameter is an object type (that is, an instance of SOMObject 
  13455.  or some class derived from SOMObject), a client program making a remote 
  13456.  invocation of that method must pass an object reference for that parameter, 
  13457.  rather than passing a local SOMObject, unless the client program is also DSOM 
  13458.  server program, in which case DSOM will automatically convert the local object 
  13459.  into an object reference. 
  13460.  
  13461.  Methods having the procedure SOM IDL modifier cannot be invoked remotely using 
  13462.  DSOM.  This is because these "methods" are called directly, rather than via 
  13463.  the normal method resolution mechanisms on which DSOM relies. 
  13464.  
  13465.  
  13466.  Determining memory allocation and ownership 
  13467.  
  13468.  When a method is invoked that returns a result of type string, sequence, or 
  13469.  array, DSOM will allocate memory in the client's address space for the result. 
  13470.  Ownership of this memory becomes the responsibility of the client program. 
  13471.  When the client program has finished using it, the client should free the 
  13472.  memory using the ORBfree function, rather than using free or SOMFree (This is 
  13473.  because the memory has been allocated by DSOM using special memory management 
  13474.  techniques; therefore, the client should ask DSOM to also free the memory.) 
  13475.  
  13476.  When invoking a method using DSOM, the client program is  responsible for 
  13477.  providing storage for all in arguments and for all inout/out arguments, with 
  13478.  the following exceptions: DSOM will allocate storage for a string or for the 
  13479.  _buffer field of a sequence when used as an out argument, and will allocate 
  13480.  storage for the_value field of an any when used as an inout or out argument. 
  13481.  This storage becomes the responsibility of the client program and should later 
  13482.  be freed using ORBfree. For a string or sequence used as an inout argument, 
  13483.  the out result is constrained to be no larger than the size of the in argument 
  13484.  allocated by the client. 
  13485.  
  13486.  
  13487. ΓòÉΓòÉΓòÉ 8.3.10. Passing object references in method calls ΓòÉΓòÉΓòÉ
  13488.  
  13489. When pointers to objects are returned as method output values (as in the 
  13490. previous examples), DSOM automatically converts the object pointers (in the 
  13491. server) to object proxies in the client. 
  13492.  
  13493. Likewise, when a client passes object (proxy) pointers as input arguments to a 
  13494. method, DSOM automatically converts the proxy argument in the client to an 
  13495. appropriate object reference in the server. 
  13496.  
  13497. Note:  If the proxy is for an object that is in the same server as the target 
  13498.        object, DSOM gives the object reference to the server object for 
  13499.        resolution to a SOM object pointer. Otherwise, DSOM leaves the proxy 
  13500.        alone, since the proxy must refer to an object in some process other 
  13501.        than the target's server. 
  13502.  
  13503.  
  13504. ΓòÉΓòÉΓòÉ 8.3.11. Memory management ΓòÉΓòÉΓòÉ
  13505.  
  13506. DSOM programs must manage four different kinds of memory resources: objects, 
  13507. object references, Environment structures, and blocks of memory. There are 
  13508. different techniques for allocating and releasing each kind of resource. 
  13509.  
  13510. Objects and object references 
  13511.  
  13512. Creating and destroying remote objects was discussed previously in this section 
  13513. (see "Creating remote objects" and "Destroying remote objects"). Creating and 
  13514. destroying local objects is described in section 3.2, "Using SOM Classes--the 
  13515. Basics," in Chapter 3, "Using SOM Classes in Client Programs." Object 
  13516. references are typically created automatically by DSOM as needed by the client 
  13517. program. They are also released in the client program by using either the 
  13518. release method or the somdProxyFree method. (The two methods are equivalent.) 
  13519.  
  13520. Environment structures 
  13521.  
  13522. When a client invokes a method and the method returns an exception in the 
  13523. Environment structure, it is the client's responsibility to free the exception. 
  13524. This is done by calling either exception_free or somdExceptionFree on the 
  13525. Envirnmen structure in which the exception was returned. (The two functions are 
  13526. equivalent.) A similar function, somExceptionFree, is available for SOM 
  13527. programmers however DSOM programmers can use somdExceptionFree to free all 
  13528. exceptions (regardless of whether they were returned from a local or remote 
  13529. method call). 
  13530.  
  13531. Blocks of memory 
  13532.  
  13533. For allocating and releasing blocks of memory within a client program, SOM 
  13534. provides the SOMMalloc and SOMFree functions (analogous to the C "mallo" and 
  13535. "free" functions). The "Memory Management" section of Chapter 3 describes these 
  13536. functions. To release memory allocated by DSOM in response to a remote method 
  13537. call, however, DSOM client programs should use the ORBfree function 
  13538.  
  13539. For example, when a method is invoked that returns a result of type string, 
  13540. sequence, or array, DSOM will allocate memory for the result in the client's 
  13541. address space. Ownership of this memory becomes the responsibility of the 
  13542. client program. When finished using this memory, the client program should free 
  13543. it using the ORBfree function, rather than free or SOMFree. This is because the 
  13544. memory has been allocated by DSOM using special memory-management techniques; 
  13545. therefore, the client should ask DSOM to also free the memory. If the storage 
  13546. is freed using SOMFree rather than ORBfree, then memory leaks will result. 
  13547.  
  13548. The differences between the SOMFree and ORBfree functions are twofold: 
  13549.  
  13550.    1. First, SOMFree should only be used to free memory not allocated by 
  13551.       DSO(for example, memory the client program allocated itself using 
  13552.       SOMMalloc), while ORBfree should be used to free memory allocated by DSOM 
  13553.       in response to a remote method call. 
  13554.  
  13555.    2. Second, SOMFee only frees a single block of memory (in the same way that 
  13556.       the C "free" function does), while ORBfree will free an entire data 
  13557.       structure, including any allocated blocks of memory within in. For 
  13558.       example, if a remote method call returns a sequence of structs, and each 
  13559.       struct contains a string, ORBfree will free, with a single call, not only 
  13560.       the sequence's "_buffer" member, but also each struct and all the strings 
  13561.       within the structs. Freeing a similar data structure using SOMFree would 
  13562.       require multiple calls (one for each call to SOMMalloc used to build the 
  13563.       data structure). 
  13564.  
  13565.  Some programmers may wish to use a single function to free blocks of memory, 
  13566.  regardless of whether they were allocated locally or by DSOM in response to a 
  13567.  remote method call. For these programmers, DSOM provides a function, 
  13568.  SOMD_NoORBfree, which can be called just after calling SOMD_Init in the client 
  13569.  program. (It requires no arguments and returns no value.) This function 
  13570.  specifies that the client program will free all memory blocks using SOMFree, 
  13571.  rather than ORBfree. In response to this call, DSOM will not keep track of the 
  13572.  memory it allocates for the client. Instead, it assumes that the client 
  13573.  program will be responsible for walking all data structures returned from 
  13574.  remote method calls, while calling SOMFree for each block of memory within. 
  13575.  Memory management for method parameters 
  13576.  
  13577.  For each method, five SOM IDL modifiers are available to specify the method's 
  13578.  memory-management policy  (that is, whether the caller or the object owns the 
  13579.  parameters' memory after the method is invoked). These modifiers are 
  13580.  memory_management, caller_owns_result, caller_owns_parameters, 
  13581.  object_owns_result, and object_owns_parameters. For a complete description of 
  13582.  these modifiers and their meanings, see the section entitled "Implementation 
  13583.  Statements" in Chapter 4, "SOM IDL and the SOM Compiler." 
  13584.  
  13585.  Note that the memory-management policy for a particular parameter applies to 
  13586.  the parameter and all the memory embedded within it (for example, if a struct 
  13587.  is owned by the caller, then so are all the struct's members). Also note that 
  13588.  the "object-owned" memory-management policy, specified by the 
  13589.  object_owns_result and object_owns_parameters modifiers, is not  supported by 
  13590.  DSM for metods invoked using the Dynamic Invocation Interface (DII). (This is 
  13591.  because the "object-owned" policy is not CORBA-compliant, and because it 
  13592.  precludes reusing Request objects to invoke a method multiple times.) 
  13593.  The CORBA policy for parameter memory management When a class contains the SOM 
  13594.  IDL modifier memory_management = corba, this signifies that all methods 
  13595.  introduced by the class follow the CORBA specification for parameter memory 
  13596.  management, except where a particular method has an explicit modifier 
  13597.  (object_owns_result or object_owns_parameters) that indicates otherwise. The 
  13598.  remainder of this section describes the CORBA specification for parameter 
  13599.  memory management. 
  13600.  
  13601.  Caller frees parameters and return results 
  13602.  
  13603.  The CORBA memory-management policy specifies that the caller of a method is 
  13604.  responsible for freeing all parameters and the return result after the method 
  13605.  call is complete. This applies regardless of whether the parameter was 
  13606.  allocated by the caller or the object (or, in the case of a remote method 
  13607.  call, by DSOM). In other words, the CORBA policy asserts that parameters are 
  13608.  uniformly "caller-owned". 
  13609.  
  13610.  Allocation responsibilities 
  13611.  
  13612.  Whether the parameter or return result should be allocated by the caller or by 
  13613.  the object depends on the type  of the parameter and its mode  ("in", "inout", 
  13614.  "out", or "return"). In general, the caller is responsible for allocating 
  13615.  storage for most parameters and return results. More specifically, CORBA 
  13616.  requires that storage for all "in" arguments, for all "inout" or "out" 
  13617.  arguments, and for all "return" results must be provided by the client 
  13618.  program, with certain exceptions as itemized below. 
  13619.  
  13620.  The object is responsible for allocating storage as follows: 
  13621.  
  13622.    o  for strings when used as "out" arguments or as "return" results 
  13623.  
  13624.    o  for the "_buffer" field of sequences when used as "out" arguments or as 
  13625.       "return" results, 
  13626.  
  13627.    o  for the "_value" field of anys when used as "inout" or "out" arguments or 
  13628.       as "return" results, 
  13629.  
  13630.    o  for pointer types when used as "inout" or "out" arguments or as "return" 
  13631.       results, 
  13632.  
  13633.    o  for arrays when used as "return" results, and 
  13634.  
  13635.    o  for objects when used as "inout" or "out" arguments or as "return" 
  13636.       results. 
  13637.  
  13638.  Note:  For "inout" strings and sequences, the "out" result is constrained to 
  13639.         be no larger than the size of the "in" argument allocated by the 
  13640.         client. 
  13641.  
  13642.  Ownership of memory allocated in the above cases becomes the responsibility of 
  13643.  the client program. For remote method calls, when a remote object allocates 
  13644.  memory for a parameter or "return" value, DSOM subsequently allocates memory 
  13645.  in the client's address space for the parameter or result. For a 
  13646.  parameter/result that is an object (rather than a block of memory) DSOM 
  13647.  automatically creates an object reference (a proxy object) in the client's 
  13648.  address space. In each case, the memory or the proxy object becomes the 
  13649.  responsibility of the client program and should later be freed by the client, 
  13650.  using ORBfree for blocks of memory or release for proxy objects. 
  13651.  The `somdReleaseResources' method and object-owned parameters 
  13652.  
  13653.  As stated earlier, the CORBA policy asserts that method parameters and return 
  13654.  results are uniformly caller-owned. This means the method caller has the 
  13655.  responsibility for freeing memory after invoking a method, regardless of 
  13656.  whether the memory was allocated by the caller or the object. 
  13657.  
  13658.  A class implementor can designate certain method parameters and results as 
  13659.  object-owned, however, by using the object_owns_result and 
  13660.  object_owns_parameters SOM IDL modifiers. These modifiers signify that the 
  13661.  object, rather than the caller, is responsible for freeing the memory 
  13662.  associated with the parameter/result. For "in" parameters, the object can free 
  13663.  the memory any time after receiving it; for "inout" and "out" parameters, and 
  13664.  for return results, the object will free the memory sometime before the object 
  13665.  is destroyed. (See the section entitled "Implementation statements" in Chapter 
  13666.  4, "SOM IDL and the SOM Compiler," for more information on these modifiers.) 
  13667.  
  13668.  When a DSOM client program makes a remote method invocation, via a proxy, and 
  13669.  the method being invoked has an object-owned parameter or return result, then 
  13670.  the client-side memory associated with the parameter/result will be owned by 
  13671.  the caller's proxy, and the server-side memory will be owned by the remote 
  13672.  object. The memory owned by the caller's proxy will be freed when the proxy is 
  13673.  released by the client program. (The time at which the server-side memory will 
  13674.  be freed depends on the implementation of the remote object.) 
  13675.  
  13676.  A DSOM client can also instruct a proxy object to free all memory that it owns 
  13677.  on behalf of the client without releasing the proxy (assuming that the client 
  13678.  program is finished using the object-owned memory), by invoking the 
  13679.  somdReleaseResource method on the proxy object. Calling somdReleaseResources 
  13680.  can prevent unused memory from accumulating in a proxy. 
  13681.  
  13682.  For example, consider a client program repeatedly invoking a remote method 
  13683.  "get_string", which returns a string that is designated (in SOM IDL) as 
  13684.  "object-owned". The proxy on which the method is invoked will store the memory 
  13685.  associated with all the returned strings, even if the strings are not unique, 
  13686.  until the proxy is released. If the client program only uses the last result 
  13687.  returned from "get_string", then unused memory accumulates in the proxy. The 
  13688.  client program can prevent this by invoking somdReleaseResources on the proxy 
  13689.  object periodicall (for example, each time it finishes using the result of the 
  13690.  last "get_string" call). 
  13691.  
  13692.  
  13693. ΓòÉΓòÉΓòÉ 8.3.12. Writing clients that are also servers ΓòÉΓòÉΓòÉ
  13694.  
  13695. In many applications, processes may need to play both client and server roles. 
  13696. That is, objects in the process may make requests of remote objects on other 
  13697. servers, but may also implement and export objects, requiring that it be able 
  13698. to respond to incoming requests. Details of how to write programs in this 
  13699. peer-to-peer style are explained in section 6.9, "Advanced Topics". 
  13700.  
  13701.  
  13702. ΓòÉΓòÉΓòÉ 8.3.13. Compiling and linking clients ΓòÉΓòÉΓòÉ
  13703.  
  13704. All client programs must include the header file "somd.h" (or for C++, 
  13705. "somd.xh") in addition to any "<className>.h" (or "<className>.xh") header 
  13706. files they require from application classes. All DSOM client programs must link 
  13707. to the SOMobjects Toolkit library: "libsomtk.a" on AIX and "somtk.lib" on OS/2. 
  13708. For more information, see the topic "Compiling and linking" in Chapter 3, 
  13709. "Using SOM Classes in Client Programs." 
  13710.  
  13711.  
  13712. ΓòÉΓòÉΓòÉ 8.4. Basic Server Programming ΓòÉΓòÉΓòÉ
  13713.  
  13714. Server programs execute and manage object implementations. That is, they are 
  13715. responsible for: 
  13716.  
  13717.    o  Notifying the DSOM daemon that they are ready to begin processing 
  13718.       requests, 
  13719.  
  13720.    o  Accepting client requests, 
  13721.  
  13722.    o  Loading class library DLLs when required, 
  13723.  
  13724.    o  Creating/locating/destroying local objects, 
  13725.  
  13726.    o  Demarshalling client requests into method invocations on their local 
  13727.       objects, 
  13728.  
  13729.    o  Marshalling method invocation results into responses to clients, and 
  13730.  
  13731.    o  Sending responses back to clients. 
  13732.  
  13733.  As mentioned previously, DSOM provides a simple, "generic" server program that 
  13734.  performs all of these tasks. All the server programmer needs to provide are 
  13735.  the application class library(ies) DLL that the implementer wants to 
  13736.  distribute. Optionally, the programmer can also supply an application#specific 
  13737.  server class, derived from SOMDServer. (The SOMDServer class can be used by 
  13738.  default.) The server program does the rest automatically. 
  13739.  
  13740.  The "generic" server program is called somdsvr and can be found in 
  13741.  /usr/lpp/som/bin/somdsvr on AIX and in %SOMBASE%\bin\somdsvr.exe on OS/2. 
  13742.  
  13743.  Some applications may require additional flexibility or functionality than 
  13744.  what is provided by the generic server program. In that case, 
  13745.  application-specific server programs can be developed. This section discusses 
  13746.  the steps involved in writing such a server program. 
  13747.  
  13748.  To create a server program, a server writer needs to know what services the 
  13749.  DSOM run-time environment will provide and how to use those services to 
  13750.  perform the duties (listed above) of a server. The DSOM run-time environment 
  13751.  provides several key objects that can be used to perform server tasks. These 
  13752.  objects and the services they provide will be discussed in this section. 
  13753.  Examples showing how to use the run-time objects to write a server are also 
  13754.  shown. 
  13755.  
  13756.  
  13757. ΓòÉΓòÉΓòÉ 8.4.1. Server run-time objects ΓòÉΓòÉΓòÉ
  13758.  
  13759. There are three DSOM run-time objects that are important in a server: 
  13760.  
  13761.    o  The server's implementation definition (ImplementationDef), 
  13762.  
  13763.    o  The SOM Object Adapter (SOMOA), and 
  13764.  
  13765.    o  The application-specific server object (an instance of either SOMDServer 
  13766.       or a class derived from SOMDServer). 
  13767.  
  13768.  Server implementation definition 
  13769.  
  13770.  A server's implementation definition must be registered in the Implementation 
  13771.  Repository before a server can be used. When a client attempts to invoke a 
  13772.  method on a remote object, DSOM consults the Implementation Repository to find 
  13773.  the location of the target object's server. 
  13774.  
  13775.  An implementation definition is represented by an object of class 
  13776.  ImplementationDef, whose attributes describe a server's ID, user-assigned 
  13777.  alias, host name, program pathname, the class of its server object, whether or 
  13778.  not it is multi-threaded, and so forth. Implementation IDs uniquely identify 
  13779.  servers within the Implementation Repository, and are used as keys into the 
  13780.  Implementation Repository when retrieving the ImplementationDef for a 
  13781.  particular server. 
  13782.  
  13783.  It is possible to change the implementation characteristics of a server, even 
  13784.  to the point of using a completely different server program on another machine 
  13785.  (with Workgroup DSOM). Thus, the implementation ID identifies a logical 
  13786.  server, and the ImplementationDef describes the current implementation of that 
  13787.  logical server. 
  13788.  
  13789.  See the topic "Registering Servers and Classes" in section 6.6 for details on 
  13790.  server registration. Two registration methods are described: "manual," (via 
  13791.  the regimpl, the wregimpl, or the pregimpl utility) and "programmatic," 
  13792.  ImplRepository methods. 
  13793.  
  13794.  When a server is initialized, it must retrieve a copy of its 
  13795.  ImplementationDef, and keep it in a global variable (SOMD_ImplDefObject). This 
  13796.  variable is used by the DSOM run time. (Client-only programs may leave the 
  13797.  SOMD_ImplDefObject variable set to NULL.) 
  13798.  SOM Object Adapter (SOMOA) 
  13799.  
  13800.  The SOM Object Adapter (SOMOA) is the main interface between the server 
  13801.  application and the DSOM run time. The SOMOA is responsible for most of the 
  13802.  server duties listed at the beginning of this section. In particular, the 
  13803.  SOMOA object handles all communications an interpretation of inbound requests 
  13804.  and outbound results. When clients send requests to a server, the requests are 
  13805.  received and processed by the SOMOA. 
  13806.  
  13807.  The SOMOA works together with the server object to create and resolve DSOM 
  13808.  references to local objects, and dispatch methods on objects. 
  13809.  
  13810.  There is one SOMOA object per server process. (The SOMOA class is implemented 
  13811.  as a single instance class.) 
  13812.  Server object 
  13813.  
  13814.  Each server process contains a single server object, which has the following 
  13815.  responsibilities for managing objects in the server: 
  13816.  
  13817.    o  Provides an interface to client applications for basic object creation 
  13818.       and destruction services, as well as any other application-specific 
  13819.       object-management services that may be required by clients. For example, 
  13820.       a print server may have a method that returns a list of all printers 
  13821.       managed by that server. Clients may call this method to find out what 
  13822.       printers are available. 
  13823.  
  13824.    o  Provides an interface to the SOM Object Adapter for support in the 
  13825.       creation and management of DSOM object references (which are used 
  13826.       identify an object in the server), and for dispatching requests. 
  13827.  
  13828.    o  The server class, SOMDServer, defines the base interface that must be 
  13829.       supported by any server object. In addition, SOMDServer provides a 
  13830.       default implementation that is suited to managing transient SOM objects 
  13831.       in a server. This section will show how an application might override the 
  13832.       basic SOMDServer methods and introduce new methods in order to tailor the 
  13833.       server object functionality to a particular application. 
  13834.  
  13835.  
  13836. ΓòÉΓòÉΓòÉ 8.4.2. Server activation ΓòÉΓòÉΓòÉ
  13837.  
  13838. Server programs may be activated either 
  13839.  
  13840.    o  Automatically by the DSOM daemon, somdd, or 
  13841.  
  13842.    o  Manually via command line invocation, or under application control. 
  13843.  
  13844.  When a server is activated automatically by somdd, it will be passed a single 
  13845.  argument (in argv[1]) that is the implementation ID assigned to the server 
  13846.  implementation when it was registered into the Implementation Repository 
  13847.  (discussed above and in section 6.6, "Configuring DSOM Applications"). This is 
  13848.  useful when the server program cannot know until activation which "logical" 
  13849.  server it is implementing. (This is true for the generic server provided with 
  13850.  DSOM.) The implementation ID is used by the server to retrieve its 
  13851.  ImplementationDef from the Implementation Repository. 
  13852.  
  13853.  A server that is not activated by somdd may obtain its ImplementationDef from 
  13854.  the Implementation Repository in any manner that is convenient: by ID, by 
  13855.  alias, and so forth. Moreover, a server may choose to "register itself" 
  13856.  dynamically, as part of its initialization. To do so, the server would use the 
  13857.  programmatic interface to the Implementation Repository. 
  13858.  
  13859.  For example, suppose that the server program "myserver" was designed so that 
  13860.  it could be activated either automatically or manually. This requires that it 
  13861.  be written to expect the implementation ID as its first argument, and to use 
  13862.  that argument to retrieve its ImplementationDef from the Implementation 
  13863.  Repository. If an application defines a server in the Implementation 
  13864.  Repository whose implementation ID is 
  13865.  
  13866.   2bcdc4f2-0f62f780-7f-00-10005aa8afdc
  13867.  then "myserver" could be run as that server by invoking the following command: 
  13868.  
  13869.   myserver 2bcdc4f2-0f62f780-7f-00-10005aa8afdc
  13870.  
  13871.  AIX users should be aware that, unless the SetUserID mode bit is set on the 
  13872.  file containing the server program, the UID for the server process will be 
  13873.  inherited from the somdd process. To set the SetUserID mode bit from the AIX 
  13874.  command line, type one of the following commands: 
  13875.  
  13876.   chmod 4000 <filename>     - or -
  13877.   chmod u+s <filename>
  13878.  
  13879.  where "<filename>" denotes the name of the file containing the server program. 
  13880.  For additional details, see the "chmod" command in InfoExplorer or consult the 
  13881.  "man" pages. 
  13882.  
  13883.  
  13884. ΓòÉΓòÉΓòÉ 8.4.3. Initializing a server program ΓòÉΓòÉΓòÉ
  13885.  
  13886.  
  13887. Initializing the DSOM run-time environment 
  13888.  
  13889. The first thing the server program should do is to initialize the DSOM run time 
  13890. by calling the SOMD_Init function. This causes the various DSOM run-time 
  13891. objects to be created and initialized, including the Implementation Repository 
  13892. (accessible via the global variable SOMD_ImplRepObject), which is used in the 
  13893. next initialization step. 
  13894. Initializing the server's ImplementationDef 
  13895.  
  13896. Next, the server program is responsible for initializing its implementationDef, 
  13897. referred to by the global variable SOMD_ImplDefObject. It is initialized to 
  13898. NULL by SOMD_Init. (For client programs it should be left as NULL.) If the 
  13899. server implementation was registered with the Implementation Repository before 
  13900. the server program was activated (as will be the case for all servers that are 
  13901. activated automatically by somdd), then the ImplementationDef can be retrieved 
  13902. from the Implementation Repository. Otherwise, the server program can register 
  13903. its implementation with the Implementation Repository dynamically (as shown in 
  13904. section 6.6, "Configuring DSOM applications"). 
  13905.  
  13906. The server can retrieve its ImplementationDef from the Implementation 
  13907. Repository by invoking the find_impldef method on SOMD_ImplRepObject.  It 
  13908. supplies, as a key, the implementation ID of the desired ImplementationDef. 
  13909.  
  13910. The following code shows how a server program might initialize the DSOM 
  13911. run-time environment and retrieve its ImplementationDef from the Implementation 
  13912. Repository. 
  13913.  
  13914. #include <somd.h> /* needed by all servers */
  13915. main(int argc, char **argv)
  13916. {
  13917.    Environment ev;
  13918.    SOM_InitEnvironment(&ev);
  13919.  
  13920. /* Initialize the DSOM run-time environment */
  13921.    SOMD_Init(&ev);
  13922.  
  13923. /* Retrieve its ImplementationDef from the Implementation
  13924.    Repository by passing its implementation ID as a key */
  13925.    SOMD_ImplDefObject =
  13926.       _find_impldef(SOMD_ImplRepObject, &ev, argv[1]);
  13927. ...
  13928. }
  13929.  
  13930. Initializing the SOM Object Adapter 
  13931.  
  13932. The next step the server must take before it is ready to accept and process 
  13933. requests from clients is to create a SOMOA object and initialize the global 
  13934. variable SOMD_SOMOAObject to point to it. This is accomplished by the 
  13935. assignment: 
  13936.  
  13937. SOMD_SOMOAObject = SOMOANew();
  13938.  
  13939. Note:  The SOMOA object is not created automatically by SOMD_Init because it is 
  13940.        only required by server processes. 
  13941.  
  13942.  After the global variables have been initialized, the server can do any 
  13943.  application-specific initialization required before processing requests from 
  13944.  clients. Finally, when the server is ready to process requests, it must call 
  13945.  the impl_is_ready method on the SOMOA: 
  13946.  
  13947.   _impl_is_ready(SOMD_SOMOAObject, &ev, SOMD_ImplDefObject);
  13948.  
  13949.  The SOMOA will then set up a communications port for incoming messages, which 
  13950.  it registers with the DSOM daemon. Once the DSOM daemon has been notified of 
  13951.  the server's port, it assists client applications in "binding" (i.e., 
  13952.  establishing a connection) to that server. 
  13953.  
  13954.  The impl_is_ready method also causes the server object, whose class is defined 
  13955.  in the server's ImplementationDef, to be created. The server object can be 
  13956.  referenced through the global variable, SOMD_ServerObject. 
  13957.  When initialization fails 
  13958.  
  13959.  It is possible that a server will encounter some error when initializing 
  13960.  itself. Servers must attempt to notify DSOM that their activation failed, 
  13961.  using the activate_impl_failed method. This method is called as follows: 
  13962.  
  13963.   /* tell the daemon (via SOMOA) that activation failed */
  13964.   _activate_impl_failed(SOMD_SOMOAObject,&ev, SOMD_ImplDefObject, rc);
  13965.  Server writers should be aware, however, that until the server's 
  13966.  SOMD_ImpldefObject has been initialized, it is not possible to call the 
  13967.  _activate_impl_failed method on the DSOM daemon. 
  13968.  
  13969.  Note:  A server program should not call activate_impl_failed once it has 
  13970.         called impl_is_ready. 
  13971.  
  13972.  
  13973. ΓòÉΓòÉΓòÉ 8.4.4. Processing requests ΓòÉΓòÉΓòÉ
  13974.  
  13975. The SOMOA is the object in the DSOM run-time environment that receives client 
  13976. requests and transforms them into method calls on local server objects. In 
  13977. order for SOMOA to listen for a request, the server program must invoke one of 
  13978. two methods on SOMD_SOMOAObject. If the server program wishes to turn control 
  13979. over to SOMD_SOMOAObject completely (that is, effectively have SOMD_SOMOAObject 
  13980. go into an infinite request-processing loop), then it invokes the 
  13981. execute_request_loop method on SOMD_SOMOAObject as follows: 
  13982.  
  13983. rc = _execute_request_loop(SOMD_SOMOAObject, &ev, SOMD_WAIT);
  13984.  
  13985. Note:  This is the way the DSOM provided "generic" server program interacts 
  13986.        with SOMD_SOMOAObject. 
  13987.  
  13988.  The execute_request_loop method takes an input parameter of type Flags. The 
  13989.  value of this parameter should be either SOMD_WAIT or SOMD_NO_WAIT. If 
  13990.  SOMD_WAIT is passed as argument, execute_request_loop will return only when an 
  13991.  error occurs. If SOMD_NO_WAIT is passed, it will return when there are no more 
  13992.  outstanding messages to be processed. SOMD_NO_WAIT is usually used when the 
  13993.  server is being used with the event manager. See the topic "Peer vs. 
  13994.  client-server processes" in section 6.9, "Advanced Topics," for more details. 
  13995.  
  13996.  If the server wishes to incorporate additional processing between request 
  13997.  executions, it can invoke the execute_next_request method to receive and 
  13998.  execute requests one at a time: 
  13999.  
  14000.   for(;;) {
  14001.      rc = _execute_next_request(SOMD_SOMOAObject, &ev, SOMD_NO_WAIT);
  14002.      /* perform app-specific code between messages here, e.g., */
  14003.         if (!rc) numMessagesProcessed++;
  14004.   }
  14005.  
  14006.  Just like execute_request_loop, execute_next_request has a Flags argument that 
  14007.  can take one of two values: SOMD_WAIT or SOMD_NO_WAIT. If execute_next_request 
  14008.  is invoked with the SOMD_NO_WAIT flag and no message is available, the method 
  14009.  returns immediately with a return code of SOMDERROR_NoMessages. If a request 
  14010.  is present, it will execute it. Thus, it is possible to "poll" for incoming 
  14011.  requests using the SOMD_NO_WAIT flag. 
  14012.  
  14013.  
  14014. ΓòÉΓòÉΓòÉ 8.4.5. Exiting a server program ΓòÉΓòÉΓòÉ
  14015.  
  14016. When a server program exits, it should notify the DSOM run time that it is no 
  14017. longer accepting requests. This should be done whether the program exits 
  14018. normally, or as the result of an error. If this is not done, somdd will 
  14019. continue to think that the server program is active, allowing clients to 
  14020. attempt to connect to it, as well as preventing a new copy of that server from 
  14021. being activated. 
  14022.  
  14023. To notify DSOM when the server program is exiting, the deactivate_impl method 
  14024. defined on SOMOA should be called. For example, 
  14025.  
  14026.  /* tell DSOM (via SOMOA) that server is now terminating */
  14027.     _deactivate_impl(SOMD_SOMOAObject, &ev, SOMD_ImplDefObject);
  14028.  
  14029. Note:  For robustness, it would be worthwhile to add appropriate "exit 
  14030.        handlers" or "signal handlers" to your application servers that call the 
  14031.        deactivate_impl method upon abnormal program termination. This ensures 
  14032.        the the DSOM daemon is made aware of the server's termination, so that 
  14033.        client connections are no longer allowed. 
  14034.  
  14035.  Finally, at the end of a server program, the SOMD_Uninit procedure must be 
  14036.  called to free DSOM run-time objects, and to release semaphores, shared memory 
  14037.  segments, and any other system resources. 
  14038.  
  14039.  For example, the exit code in the server program might look like this: 
  14040.  
  14041.       ...
  14042.       SOMD_Uninit(&e);
  14043.       SOM_UninitEnvironment(&e);
  14044.   }
  14045.  
  14046.  Observe also the SOM_UninitEnvironment call, which frees any memory associated 
  14047.  with the specified Environment structure. 
  14048.  
  14049.  When a Windows DSOM server application receives a WM_QUIT message while 
  14050.  processing incoming requests, the execute_request_loop method will return 
  14051.  SOMDERROR_WMQUIT.  When the server receives SOMDERROR_WMQUIT, it should 
  14052.  perform its usual clean up and termination procedures. 
  14053.  
  14054.  
  14055. ΓòÉΓòÉΓòÉ 8.4.6. Managing objects in the server ΓòÉΓòÉΓòÉ
  14056.  
  14057.  
  14058. Object references, ReferenceData, and the ReferenceData table 
  14059.  
  14060. One of SOMOA's responsibilities is to support the creation of object references 
  14061. (SOMDObjects). Recall from the "Stack" example discussion (in Section 6.2) that 
  14062. an object reference  is an exportable "handle" to an object and that proxies 
  14063. are examples of object references. The SOMOA interface supports three 
  14064. operations for creating object references: create, create_constant, and 
  14065. create_SOM_ref. 
  14066.  
  14067. The create and create_constant methods allow a serve to associate 
  14068. application-specific data about an object with an object reference for that 
  14069. object. This data, called reference data, is represented in a sequence of up to 
  14070. 1024 bytes of information about the object. This sequence, defined by the type 
  14071. ReferenceData, may contain the object's location, state, or any other 
  14072. characteristics meaningful to the application. Usually, ReferenceData is used 
  14073. by a server process to locate or activate an object in the server. 
  14074. ReferenceData, and hence the methods create and create_constant are usually 
  14075. only used in connection with persistent objects (objects whose lifetimes exceed 
  14076. that of the process that created them). 
  14077.  
  14078. The create method differs from the create_constant method in the following way: 
  14079. ReferenceData associated with an object reference constructed by 
  14080. create_constant is immutable whereas the the ReferenceData associated with an 
  14081. object reference created by create can be changed (via the change_id method). 
  14082. References created with create_constant return true when the method is_constant 
  14083. is invoked on them. 
  14084.  
  14085. The create method stores the ReferenceData in a ReferenceData table associated 
  14086. with the server, while create_constant maintains the ReferenceData as a 
  14087. constant part of the object reference. The ReferenceData associated with an 
  14088. object reference (whether it was constructed using create or create_constant 
  14089. can be retrieved via the SOMOA method get_id. 
  14090.  
  14091. The IDL SOMOA interface declarations of create, create_constant, get_id, and 
  14092. change_id, and the SOMDObject interface declaration of is_constant are 
  14093. presented below. 
  14094.  
  14095. /* From the SOMOA interface */
  14096.  
  14097.    sequence <octet,1024> Referencedata;
  14098.    SOMDObject create(in ReferenceData id, in InterfaceDef intf,
  14099.                      in ImplementationDef impl);
  14100.  
  14101.    SOMDObject create_constant(in ReferenceData id,
  14102.                               in InterfaceDef intf,
  14103.                               in ImplementationDef impl);
  14104.  
  14105.    ReferenceData get_id(in SOMDObject objref);
  14106.  
  14107.    void change_id(in SOMDObject objref, in ReferenceData id);
  14108.  
  14109. /* From the SOMDObject interface */
  14110.  
  14111.    boolean is_constant();
  14112.  
  14113. An example of how ReferenceData can be used by an application follows the 
  14114. description of SOMDServer objects in the next section 
  14115. Simple SOM object references 
  14116.  
  14117. In order to efficiently support the generation and interpretation of references 
  14118. to SOM objects, the SOMOA defines another method called create_SOM_ref. 
  14119.  
  14120. The create_SOM_ref method creates a simple DSOM reference (SOMDObject) for a 
  14121. local SOM object. The reference is "special" in that, unlike create and 
  14122. create_constant there is no user-supplied ReferenceData associated with the 
  14123. object and because the reference is only valid while the SOM object exists in 
  14124. memory. The SOMObject to which it refers can be retrieved via the 
  14125. get_SOM_object method. The is_SOM_ref method can be used to tell if the 
  14126. reference was created using create_SOM_ref or not. The IDL declarations for 
  14127. create_SOM_ref, get_SOM_object, and is_SOM_ref are displayed below: 
  14128.  
  14129. /* from SOMOA's interface */
  14130.  
  14131.    SOMDObject create_SOM_ref(in SOMObject somobj,
  14132.                              in ImplementationDef impl);
  14133.  
  14134.    SOMObject get_SOM_object(in SOMDObject somref);
  14135.  
  14136. /* from SOMDObject's interface */
  14137.  
  14138.    boolean is_SOM_ref();
  14139.  
  14140. SOMDServer (default server-object class) 
  14141.  
  14142. Every server has a server object that implements three kinds of activities: 
  14143.  
  14144.    o  Creation and destruction of SOM objects 
  14145.  
  14146.    o  Mapping between SOMObjects and SOMDObjects, and 
  14147.  
  14148.    o  Dispatching methods on SOM objects 
  14149.  
  14150.  Additional, application-specific server methods (for initialization, server 
  14151.  control, etc.) can be defined in a subclass of the SOMDServer class. The class 
  14152.  of the server object to be used with a server is contained in the server's 
  14153.  ImplementationDef. 
  14154.  
  14155.  Following are the IDL declarations of the SOMDServer operations: 
  14156.  
  14157.   // methods called by a client
  14158.  
  14159.      SOMObject somdCreateObj(in Identifier objclass, in string hints)
  14160.  
  14161.      void somdDeleteObj(in SOMObject somobj);
  14162.  
  14163.      SOMClass somdGetClassObj(in Identifier objclass);
  14164.  
  14165.   // methods called by SOMOA
  14166.  
  14167.      SOMDObject somdRefFromSOMObj(in SOMObject somobj);
  14168.  
  14169.      SOMObject somdSOMObjFromRef(in SOMDObject objref);
  14170.  
  14171.      void somdDispatchMethod(in SOMObject somobj,
  14172.                              out somToken retValue,
  14173.                              in somId methodId,
  14174.                              in va_list ap);
  14175.  
  14176.  Creation and destruction of SOM objects 
  14177.  
  14178.  The SOMDServer class defines methods for the basic creation of SOM objects in 
  14179.  the server process (somdCreateObj), and for finding the SOM class object for a 
  14180.  specified class (somdGetClassObj). With somdGetClassObj, a client can get a 
  14181.  proxy to a class object on the server, so that methods introduced in the 
  14182.  class's metaclass (for example, class-specific constructors, etc.) may be 
  14183.  invoked directly on the class object. Examples of client use of these two 
  14184.  methods were presented earlier in Sections 6.2 and 6.3. 
  14185.  
  14186.  With somdDeleteObj, the client can involve the server object in object 
  14187.  destruction. (The methods somdTargetFree and somFree are defined on the object 
  14188.  themselves and do not involve the server object.) Involving the server object 
  14189.  in object creation and destruction can be important for applications that need 
  14190.  more control over how objects are created and destroyed, or if the application 
  14191.  needs to keep track of an object's creation and destruction. 
  14192.  Mapping objects to object references 
  14193.  
  14194.  SOMDServer also defines methods that implement mappings between SOMObjects and 
  14195.  SOMDObjects (object references) and a method for dispatching method calls on 
  14196.  SOM objects. These methods are used by the SOM Object Adapter (SOMOA) when 
  14197.  converting remote requests into method calls and results into responses. 
  14198.  
  14199.  Recall from the topic "Proxy objects" in Section 6.3, "Basic Client 
  14200.  Programming", that servers return proxies to remote objects as method results, 
  14201.  not the remote objects themselves. Recall also that class libraries need not 
  14202.  be designed to be distributed (that is, the code that implements the classes 
  14203.  need not be aware of the existence of proxy objects at all). Thus, it is up to 
  14204.  the DSOM run-time environment to ensure that proxies, rather than remote 
  14205.  objects, are returned to clients. The SOMD_SOMOAObject and SOMD_ServerObject 
  14206.  work together to perform this service. Whenever a result from a remote method 
  14207.  call includes a SOMObject, the SOMD_SOMOAObject invokes the somdRefFromSOMObj 
  14208.  method on SOMD_ServerObject, asking it to create a SOMDObject from the 
  14209.  SOMObject. 
  14210.  
  14211.  The default implementation (i.e., SOMDServer's implementation) for 
  14212.  somdRefFromSOMObj uses the create_SOM_ref method to return a "simple" 
  14213.  reference for the SOMObject. Application-specific server objects (instances of 
  14214.  a subclass of SOMDServer) may elect to use create or create_constant to 
  14215.  construct the object reference if the application requires Reference Data to 
  14216.  be stored. 
  14217.  Hints on the use of create vs. create_constant 
  14218.  
  14219.  Enough context now exists so that the following question may be answered: "If 
  14220.  object references constructed with create support changeable ReferenceData, 
  14221.  but object references constructed with create_constant do not, why would I 
  14222.  ever want to use create_constant?" 
  14223.  
  14224.  Invocations of create add entries to a table called the ReferenceData Table. 
  14225.  The ReferenceData Table is persistent; that is, ReferenceData saved in it 
  14226.  persists between server activations. Two calls to create with the same 
  14227.  arguments do not return the same SOMDObject (per CORBA 1.1 specifications) 
  14228.  That is, if create is called twice with the same arguments, two entries in the 
  14229.  ReferenceData Table will be created. If a server using create wishes to avoid 
  14230.  cluttering up the ReferenceData Table with multiple references to the same 
  14231.  object, it must maintain a table of its own to keep track of the references it 
  14232.  has created to avoid calling create twice with the same arguments. 
  14233.  
  14234.  The create_constant method stores the ReferenceData as part of the 
  14235.  SOMDObject's state; that is, it does not add entries to the ReferenceData 
  14236.  Table. The create_constant method, then, might be used by a server that does 
  14237.  not want to maintain a table of references nor pay the penalty of cluttering 
  14238.  up the ReferenceData Table with multiple entries. 
  14239.  Mapping object references to objects 
  14240.  
  14241.  The somdSOMObjFromRef method maps SOMDObjects to SOMObjects. This method is 
  14242.  invoked by  SOMOA on the server object, for each object reference found as a 
  14243.  parameter in a request. 
  14244.  
  14245.  The default implementation for somdSOMObjFromRef returns the address of the 
  14246.  SOMObject for which the specified object reference was create (using the 
  14247.  somdRefFromSOMObj method). If the object reference was not created by the same 
  14248.  server process, then an exception (BadObjref) is raised. The default 
  14249.  implementation does not, however, verify that the original object (for which 
  14250.  the object reference was created) still exists. If the original object has 
  14251.  been deleted (for example, by another client program), then the address 
  14252.  returned will not represent a valid object, and any methods invoked on that 
  14253.  object pointer will result in server failure. Note: The default implementation 
  14254.  of somdSOMObjFromRef does not check that the original object address is still 
  14255.  valid because the check is very expensive and seriously degrades server 
  14256.  performance. 
  14257.  
  14258.  To have a server verify that all results from somdSOMObjFromRef represent 
  14259.  valid objects, server programmers can subclass SOMDServer and override the 
  14260.  somdSOMObjFromRef method to perform a validity check on the result (using the 
  14261.  somIsObj function). For example, a subclass "MySOMDServer" of SOMDServer could 
  14262.  implement the somdSOMObjFromRef method as follows: 
  14263.  
  14264.   SOM_Scope SOMObject SOMLINK somdSOMObjFromRef(MySOMDServer somSelf,
  14265.                                                 Environment * ev,
  14266.                                                 SOMDObject objref)
  14267.   {
  14268.       SOMObject obj;
  14269.       StExcep_INV_OBJREF *ex;
  14270.  
  14271.       /* MySOMDServerData *somThis = MySOMDServerGetData(somSelf); */
  14272.       MySOMDServerMethodDebug("MySOMDServer", "somdSOMObjFromRef");
  14273.  
  14274.       obj = MySOMDServer_parent_SOMDServer_somdSOMObjFromRef(somSelf,
  14275.                                                       ev, objref);
  14276.       if (somIsObj(obj))
  14277.           return (obj);
  14278.       else {
  14279.           ex = (StExcep_INV_OBJREF *)
  14280.                 SOMMalloc(sizeof(StExcep_INV_OBJREF));
  14281.           ex->minor = SOMDERROR_BadObjref;
  14282.           ex->completed = NO;
  14283.           somSetException(ev, USER_EXCEPTION,
  14284.                           ex_StExcep_INV_OBJREF, ex);
  14285.           return (NULL);
  14286.       }
  14287.   }
  14288.  
  14289.  Dispatching a method 
  14290.  
  14291.  After SOMOA (with the help of the local server object) has resolved all the 
  14292.  SOMDObjects present in a request, it is ready to invoke the specified method 
  14293.  on the target. Rather than invoking somDispatch directly  on the target, it 
  14294.  calls the somdDispatchMethod method on the server object. The parameters to 
  14295.  somdDispatchMethod are the same as the parameters for SOMObject::somDispatch 
  14296.  (see the SOMobjects Developer Toolkit: Programmers Reference Manual for a 
  14297.  complete description). 
  14298.  
  14299.  The default implementation for somdDispatchMethod in SOMServer simply invokes 
  14300.  SOMObject::somDispatch on the specified target object with the supplied 
  14301.  arguments. The reason for this indirection through the server object is to 
  14302.  give the server object a chance to intercept method calls coming into the 
  14303.  server process, if desired. 
  14304.  
  14305.  
  14306. ΓòÉΓòÉΓòÉ 8.4.7. Example: Writing a persistent object server ΓòÉΓòÉΓòÉ
  14307.  
  14308. This section shows an example of how to provide a server class implementation 
  14309. for persistent SOM objects. (The Persistence Framework of the full-capability 
  14310. SOMobjects Developer Toolkit can be used to write a persistent object s erver; 
  14311. an example of that type is given in the SOMobjects Developer Toolkit Users 
  14312. Guide.)  All of the persistent object management is contained in the server 
  14313. class; this class can be used with the DSOM "generic" server program, somdsvr. 
  14314.  
  14315. The following example describes a user-supplied server class "MyPServer" that 
  14316. is derived from SOMDServer. The "MyPServer" class introduces five new methods: 
  14317.  
  14318.    o  isPObj 
  14319.    o  assignRefDataToPObj 
  14320.    o  deletePObj 
  14321.    o  getRefDataFromPObj 
  14322.    o  activatePObjFromRefData 
  14323.  
  14324.  and overrides four SOMDServer methods: 
  14325.  
  14326.    o  somdCreateObj 
  14327.    o  somdDeleteObj 
  14328.    o  somdRefFromSOMObj 
  14329.    o  somdSOMObjFromRef. 
  14330.  
  14331.  The example shows how a server class might use and manage Reference Data in 
  14332.  object references to find and activate persistent objects. 
  14333.  
  14334.  The IDL specification for "MyPServer" follows: 
  14335.  
  14336.  
  14337.   interface MyPServer : SOMDServer {
  14338.       boolean isPObj (in SOMObject obj);
  14339.       void assignRefDataToPObj(in SOMObject pobj);
  14340.       void deletePObj(in SOMObject pobj);
  14341.       ReferenceData getRefDataFromPObj(in SOMObject pobj);
  14342.       SOMObject activatePObjFromRefData(in ReferenceData rd);
  14343.     #ifdef __SOMIDL__
  14344.       implementation {
  14345.           somdCreateObj     : override;
  14346.           somdDeleteObj     : override;
  14347.           somdRefFromSOMObj : override;
  14348.           somdSOMObjFromRef : override:
  14349.       };
  14350.     #endif
  14351.   };
  14352.  
  14353.  The "isPObj" method returns TRUE if the object passed to it is a persistent 
  14354.  object. It is implemented as follows: 
  14355.  
  14356.   SOM_Scope boolean SOMLINK
  14357.   isPObj(MyPServer somSelf, Environment *ev, SOMObject obj) {
  14358.       return(obj && _somIsA(obj, MyPersistentObjectNewClass(0, 0));
  14359.   }
  14360.  
  14361.  The following two procedures override SOMDServer's implementations of 
  14362.  somdCreateObj and somdDeleteObj. 
  14363.  
  14364.   SOM_Scope SOMObject SOMLINK
  14365.                 somdCreateObj(MyPServer somSelf, Environment *ev,
  14366.                               Identifier objclass, string hints)
  14367.   {
  14368.      /* create the object as usual */
  14369.      SOMObject obj =
  14370.         parent_somdCreateObj(somSelf, ev, objclass, hints);
  14371.      /* if obj is persistent, assign Ref Data to it */
  14372.      if (_isPObj(somSelf, ev, obj))) {
  14373.         _assignRefDataToPObj(somSelf, ev, obj)
  14374.      }
  14375.      return(obj);
  14376.   }
  14377.  
  14378.  The implementation of somdCreateObj first creates the object as usual by 
  14379.  employing the implementation of SOMDServer  (MyPServer's parent). If the newly 
  14380.  created object is persistent, the job of "assignRefDataToPObj" is to associate 
  14381.  with the object a piece of data that (1) identifies the object, (2) is 
  14382.  retrievable from the object, and (3) can be coerced into ReferenceData so that 
  14383.  it can be used to create a SOMDObject (an object reference). 
  14384.  
  14385.   SOM_Scope void SOMLINK
  14386.       somdDeleteObj(MyPServer somSelf, Environment *ev, SOMObject obj)
  14387.   {
  14388.      /* is obj persistent, have the persistence framework delete it */
  14389.      if (_isPObj(somSelf, ev, obj)) {
  14390.      _deletePObj(somSelf, ev, obj);
  14391.      } else /* obj is not persistent, so delete as usual */
  14392.          parent_somdDeleteObj(somSelf, ev, obj);
  14393.   }
  14394.  
  14395.  The somdDeleteObj implementation, when the object to be deleted is persistent, 
  14396.  invokes "deletePObj" to delete the object. When the object is not persistent, 
  14397.  the SOMDServer implementation of somdDeleteObj deletes the object. 
  14398.  
  14399.  The following two procedures override SOMDServer's implementations of the 
  14400.  methods somdRefFromSOMObj and somdSOMObjFromRef: 
  14401.  
  14402.   SOM_Scope SOMDObject SOMLINK
  14403.                 somdRefFromSOMObj(MyPServer somSelf, Environment *ev,
  14404.                 SOMObject obj)
  14405.   {
  14406.     SOMDObject objref;
  14407.  
  14408.     /* is obj persistent */
  14409.     if (_isPObj(somSelf, ev, obj {
  14410.       /* Create an object reference based on identifying data. */
  14411.       ReferenceData rd = _getRefDataFromPObj(somSelf, ev, obj);
  14412.       InterfaceDef intf =
  14413.          _lookup_id(SOM_InterfaceRepository,ev,somGetClassName(obj));
  14414.       objref = _create_constant(SOMD_SOMOAObject, ev, &rd, intf
  14415.                                  SOMD_ImplDefObject);
  14416.       _somFree(intf);
  14417.       SOMFree(rd._buffer);
  14418.     } else /* obj is not persistent, so get Ref in usual way */
  14419.        objref = parent_somdRefFromSOMObj(somSelf, ev, obj);
  14420.     return(objref);
  14421.   }
  14422.  
  14423.  Method somdRefFromSOMObj is responsible for producing a SOMDObject (the"Ref" 
  14424.  in somdRefFromSOMObj) from a SOMObject. As mentioned earlier, SOMOA exports 
  14425.  two methods for creating SOMDObjects: create and create_constant. This 
  14426.  implementation uses create_constant because it does not want to store the 
  14427.  ReferenceData in the ReferenceData Table. If it did use create and store the 
  14428.  ReferenceData in the persistent table, the server object would either (1) have 
  14429.  to keep a persistent table that maps SOMObjects to SOMDObjects so that it 
  14430.  didn't call create twice with the same arguments (recall that create always 
  14431.  returns a new SOMDObject even when called twice with the same arguments), or 
  14432.  (2) fill up the ReferenceData table with SOMDObjects that contain the same 
  14433.  ReferenceData. 
  14434.  
  14435.  The prerequisites for asking SOMOA to create a SOMDObject are (1) some 
  14436.  ReferenceData to be associated with the SOMDObject, (2) an InterfaceDef that 
  14437.  describes the interface of the  object, and (3) an ImplementationDef that 
  14438.  describes te object's implementation. The InterfaceDef is retrieved from the 
  14439.  SOM Interface Repository using the object's class name as key. The 
  14440.  ImplementationDef is held in the variable SOMD_ImplDefObject that is set when 
  14441.  the server process is initialized. The "MyPServer" method "getRefDataFromPObj" 
  14442.  is used to retrieve the identifying data from the object and coerce it into 
  14443.  ReferenceData. With these three arguments, SOMOA's create_constant is called 
  14444.  to create the SOMDObject. 
  14445.  
  14446.   SOM_Scope SOMObject SOMLINK
  14447.                 somdSOMObjFromRef(MyPServer somSelf, Environment *ev,
  14448.                 SOMDObject objref)
  14449.   {  SOMObject obj;
  14450.  
  14451.      /* test if objref is mine */
  14452.      if (_is_constant(objref, ev)) {
  14453.         /* objref was mine, activate persistent object myself */
  14454.         ReferenceData rd = _get_id(SOMD_SOMOAObject, ev, objref)
  14455.         obj = _activatePObjFromRefData(somSelf, ev, &rd);
  14456.         SOMFree(rd._buffer);
  14457.      } else
  14458.        /* it's not one of mine, let parent activate object */
  14459.        obj = parent_somdSOMObjFromRef(somSelf, ev, objref);
  14460.      return obj;
  14461.   }
  14462.  
  14463.  This implementation of somdSOMObjFromRef is a little different from the others 
  14464.  in that the server object must determine whether the SOMDObject is one that it 
  14465.  created (that is, one that represents a persistent object), or is just a 
  14466.  SOMDObject that was created by the SOMDServer code (its parent). This is done 
  14467.  by asking the SOMDObject if it is a "constant" object reference (that is, one 
  14468.  created by create_constant). If the SOMDObject says that it is a "constant", 
  14469.  then the "MyPServer" may safely assume that the SOMDObject represents a 
  14470.  persisten object that it created. If the SOMDObject is determined to represent 
  14471.  a persistent object, then its  ReferenceData is used to locate/activate the 
  14472.  object it represents (via the method "activatePObjFromRefData"). 
  14473.  
  14474.  
  14475. ΓòÉΓòÉΓòÉ 8.4.8. Identifying the source of a request ΓòÉΓòÉΓòÉ
  14476.  
  14477. CORBA 1.1 specifies that a Basic Object Adapter should provide a facility for 
  14478. identifying the principal (or user) on whose behalf a request is being 
  14479. performed. The get_principal method, defined by BOA and impleented by SOMOA 
  14480. returns a Principal object, which identifies the caller of a particular method. 
  14481. From this information, an application can perform access control checking. 
  14482.  
  14483. In CORBA 1.1, the interface to Principal is not defined, and is left up to the 
  14484. ORB implementation. In the current release of DSOM, a Principal object is 
  14485. defined to have two attributes: 
  14486.  
  14487.  userName (string)  Identifies the name of the user who invoked a request. 
  14488.  
  14489.  hostName (string)  Identifies the name of the host from which the request 
  14490.            originated. 
  14491.  
  14492.  Currently, the value of the UserName attribute is obtained from the USER 
  14493.  environment variable in the calling process. Likewise, the hostName attribute 
  14494.  is obtained from the HOSTNAME environment variable. This facility is intended 
  14495.  to provide basic information about the source of a request, and currently, is 
  14496.  not based on any specific authentication (i.e., "login") scheme. More rigorous 
  14497.  authentication and security mechanisms will be considered for future DSOM 
  14498.  implementations. 
  14499.  
  14500.  The IDL prototype for the get_principal method, defined on BOA (SOMOA) is as 
  14501.  follows: 
  14502.  
  14503.   Principal  get_principal (in SOMDObject obj,
  14504.                              in Environment *req_ev);
  14505.  
  14506.  This call will typically be made either by the target object or by the server 
  14507.  object, when a method call is received. The get_principal method uses the 
  14508.  Environment structure associated with the request, and an object reference for 
  14509.  the target object, to produce a Principal object that define the request 
  14510.  initiator. 
  14511.  
  14512.  Note:  CORBA 1.1 defines a "tk_Principal" TypeCode which is used to identify 
  14513.         the type of Principal object arguments in requests, in case special 
  14514.         handling is needed when building the request. Currently, DSOM does not 
  14515.         provide any special handling of objects of type "tk_Principal"; they 
  14516.         are treated like any other object. 
  14517.  
  14518.  
  14519. ΓòÉΓòÉΓòÉ 8.4.9. Compiling and linking servers ΓòÉΓòÉΓòÉ
  14520.  
  14521. The server program must include the "somd.h" header file. Server programs must 
  14522. link to the SOMobjects Toolkit library: "libsomtk.a" on AIX, and "somtk.lib" or 
  14523. OS/2. 
  14524.  
  14525. For more information, see the topic "Compiling and linking" in Chapter 5, 
  14526. "Implementing Classes in SOM." 
  14527.  
  14528.  
  14529. ΓòÉΓòÉΓòÉ 8.5. Implementing Classes ΓòÉΓòÉΓòÉ
  14530.  
  14531. DSOM has been designed to work with a wide range of object implementations, 
  14532. including SOM class libraries as well as non-SOM object implementations. This 
  14533. section describes the necessary steps in using SOM classes or non-SOM object 
  14534. implementations with DSOM. 
  14535.  
  14536.  
  14537. ΓòÉΓòÉΓòÉ 8.5.1. Using SOM class libraries ΓòÉΓòÉΓòÉ
  14538.  
  14539. It is quite easy to use SOM classes in multi-process DSOM-based applications as 
  14540. exemplified by the sample DSOM application presented in section 6.2, "A Simple 
  14541. DSOM Example". In fact, in many cases, existing SOM class libraries may be used 
  14542. in DSOM applications without requiring any special coding or recoding for 
  14543. distribution. This is possible through the use of DSOM's generic server 
  14544. program, which uses SOM and the SOM Object Adapter (SOMOA) to load SOM class 
  14545. libraries on demand, whenever an object of a particular class is created or 
  14546. activated. 
  14547.  
  14548. The topic "Registering servers and classes" in section 6.6 "Configuring DSOM 
  14549. Applications" discusses how to register a server implementation consisting of a 
  14550. DSOM generic server process and one or more SOM class libraries. 
  14551. Role of DSOM generic server program 
  14552.  
  14553. The generic server program provides basic server functionality: it continuously 
  14554. receives and executes requests (via an invocation of the SOMOA's 
  14555. execute_request_loop method), until the server is stopped. Some requests result 
  14556. in the creation of SOM objects; the generic server program will find and load 
  14557. the DLL for the object's class automatically, if it has not already been 
  14558. loaded. 
  14559.  
  14560. When generic server program functionality is not sufficient for the particular 
  14561. application, application-specific server programs can be developed. For 
  14562. example, some applications may want to interact with a user or I/O device 
  14563. between requests. The previous section, entitled "Basic Server Programming," 
  14564. discussed the steps involved in writing a server program. 
  14565. Role of SOM Object Adapter 
  14566.  
  14567. The SOM Object Adapter is DSOM's standard object adapter. It provides basic 
  14568. support for receiving and dispatching requests on objects. As an added feature, 
  14569. the SOMOA and the server process's server object collaborate t automate the 
  14570. task of converting SOM object pointers into DSOM object references, and vice 
  14571. versa. That is, whenever an object pointer is passed as an argument to a 
  14572. method, the SOMOA and the server object convert the pointer to a DSOM bject 
  14573. reference (since a pointer to an object is meaningless outside the object's 
  14574. address space). 
  14575. Role of SOMDServer 
  14576.  
  14577. The server process's server object (whose default class is SOMDServer) is 
  14578. responsible for creating/destroying objects on the server via somdCreateObj, 
  14579. somdGetClassObj, and somdDeleteObj, for mapping between object references 
  14580. (SOMDObjects) and SOMObjects via somdRefFromSOMObj and somdSOMObjFromRef, and 
  14581. for dispatching remote requests to server process objects via 
  14582. somdDispatchMethod. These last three methods are invoked on the server object 
  14583. by the SOMOA when objects are to be returned to clients, when incoming requests 
  14584. contain object references, and when the method is ready to be dispatched, 
  14585. respectively. By partitioning out these mapping and dispatching functions into 
  14586. the server object, the application can more easily customize them, without 
  14587. having to build object adapter subclasses. 
  14588.  
  14589. SOMDServer can be subclassed by applications that want to manage object 
  14590. location, object activation, and method dispatching. An example of such an 
  14591. application (which provides a server class implementation for persistent SOM 
  14592. objects) is shown in section 6.4, "Basic Server Programming." 
  14593.  
  14594. These features of SOMOA and SOMDServer make it possible to take existing OM 
  14595. classes, which have been written for a single-address space environment, and 
  14596. use them unchanged in a DSOM application. More information on the SOMOA and 
  14597. server objects can be found in the "Basic Server Programming" section. 
  14598. Implementation constraints 
  14599.  
  14600. The generic server program (somdsvr), the SOMOA, and the SOMDServer make it 
  14601. easy to use SOM classes with DSOM. However, if there are any parts of the class 
  14602. implementation that were written expecting a single-process environment, the 
  14603. class may have to be modified to behave properly in a client/server 
  14604. environment. Some common implementation practices to avoid are listed below 
  14605.  
  14606.    o  Printing to standard output. Any text printed by a method will appear at 
  14607.       the server, as opposed to the client. In fact, the server may not be 
  14608.       attached to a text display device or window, so the text may be lost 
  14609.       completely. It is preferred that any textual output generated by a method 
  14610.       be returned as an output string. 
  14611.  
  14612.       Note:  Passing textual output between the client program and the called 
  14613.              method via an "inout string" parameter is strongly discouraged. As 
  14614.              discussed in the CORBA 1.1 specification (page 94), the size of 
  14615.              the output string is constrained by the size of the input string. 
  14616.              If there was no input string value, the size of the output string 
  14617.              would be constrained to 0 bytes. Instead, it is preferred that 
  14618.              textual data be returned either as an output string (DSOM provides 
  14619.              the storage), or by passing a character array buffer (client 
  14620.              provides the storage). 
  14621.  
  14622.    o  Creating and deleting objects. Methods that create or delete objects may 
  14623.       have to be modified if the created objects are intended to be remote. The 
  14624.       calls to create local objects are different than the calls to create 
  14625.       remote objects. 
  14626.  
  14627.    o  Using pointers to client-allocated memory in instance variables. Consider 
  14628.       the following example: A class has a method that accepts a pointer to a 
  14629.       data value created by the client (e.g., a string or a struct), and simply 
  14630.       stores the pointer in an instance variable or attribute. However, in 
  14631.       DSOM, the called method is passed a pointer to a copy of the value (in 
  14632.       the request message body), but the copy is freed at the end of the 
  14633.       request. If the data value is meant to persist between requests, the 
  14634.       object is responsible for making its own copy of it. (The implementation 
  14635.       of the "_set_printerName" method in the topic "Wrapping a printer API" 
  14636.       later in this section is an example of a method performing such a copy.) 
  14637.  
  14638.    o  Using "procedure" methods. Methods having the procedure SOM IDL modifier 
  14639.       cannot be invoked remotely using DSOM.  This is because these "methods" 
  14640.       are called directly, rather than by the normal method resolution 
  14641.       mechanisms on which DSOM relies. 
  14642.  
  14643.  In addition to those coding practices which simply do not "port" to a 
  14644.  distributed environment, there are a few other restrictions that are imposed 
  14645.  by DSOM's (current) implementation. 
  14646.  
  14647.    o  Using parameter types not supported by DSOM. DSOM can make remote 
  14648.       invocations only of methods whose parameter types are among the following 
  14649.       IDL types:  basic types short, long, unsigned short, unsigned long,float, 
  14650.       double, char, boolean, octet), enum struct, union, sequence, string, 
  14651.       array, any, and object (an interface name, designating a pointer to an 
  14652.       object that supports that interface).  The members of a struct, union, 
  14653.       sequence, or array, and the value of any any, must also be from the above 
  14654.       list of supported DSOM types. 
  14655.  
  14656.       In addition to the above types, DSOM also supports method parameters of 
  14657.       type pointer to one of the above types (for example,  long*).  Pointers 
  14658.       to pointers are not supported, however, and pointers embedded within one 
  14659.       of the above types (for example, a pointer within a struct) are not 
  14660.       supported.  The "void*" type is also not supported.  Currently, DSOM has 
  14661.       the limitation that NULL pointer values cannot be returned as inout or 
  14662.       out method arguments, although it is expected that this limitation will 
  14663.       be addressed in the future release. 
  14664.  
  14665.       Types declared as SOMFOREIGN types are not currently supported by DSOM. 
  14666.  
  14667.    o  Packing of structures used as method arguments. If a compiler option is 
  14668.       used to pack or optimize storage of structs (including reordering of 
  14669.       struct members) or unions, it is important to indicate the exact 
  14670.       alignment of the structures using alignment modifiers expressed in the 
  14671.       implementation section of the IDL file. This information must then be 
  14672.       updated in the Interface Repository. 
  14673.  
  14674.  Some applications may need to associate specific identification information 
  14675.  with an object, to support application-specific object location or activation. 
  14676.  In that case, an application server should create object references 
  14677.  explicitly, using the create or create_constant method in SOMOA. A logical 
  14678.  place to put these calls is in a subclass of SOMDServer, as it is the server 
  14679.  object that is responsible for producing/activating objects from object 
  14680.  references. 
  14681.  
  14682.  
  14683. ΓòÉΓòÉΓòÉ 8.5.2. Using other object implementations ΓòÉΓòÉΓòÉ
  14684.  
  14685. As an Object Request Broker, DSOM must support a wide range of object 
  14686. implementations, including non-SOM implementations. For example, in a print 
  14687. spooler application, the implementation of a print queue object may be provided 
  14688. by the operating system, where the methods on the print queue are executable 
  14689. programs or system commands. As another example, consider an application that 
  14690. uses a large, existing class library that is not implemented using SOM. 
  14691. Finally, consider a class library where persistence is implemented by something 
  14692. other than the Persistence Framework. 
  14693.  
  14694. In each of these examples, the application must participate  in object 
  14695. identification, activation, initialization, and request dispatching. Each 
  14696. server supplies a server object (derived from SOMDServer) that works in 
  14697. conjunction with the SOMOA for this purpose. 
  14698. Wrapping a printer API 
  14699.  
  14700. Presented below is a simple example showing how an existing API could be 
  14701. "wrapped" as SOM objects. The API is admittedly trivial, but it is hoped that 
  14702. readers understand this simple example well enough to create more sophisticated 
  14703. applications of their own. 
  14704.  
  14705. The "API" wrapped in this example is comprised of two OS/2 system calls. The 
  14706. first one asks for a file to be printed on a specific printer: 
  14707.  
  14708. print /D:<printerName> <filename>
  14709.  
  14710. The second one asks for the file currently being printed on device 
  14711. <printerName> to be cancelled. 
  14712.  
  14713. print /D:<printerName> /C
  14714.  
  14715. Two IDL interfaces are declared in the module "PrinterModule": "Printer" and 
  14716. "PrinterServer". The "Printer" interface wraps the two system calls. The 
  14717. "PrinterServer" interface describes a subclass of SOMDServer. 
  14718. "PrinterModule::PrinterServer" will be the class of the server object in the 
  14719. print-server application. 
  14720.  
  14721. #include <somdserv.idl>
  14722.  
  14723. module PrinterModule {
  14724.   interface Printer : SOMObject {
  14725.     attribute string printerName;
  14726.     void print(in string fname);
  14727.     void cancel();
  14728.     #ifdef __SOMIDL__
  14729.     implementation {
  14730.       printerName: noset;
  14731.       };
  14732.     #endif
  14733.   };
  14734.  
  14735.   interface PrinterServer :SOMDServer{
  14736.     #ifdef __SOMIDL__
  14737.     implementation {
  14738.       somdCreateObj: override;
  14739.       somdRefFromSOMObj: override;
  14740.       somdSOMObjFromRef: override;
  14741.       };
  14742.     #endif
  14743.   };
  14744.  
  14745. };
  14746.  
  14747. Note that the "Printer" interface defines one attribute, "printerName", that 
  14748. will be used to identify the printer. It will be set when a "Printer" is 
  14749. created. Printer's two operations, "print" and "cancel", correspond to the two 
  14750. system commands the interface is encapsulating. The "PrinterServer" interface 
  14751. does not introduce any new attributes or operations. It does specify that three 
  14752. of SOMDServer's methods will have their implementations overridden The three 
  14753. method procedures below show how the "Printer" interface is implemented for the 
  14754. "_set_printerName", "print", and "cancel" methods. 
  14755.  
  14756. SOM_Scope void  SOMLINK PrinterModule_Printer_set_printerName(
  14757.  PrinterModule_Printer somSelf, Environment *ev, string printerName)
  14758. {
  14759.     PrinterModule_PrinterData *somThis =
  14760.       PrinterModule_PrinterGetData(somSelf);
  14761.  
  14762.     if (_printerName) SOMFree(_printerName);
  14763.     _printerName = (string)SOMMalloc(strlen(printerName) + 1);
  14764.     strcpy(_printerName, printerName);
  14765. }
  14766.  
  14767.  
  14768. SOM_Scope void  SOMLINK PrinterModule_Printerprint(
  14769.  PrinterModule_Printer somSelf, Environment *ev, string fname)
  14770. {
  14771.     long rc;
  14772.     PrinterModule_PrinterData *somThis =
  14773.       PrinterModule_PrinterGetData(somSelf);
  14774.     string printCommand = (string)
  14775.       SOMMalloc(strlen(_printerName) + strlen(fname) + 10 + 1);
  14776.  
  14777.     sprintf(printCommand,"print /D:%s %s",_printerName,fname);
  14778.     rc = system(printCommand);
  14779.     if (rc) raiseException(ev,rc);
  14780. }
  14781.  
  14782.  
  14783. SOM_Scope void  SOMLINK PrinterModule_Printercancel(
  14784.  PrinterModule_Printer somSelf, Environment *ev)
  14785. {
  14786.     long rc;
  14787.     PrinterModule_PrinterData *somThis =
  14788.       PrinterModule_PrinterGetData(somSelf);
  14789.     string printCommand =
  14790.       (string) SOMMalloc(strlen(_printerName) + 12 + 1);
  14791.  
  14792.     sprintf(printCommand,"print /D:%s /C",_printerName);
  14793.     rc = system(printCommand);
  14794.     if (rc) raiseExeception(ev,rc);
  14795. }
  14796.  
  14797. Note:  The implementation of the "raiseException" procedure shown in the 
  14798.        example above must be provided by the application. However, it is not 
  14799.        shown in this example. 
  14800.  
  14801.  The three method procedures that implement the "PrinterServer" interface's 
  14802.  three overridden methods of SOMServer are very similar to the method 
  14803.  procedures of the "MyPServer" server-object class presented in the previous 
  14804.  section (6.4), and therefore have not been shown here. 
  14805.  
  14806.  
  14807. ΓòÉΓòÉΓòÉ 8.5.3. Parameter memory management ΓòÉΓòÉΓòÉ
  14808.  
  14809. There are five SOM IDL modifiers available for specifying the memory-management 
  14810. policy for the parameters of a method (regardless of whether the caller or the 
  14811. object owns the parameters' memory after the method is invoked). These 
  14812. modifiers are: 
  14813.  
  14814.   memory_management,  caller_owns_result,  caller_owns_parameters, 
  14815. object_owns_result, and  object_owns_parameters. 
  14816.  
  14817. See the section entitled "Implementation Statements" in Chapter 4, "SOM IDL and 
  14818. the SOM Compiler," for a complete description of these modifiers and their 
  14819. meanings. Note that the memory-management policy for a particular parameter 
  14820. applies to the parameter and all the memory embedded within it (for example, if 
  14821. a struct is owned by the caller, then so are all the struct's members). 
  14822.  
  14823. When a class contains the memory_management = corba SOM IDL modifier, this 
  14824. signifies that all methods introduced by the class follow the CORBA 
  14825. specification for parameter memory management, except where a particular method 
  14826. has an explicit modifier  (object_owns_result or object_owns_parameters) that 
  14827. indicates otherwise. For a description of the CORBA specification, see the 
  14828. earlier subtopic entitled "The CORBA policy for parameter memory management" 
  14829. (under the topic "Memory Management" in Section 6.3 of this chapter). 
  14830.  
  14831.  
  14832. ΓòÉΓòÉΓòÉ 8.5.4. Building and registering class libraries ΓòÉΓòÉΓòÉ
  14833.  
  14834. The generic server uses SOM's run-time facilities to load class libraries 
  14835. dynamically. Thus, dynamically linked libraries (DLLs) should be created for 
  14836. the classes, just as they would be for non-distributed SOM-based applications. 
  14837. For more information, see the topic Creating a SOM class library in Chapter 5 
  14838. "Implementing classes in SOM." 
  14839.  
  14840. During the development of the DLL, it is important to remember the following 
  14841. steps: 
  14842.  
  14843.    o  Export a routine called SOMInitModule in the DLL, which will be called by 
  14844.       SOM to initialize the class objects implemented in that library. 
  14845.       SOMInitModule should contain a <className>NewClass call for each class in 
  14846.       the DLL. 
  14847.  
  14848.    o  For each class in the DLL, specify the DLL name in the class's IDL file. 
  14849.       The DLL name is specified using the dllname=<name> modifier in the 
  14850.       implementation statement of the interface definition. If not specified, 
  14851.       the DLL filename is assumed to be the same as the class name. 
  14852.  
  14853.    o  For each class in the DLL, compile the IDL description of the class into 
  14854.       the Interface Repository. This is accomplished by invoking the following 
  14855.       command syntax: 
  14856.  
  14857.  
  14858.                     sc -sir -u stack.idl       (On AIX or OS/2)
  14859.  
  14860.       Note:  If the classes are not compiled into the Interface Repository, 
  14861.              DSOM will generate a run-time error (30056: 
  14862.              SOMDERROR_BadDescriptor) when an attempt is made to lookup the 
  14863.              signature of a method in the class (for example, on a method 
  14864.              call). 
  14865.  
  14866.    o  Put the DLL in one of the directories listed in LIBPATH for AIX or OS/2, 
  14867.       or listed in PATH for Windows.  This is necessary for both OS/2, AIX, and 
  14868.       Windows.) 
  14869.  
  14870.  
  14871. ΓòÉΓòÉΓòÉ 8.6. Configuring DSOM Applications ΓòÉΓòÉΓòÉ
  14872.  
  14873.  
  14874. ΓòÉΓòÉΓòÉ 8.6.1. Preparing the environment ΓòÉΓòÉΓòÉ
  14875.  
  14876. Some environment variables must be defined before running DSOM. Unless noted, 
  14877. these environment variables are required in both the AIX and OS/2 environments. 
  14878.  
  14879.  HOSTNAME=<name>                   Each machine that is running DSOM must have 
  14880.                                    its HOSTNAME variable set. 
  14881.  
  14882.  USER=<name>                       USER specifies the name of the DSOM user 
  14883.                                    running a client program. 
  14884.  
  14885.  SOMIR=<file(s)>                   SOMIR specifies a list of files (separated 
  14886.                                    by a colon on AIX and a semicolon on OS/2) 
  14887.                                    which together make up the Interface 
  14888.                                    Repository. See Chapter 7, "The Interface 
  14889.                                    Repository Framework," for more information 
  14890.                                    on how to set this variable. 
  14891.  
  14892.                                    Note:  For DSOM, it is preferable to use 
  14893.                                           full pathnames in the list of IR 
  14894.                                           files, since the IR will be shared by 
  14895.                                           several programs that may not all be 
  14896.                                           started in the same directory. 
  14897.  
  14898.  SOMSOCKETS=<name>                 SOMSOCKETS specifies the name of the SOM 
  14899.                                    Sockets subclass that implements the sockets 
  14900.                                    services. 
  14901.  
  14902.                                    Note:  For Workstation DSOM, this variable 
  14903.                                           is effectively ignored. (However, it 
  14904.                                           may be used by the Event Management 
  14905.                                           Framework.) 
  14906.  
  14907.  SOMDDIR=<directory>               SOMDDIR specifies the directory where 
  14908.                                    various DSOM files should be located, 
  14909.                                    including the Implementation Repository 
  14910.                                    files. See the later section in this chapter 
  14911.                                    entitled "Registering servers and classes" 
  14912.                                    for more information. 
  14913.  
  14914.                                    Note:  If this value is not set, DSOM will 
  14915.                                           attempt to use a default directory: 
  14916.                                           $SOMBASE/etc/dsom on AIX, and 
  14917.                                           %SOMBASE%\ETC\DSOM on OS/2. 
  14918.  
  14919.  SOMDPORT=<integer>                In DSOM, servers, clients and DSOM daemons 
  14920.                                    communicate with each other using a 
  14921.                                    "sockets" abstraction. In particular DSOM 
  14922.                                    clients establish connections to DSOM 
  14923.                                    servers by communicating with the DSOM 
  14924.                                    daemon, somdd, running on each server 
  14925.                                    machine. The daemon is designed to listen 
  14926.                                    for client requests on a well-known port. 
  14927.  
  14928.                                    Normally, somdd will look in the 
  14929.                                    /etc/services (for AIX) or %ETC%\SERVICES 
  14930.                                    (for OS/2) file for its well-known port 
  14931.                                    number. However, if the user has set the 
  14932.                                    SOMDPORT environment variable, the value of 
  14933.                                    SOMDPORT will be used and the "services" 
  14934.                                    file will not be consulted. The user should 
  14935.                                    pick a 16-bit integer that is not likely to 
  14936.                                    be in use by another application (check the 
  14937.                                    "services" file for ports reserved for use 
  14938.                                    on your machine). Typically, values below 
  14939.                                    1024 are reserved and should not  be used. 
  14940.  
  14941.                                    Note:  If there is no "services" file and 
  14942.                                           the SOMDPORT environment variable is 
  14943.                                           not set, DSOM will use a default port 
  14944.                                           number (currently 9393). 
  14945.  
  14946.  SOMDTIMEOUT=<integer>             SOMDTIMEOUT specifies how long a receiver 
  14947.                                    should wait for a message, or how long a 
  14948.                                    sender should wait for an acknowledgement. 
  14949.                                    The value should be expressed in seconds. 
  14950.                                    The default value is 600 seconds (10 
  14951.                                    minutes). 
  14952.  
  14953.  SOMDDEBUG=<integer>               SOMDDEBUG may optionally be set to enable 
  14954.                                    DSOM run-time error messages. If set to 0, 
  14955.                                    error reporting is disabled. If set to 1, 
  14956.                                    error reporting is enabled. Error reports 
  14957.                                    may be directed to the file named by 
  14958.                                    SOMDMESSAGELOG, if set. 
  14959.  
  14960.  SOMDMESSAGELOG=<file>             SOMDMESSAGELOG may optionally be set to the 
  14961.                                    name of a file where DSOM run-time error 
  14962.                                    messages are recorded. If not set, error 
  14963.                                    messages will be reported on the standard 
  14964.                                    output device. 
  14965.  
  14966.  SOMDNUMTHREADS=<integer>          SOMDNUMTHREADS may optionally be set to the 
  14967.                                    maximum number of requests threads created 
  14968.                                    per server.  If SOMDNUMTHREADS is not set, 
  14969.                                    then a separate thread will be created for 
  14970.                                    each request (when using somdsvr on OS/2 as 
  14971.                                    multi-threaded server). 
  14972.  
  14973.  
  14974. ΓòÉΓòÉΓòÉ 8.6.2. Registering class interfaces ΓòÉΓòÉΓòÉ
  14975.  
  14976. DSOM relies heavily on the Interface Repository for information on method 
  14977. signatures (that is, a description of the method's parameters and return 
  14978. value). It is important to compile the IDL for all application classes into the 
  14979. IR before running the application. 
  14980.  
  14981. For each class in the DLL, compile the IDL description of the class into the 
  14982. Interface Repository. This is accomplished by invoking the following command 
  14983. syntax: 
  14984.  
  14985.     sc -sir -u stack.idl     (on AIX or OS/2)
  14986.  
  14987. If the default SOM IR (supplied with the SOMobjects Toolkit and Run times) is 
  14988. not used by the application, the user's IR must include the interface 
  14989. definitions for: 
  14990.  
  14991.    o  the appropriate Sockets class (if the SOMSOCKETS environment variable is 
  14992.       set), 
  14993.  
  14994.    o  the server class (derived from SOMDServer), and 
  14995.  
  14996.    o  the definitions of the standard DSOM exceptions (found in file 
  14997.       "stexcep.idl") that may be returned by a method call. 
  14998.  
  14999.  
  15000. ΓòÉΓòÉΓòÉ 8.6.3. Registering servers and classes ΓòÉΓòÉΓòÉ
  15001.  
  15002.  
  15003. Implementation definitions 
  15004.  
  15005. The Implementation Repository holds ImplementationDef objects The 
  15006. ImplementationDef class defines attributes necessary for the SOMOA to find and 
  15007. activate the implementation of an object. Details of the ImplementationDef 
  15008. object are not currently defined in the CORBA 1.1 specification; the attributes 
  15009. that have been defined are required by DSOM. 
  15010.  
  15011. Listed below is each available attribute, with its corresponding type in 
  15012. parentheses, followed by a description of its purpose: 
  15013.  
  15014.  impl_id (string)              Contains the DSOM-generated identifier for a 
  15015.                                server implementation. 
  15016.  
  15017.  impl_alias (string)           Contains the "alias" (user-friendly name) for a 
  15018.                                server implementation. 
  15019.  
  15020.  impl_program (string)         Contains the name of the program or command file 
  15021.                                which will be executed when a process for this 
  15022.                                server is started automatically by somdd. If the 
  15023.                                full pathname is not specified, the directories 
  15024.                                specified in the  PATH environment variable will 
  15025.                                be searched for the named program or command 
  15026.                                file. 
  15027.  
  15028.                                Optionally, the server program can be run under 
  15029.                                control of a "shell" or debugger, by specifying 
  15030.                                the shell or debugger name first, followed by 
  15031.                                the name of the server program. (A space 
  15032.                                separates the two program names.)  For example, 
  15033.  
  15034.                                                                               dbx myprogram
  15035.  
  15036.                                will start the program "myprogram" under control 
  15037.                                of "dbx". 
  15038.  
  15039.                                Servers that are started automatically by somdd 
  15040.                                will always be passed their impl_id as the first 
  15041.                                parameter, in order to retrieve their 
  15042.                                ImplementationDef (if desired). 
  15043.  
  15044.  impl_flags (Flags)            Contains a bit-vector of flags used to identify 
  15045.                                server options (for example, the 
  15046.                                IMPLDEF_MULTI_THREAD flag indicates 
  15047.                                multi-threading). 
  15048.  
  15049.  impl_server_class (string)    Contains the name of the SOMDServer class or 
  15050.                                subclass created by the server process. 
  15051.  
  15052.  impl_refdata_file (string)    Contains the full pathname of the file used to 
  15053.                                store ReferenceData for the server. 
  15054.  
  15055.  impl_refdata_bkup (string)    Contains the full pathname of the backup mirror 
  15056.                                file used to store ReferenceData for the server. 
  15057.                                This file can be used to restore a copy of the 
  15058.                                primary file in case it becomes corrupted. (It 
  15059.                                would be a good idea to keep the primary and 
  15060.                                backup files in different disk volumes.) 
  15061.  
  15062.  impl_hostname (string)        Contains the hostname of the machine where the 
  15063.                                server is located. 
  15064.  
  15065.  
  15066. ΓòÉΓòÉΓòÉ 8.6.4. The `regimpl' `pregimpl,' `wregimpl' registration utilities ΓòÉΓòÉΓòÉ
  15067.  
  15068. Before an implementation (a server program and class libraries) can be used by 
  15069. client applications, it must be registered with DSOM by running the 
  15070. implementation registration utility, regimpl (on AIX), pregimpl (on OS/2) or 
  15071. wregimpl (on Windows).  The  regimpl  utility can also be executed from the DOS 
  15072. command line;  this facility is available primarily for use in batch files. 
  15073. During execution of regimpl, pregimpl, or wregimpl, DSOM updates it database to 
  15074. include the new server implementation and the associated classes. This enables 
  15075. DSOM to find and, if necessary, to activate the server so that clients can 
  15076. invoke methods on it. 
  15077.  
  15078. Typically, DSOM users employ the generic SOM-object server program, described 
  15079. below. A discussion on how to write a specific (non-generic) server program is 
  15080. found in the earlier section, "Basic Server Programming." 
  15081. Registration steps Using `regimpl' 
  15082.  
  15083. Registering a server implementation and its classes requires the steps 
  15084. described in the following paragraphs. 
  15085.  
  15086. First, make sure the SOMDDIR environment variable is defined to the name of the 
  15087. Implementation Repository directory, as discussed in the section "Preparing the 
  15088. Environment." 
  15089.  
  15090. Then, to run the regimpl utility, at the system prompt enter: 
  15091.  
  15092. > regimpl 
  15093.  
  15094. This brings up the DSOM Implementation Registration Utility menu, shown below. 
  15095. To begin registering the new implementation, select "1.Add" from the 
  15096. IMPLEMENTATION OPERATIONS section; that is, at the "Enter operation:" prompt, 
  15097. enter "1" (as shown in bold): 
  15098.  
  15099. DSOM IMPLEMENTATION REGISTRATION UTILITY
  15100. (C) Copyright IBM Corp. 1992,1993.  All rights reserved.
  15101.  
  15102. Implementation data being loaded from: /u/xyz/dsomRepos/
  15103.  
  15104. [ IMPLEMENTATION OPERATIONS ]
  15105.  1.Add  2.Delete  3.Change
  15106.  4.Show one  5.Show all  6.List aliases
  15107. [ CLASS OPERATIONS ]
  15108.  7.Add  8.Delete  9.Delete from all  10.List classes
  15109. [ SAVE & EXIT OPERATIONS ]
  15110.  11.Save data  12.Exit
  15111. Enter operation: 1
  15112.  
  15113. The regimpl utility then issues several prompts for information about the 
  15114. server implementation (typical responses are shown in bold as an example). 
  15115.  
  15116. Implementation alias.  Enter a "shorthand" name for conveniently referencing 
  15117. the registered server implementation while using regimpl: 
  15118.  
  15119. Enter an alias for new implementation:  myServer
  15120.  
  15121. Program name.  Enter the name of the program that will execute as the server. 
  15122. This may be the name of one of the DSOM generic servers (discussed under the 
  15123. later topic "Running DSOM Servers") or a user-defined name for one of these 
  15124. servers. If the program is located in PATH, only the program name needs to be 
  15125. specified. Otherwise, the pathname must be specified. 
  15126.  
  15127. Enter server program name:(default: somdsvr)  <return>
  15128.  
  15129. Multi-threading.  Specify whether or not the server expects the SOM Object 
  15130. Adapter (SOMOA) to run each method in a separate thread or not. Notes: This 
  15131. option is only meaningful on OS/2. It is the responsibility of the class 
  15132. implementer to ensure that the methods being executed by the server are "thread 
  15133. safe". 
  15134.  
  15135. Allow multiple threads in the server? [y/n]
  15136. (default: n) : n
  15137.  
  15138. Server class.  Enter the name of the SOMDServer class or subclass that will 
  15139. manage the objects in the server. 
  15140.  
  15141. Enter server class (default: SOMDServer) : <return>
  15142.  
  15143. Reference data file name.  Enter the full pathname of the file used to store 
  15144. ReferenceData associated with object references created by this server. Note: A 
  15145. file name is required only  if the server is using the create method to 
  15146. generate object references. 
  15147.  
  15148. Enter object reference file name (optional) :  <return>
  15149. Backup reference data file name.  Enter the full pathname of the backup file 
  15150. used to mirror the primary ReferenceData file for this server. Note: a file 
  15151. name is required only if (1) a primary reference data file has been specified, 
  15152. and (2) the application desires an online backup to be maintained. This file 
  15153. can be used to restore a copy of the primary file should it become corrupted. 
  15154.  
  15155. Enter object reference backup file name (optional) : <return>
  15156.  
  15157. Host machine name.  This is the name of the machine on which the server program 
  15158. code is stored. The same name should be indicated in the HOSTNAME environment 
  15159. variable. (If "localhost" is entered, the contents of the HOSTNAME environment 
  15160. variable will be used. 
  15161.  
  15162. Enter host machine name:(default: localhost)  <return>
  15163.  
  15164. The regimpl system next displays a summary of the information defined thus far, 
  15165. and asks for confirmation before adding it. Enter "y" to save the 
  15166. implementation information in the Implementation Repository. 
  15167.  
  15168.  
  15169. ================================================================
  15170. Implementation id.........: 2befc82b-13a11e00-7f-00-10005ac9272a
  15171. Implementation alias......: myServer
  15172. Program name..............: somdsvr
  15173. Multithreaded.............: No
  15174. Server class..............:SOMDServer
  15175. Object reference file.....:
  15176. Object reference backup...:
  15177. Host Name.................: localhost
  15178.  
  15179. The above implementation is about to be added. Add? [y/n] y
  15180. Implementation 'myServer' successfully added
  15181. Add class.  Once the server implementation is added, the complete menu 
  15182. reappears. The next series of prompts and entries will identify the classes 
  15183. associated with this server. To begin, from the CLASS OPERATIONS section, 
  15184. select "7.Add": 
  15185.  
  15186.  
  15187. [ IMPLEMENTATION OPERATIONS ]
  15188.  1.Add  2.Delete  3.Change
  15189.  4.Show one  5.Show all  6.List aliases
  15190. [ CLASS OPERATIONS ]
  15191.  7.Add  8.Delete  9.Delete from all  10.List classes
  15192. [ SAVE & EXIT OPERATIONS ]
  15193.  11.Save data  12.Exit
  15194.  
  15195. Enter operation: 7
  15196. Class name.  Enter the name of a class associated with the implementation 
  15197. alias. 
  15198.  
  15199. Enter name of class:  class1
  15200.  
  15201. Implementation alias.  Enter the alias for the server that implements the new 
  15202. class (this should be the same alias as given above). 
  15203.  
  15204. Enter alias of implementation that implements class:  myServer
  15205.  
  15206. Class 'class1' now associated with implementation 'myServer'
  15207.  
  15208. The top-level menu will then reappear. Repeat the previous three steps until 
  15209. all classes have been associated with the server. 
  15210.  
  15211. Then, from the SAVE & EXIT OPERATIONS section, select "11.Save data" to 
  15212. complete the registration. Finally, select "12.Exit" to exit the regimpl 
  15213. utility. 
  15214.  
  15215. [ IMPLEMENTATION OPERATIONS ]
  15216.  1.Add  2.Delete  3.Change
  15217.  4.Show one  5.Show all  6.List aliases
  15218. [ CLASS OPERATIONS ]
  15219.  7.Add  8.Delete  9.Delete from all  10.List classes
  15220. [ SAVE & EXIT OPERATIONS ]
  15221.  11.Save data  12.Exit
  15222.  
  15223. Enter operation:  11
  15224.  
  15225. Enter operation:  12
  15226.  
  15227. Command line interface to `regimpl' 
  15228.  
  15229. The regimpl utility also has a command line interface. The command flags 
  15230. correspond to the interactive commands described above. The syntax of the 
  15231. regimpl commands follow. 
  15232.  
  15233. Note:  The regimpl command and any optional regimpl command flags can be 
  15234.        entered at a system prompt, and the command will execute as described 
  15235.        below.  For OS/2 and Windows users, this et-based interface is 
  15236.        particularly useful in batch files.
  15237.  
  15238.  To enter interactive mode: 
  15239.  
  15240.     regimpl
  15241.  
  15242.  To add an implementation: 
  15243.  
  15244.     regimpl -A -i <str> [-p <str>] [-v <str>][-f <str>] [-b <st>]
  15245.                           [-h <str>] [-m {on|off}] [-z tr>]
  15246.  
  15247.  To update an implementation: 
  15248.  
  15249.     regimpl -U -i <str> [-p <str>] [-v<str>]&l    brk.-f <str>  [-b <str>]
  15250.                            [-h <str>] [-m {on|off}]
  15251.  
  15252.  To delete one or more implementations: 
  15253.  
  15254.     regimpl -D -i <str> [-i ...]
  15255.  
  15256.  To list all, or selected, implementations: 
  15257.  
  15258.     regimpl -L  [-i <str> [-i ...]]
  15259.  
  15260.  To list all implementation aliases: 
  15261.  
  15262.     regimpl -S
  15263.  
  15264.  To add class associations to one or more implementations: 
  15265.  
  15266.    regimpl -a -c <str> [-c ...] -i <str> [-i ...]
  15267.  
  15268.  To delete class associations from all, or selected, implementations: 
  15269.  
  15270.    regimpl -d -c <str> [-c ...][-i <str> [-...]]
  15271.  
  15272.  To list classes associated with all, or selected, implementation: 
  15273.  
  15274.     regimpl -l [-i <str> [-i ...]]
  15275.  
  15276.  The following parameters are used in the commands described above: 
  15277.  
  15278.  
  15279.   -i <str>    = Implementation alias name(maximum of 16 -i names)
  15280.   -p <str>    = Server program name  (default: somdsvr)
  15281.   -v <str>    = Server-class name  (default: SOMDServer)
  15282.   -f <str>    = Reference data file name  (optional)
  15283.   -b <str>    = Reference data backup file name  (optional)
  15284.   -h <str>    = Host machine name  (default: localhost)
  15285.   -m {on|off} = Enable multi-threaded server  (optional)
  15286.   -z <str>    = Implementation ID
  15287.   -c <str>    = Class name(maximum of 16 -c names)
  15288.  
  15289.  Registration steps using `pregimpl' or `wregimpl' 
  15290.  
  15291.  The pregimpl utility is a Presentation Manager version of regimpl, the DSOM 
  15292.  implementation definition utility. Similarly, the wregimpl utility is a 
  15293.  Windows version of regimpl. The pregimpl and wregimpl utilities offer all the 
  15294.  functionality of regimpl except its command-line arguments (described earlier 
  15295.  in "Command line interface to `regimpl'"). In addition, the pregimpl and 
  15296.  wregimpl utilities provide an intuitive GUI interface in place of regimpl's 
  15297.  text-based interface. Before proceeding, you should first familiarize yourself 
  15298.  with the basic registration process described earlier in "Registration steps 
  15299.  using `regimpl'." 
  15300.  
  15301.  Note: OS/2 or Windows users can execute the text-interface regimpl utility by 
  15302.  entering "regimpl" at a system prompt, as described in the previous topic, 
  15303.  "Command line interface to `regimpl'." This facility is available primarily 
  15304.  for use in batch files. 
  15305.  
  15306.  You can start the pregimpl or wregimpl utility conveniently in either of two 
  15307.  ways: 
  15308.  
  15309.    o  From the Register Impls icon in the SOMobjects icon group, or 
  15310.  
  15311.    o  From the Run option of the File menu. 
  15312.  
  15313.  With pregimpl or wregimpl, you can view, add, change or delete DSOM 
  15314.  implementation definitions, as well as view add or delete implementation class 
  15315.  definitions. These basic functions are accessible from the main menu in the 
  15316.  initial window that displays when you start pregimpl or wregimpl. Thus, the 
  15317.  main menu offers the choices: 
  15318.  
  15319.       File 
  15320.       Implementations 
  15321.       Classes 
  15322.  
  15323.  To work with an implementation definition,  first click Implementations on the 
  15324.  main menu (or press Alt-I). The pulldown menu that appears shows the options: 
  15325.  
  15326.       View 
  15327.       Add 
  15328.       Change 
  15329.       Delete 
  15330.  
  15331.  To add an implementation definition, click Add  on the pulldown menu (or press 
  15332.  A). This will bring up the Add Implementations  dialog box, where you can 
  15333.  define or change fields as necessary. The "Alias" field is the only blank 
  15334.  field for which a setting is mandatory. For this, you should enter a " 
  15335.  shorthand" name for conveniently referencing the registered server 
  15336.  implementation while using pregimpl or wregimpl; for example:  myServer 
  15337.  
  15338.  Except for the "Alias" setting, the remainder of the fields may be left either 
  15339.  blank or with the default settings that are provided (see "Registration steps 
  15340.  using `regimpl'" for descriptions of the defaults). If you should clear a 
  15341.  field that originally contained a default, then when the implementation is 
  15342.  applied, pregimpl or wregimpl will still use the default setting [Note: The 
  15343.  implementation-ID ("Impl ID") field is also displayed. This is not an editable 
  15344.  field but is shown for information purposes.] 
  15345.  
  15346.  Once the definition is complete, click Apply  (or press Alt-A) to add the 
  15347.  definition. Click Discard  (or Alt-D) to discard a new definition. You can 
  15348.  select Exit (or Alt-X) at any time to exit the dialog box. (Message boxes or 
  15349.  confirmation windows typically appear after you make entries.) 
  15350.  
  15351.  To change an implementation definition,  click Change  from the 
  15352.  Implementations pulldown menu (or press C). In the Change Implementations 
  15353.  dialog box that appears, you can select the desired implementation by 
  15354.  scrolling though the list box on the left and highlighting your choice. Each 
  15355.  time an implementation is highlighted, details of its definition will appear 
  15356.  in the edit fields on the right. You can change any of the fields except the 
  15357.  implementation-ID. Once the changes are made, click Apply  (or Alt-A) or 
  15358.  Discard  (or Alt-D) as desired. Click Exit  (or Alt-X) to exit the dialog box. 
  15359.  
  15360.  The View  and Delete  implementations functions work similarly to the Change 
  15361.  Implementations function above. That is, you can highlight a selection in the 
  15362.  list box on the left, and details of its definition will appear in the edit 
  15363.  fields on the right. In the Delete Implementations dialog box, click Delete 
  15364.  Current Implementation  to delete a selected implementation definition. For 
  15365.  either function, click Exit  (or Alt-X) to exit the dialog box. 
  15366.  
  15367.  To work with class definitions,  first click Classes from the main menu (or 
  15368.  press Alt-C). This produces a pulldown menu with the options: 
  15369.  
  15370.       View 
  15371.       Add 
  15372.       Delete 
  15373.  
  15374.  To add classes, select Add  on the Classes pulldown menu (or press A) From the 
  15375.  resulting Add Classes  dialog box, you can select an implementation by 
  15376.  scrolling through the list box on the left and highlighting your choice. When 
  15377.  an implementation is selected, the classes associated with it will display in 
  15378.  the list box on the right. To add a new class name to the highlighted 
  15379.  implementation, enter the name in the edit field at the bottom right, and 
  15380.  click Add Class (or press Alt-A). The new class name will then appear in the 
  15381.  list box on the right. 
  15382.  
  15383.  The current class name will not be cleared from the edit field, so that more 
  15384.  implementations may be selected, if appropriate, and the same class can be 
  15385.  added to them. Or, you can enter another new class name and add it to the 
  15386.  implementation as described above. Exit  (or Alt-X) may be selected at any 
  15387.  time to exit the dialog box. 
  15388.  
  15389.  To view classes,select View  from the Classes pulldown menu (or press V). When 
  15390.  you highlight an implementation in the list box on the left, the classes 
  15391.  associated with the implementation will be shown in the list box on the right. 
  15392.  
  15393.  To switch key order, select the "Classes" radio button under "Display keyed 
  15394.  by". This causes all of the defined classes to appear in the list box on the 
  15395.  left. When you highlight a class name, all of the implementations associated 
  15396.  with that class will appear in the list box on the right. Exit  (or Alt-X) may 
  15397.  be selected at any time to exit the dialog box. 
  15398.  
  15399.  To delete classes,select Delete  from the Classes pulldown menu (or press D). 
  15400.  When you highlight an implementation in the list box on the left, the classes 
  15401.  associated with the implementation will be shown in the list box on the right. 
  15402.  You can then highlight a class and click Delete Class  (or Alt-D) to delete 
  15403.  the class from the highlighted implementation. A confirmation window will 
  15404.  appear next, which will also give you the option of deleting the class from 
  15405.  all  implementations. Exit  (or Alt-X) may be selected at any time to exit the 
  15406.  dialog box. 
  15407.  
  15408.  Important: Please note that any changes are saved internally in memory, but 
  15409.  are not  written to the database until you save the changes by clicking File 
  15410.  (or Alt-F) from the main menu and the n Save  (or S) from the resulting 
  15411.  pulldown menu. Conversely, you can abort all changes and reload the original 
  15412.  database by clicking File (Alt-F) and then Abort+Reload  (A). To exit the 
  15413.  pregimpl or wregimpl program, click File  (Alt-F) and then Exit  (X). 
  15414.  
  15415.  
  15416. ΓòÉΓòÉΓòÉ 8.6.5. Programmatic interface to the Implementation Repository ΓòÉΓòÉΓòÉ
  15417.  
  15418. The Implementation Repository can be accessed and updated dynamically using the 
  15419. programmatic interface provided by the ImplRepository class (defined in 
  15420. "implrep.idl"). The global variable SOMD_ImplRepObject is initialized by 
  15421. SOMD_Init to point to the ImplRepositor object. The following methods are 
  15422. defined on it: 
  15423.  
  15424.             void  add_impldef (in ImplementationDef impldef)
  15425.  
  15426.       Adds an implementation definition to the Implementation Repository. 
  15427.       (Note: The value of the "impl_id" attribute is ignored. A unique ImplId 
  15428.       will be generated for the newly added ImplementationDef.) 
  15429.  
  15430.             void  delete_impldef (in ImplId implid);
  15431.  
  15432.       Deletes an implementation definition from the Implementation Repository. 
  15433.  
  15434.             void update_impldef(in ImplementationDef impldef);
  15435.  
  15436.       Updates the implementation definition (defined by the "impl_id" of the 
  15437.       supplied implementationDef) in the Implementation Repository. 
  15438.  
  15439.             ImplementationDef find_impldef(in ImplId implid);
  15440.  
  15441.       Returns a server implementation definition given its ID. 
  15442.  
  15443.             ImplementationDef find_impldef_by_alias(in string alias_name);
  15444.  
  15445.       Returns a server implementation definition, given its user-friendly 
  15446.       alias. 
  15447.  
  15448.             sequence<ImplementationDef>  find_impldef_by_class
  15449.                                                         (in string classname)
  15450.  
  15451.       Returns a sequence of ImplementationDefs for those servers that have an 
  15452.       association with the specified class. Typically, a server is associated 
  15453.       with the classes it knows how to implement, by registering its known 
  15454.       classes via the add_class_to_impldef method. 
  15455.  
  15456.             ORBStatus  find_all_impldefs  (out sequence<ImplementationDef> outimpldefs);
  15457.  
  15458.       Retrieves all ImplementationDef objects in the Implementation Repository. 
  15459.  
  15460.  The following methods maintain an association between server implementations 
  15461.  and the names of the classes they implement. These methods effectively 
  15462.  maintain a mapping of <className, Implid>. 
  15463.  
  15464.             void add_class_to_impldef (in ImplId implid,
  15465.                                         in string classname);
  15466.  
  15467.       Associates a class, identified by name, with a server, identified by its 
  15468.       ImplId. This type of association is used to lookup server implementations 
  15469.       via the find_impldef_by_class method. 
  15470.  
  15471.             void  remove_class_from_impldef (
  15472.                                          in ImplId implid,
  15473.                                          in string classname);
  15474.  
  15475.       Removes the association of a particular class with a server. 
  15476.  
  15477.             void remove_class_from_all (
  15478.  
  15479.                                        in string classname);
  15480.  
  15481.       Removes the association of a particular class from all server 
  15482.       implementations in the Implementation Repository. 
  15483.  
  15484.             sequence<string>  find_classes_by_impldef
  15485.                                           (in ImplId implid);
  15486.  
  15487.       Returns a sequence of class names associated with a server. 
  15488.  
  15489.  With the ImplRepository programmatic interface, it is possible for an 
  15490.  application to define additional server implementations at run time. 
  15491.  
  15492.  
  15493. ΓòÉΓòÉΓòÉ 8.6.6. The `dsom' server manager utility ΓòÉΓòÉΓòÉ
  15494.  
  15495. The dsom utility is a command-line utility program used to manage server 
  15496. processes. At present, server processes that can be managed are limited to 
  15497. those present in the Implementation Repository. The choice of Implementation 
  15498. Repository is determined by the environment variable SOMDDIR. The dsom utility 
  15499. can be used to start, restart, stop, list, enable, or disable server processes. 
  15500. Note: The dsom command requires somdd to be running on the machine in which the 
  15501. server process is (or will be) located. 
  15502.  
  15503. The syntax of the dsom command is as follows: 
  15504.  
  15505. dsom <cmd> { impl_alias1 [impl_alias2 ...] |* }
  15506.  
  15507. where <cmd> can be any one of the terms:  start, restart, stop, list, disable, 
  15508. or enable. Each impl_alias is the server-alias name for a server process All 
  15509. forms of the command take one or more server-alias names, or a wild card 
  15510. character "*".  The "*" will be replaced with all of the server-alias names 
  15511. present in the Implementation Repository. 
  15512.  
  15513. For example, to start one or more server processes, the command takes the form: 
  15514.  
  15515. dsom start { impl_alias1 [impl_alias2 ...] | * }
  15516.  
  15517. To restart one or more server processes: 
  15518.  
  15519. dsom restart { impl_alias1 [impl_alias2 ...] | * }
  15520.  
  15521. To stop one or more server processes: 
  15522.  
  15523. dsom stop { impl_alias1 [impl_alias2 ...] | * }
  15524.  
  15525. To list the status of one or more server processes: 
  15526.  
  15527. dsom list { impl_alias1 [impl_alias2 ...] | * }
  15528.  
  15529. To prevent the server processes from starting, use the disable command. To 
  15530. disable one or more server processes: 
  15531.  
  15532. dsom disable { impl_alias1 [impl_alias2 ...] | * }
  15533.  
  15534. A previously disabled server process can be enabled by the enable command. To 
  15535. enable one or more server processes: 
  15536.  
  15537. dsom enable { impl_alias1 [impl_alias2 ...] | * }
  15538.  
  15539. Interpretation of `dsom' messages 
  15540.  
  15541. The messages generated by the dsom utility have a one-to-one mapping on the 
  15542. DSOM error codes. Knowing this mapping will aid in a better understanding of 
  15543. the dsom return messages. The following six messages are mapped onto the DSOM 
  15544. error code of 0 (success): 
  15545.  
  15546.  'dsom' cmd    Message 
  15547.  
  15548.  start       **Started server process** 
  15549.  
  15550.  restart     **Restarted server process** 
  15551.  
  15552.  list        **Server process currently running** 
  15553.  
  15554.  stop        **Stopped server process** 
  15555.  
  15556.  disable     **Successfully disabled server** 
  15557.  
  15558.  enable      **Successfully enabled server** 
  15559.  
  15560.  The messages generated by the dsom utility commands are mapped onto DSOM error 
  15561.  codes, as follows: 
  15562.  
  15563.   ΓöîΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÉ
  15564.   ΓöéDSOM error code      Message             Γöé
  15565.   Γöé                                         Γöé
  15566.   ΓöéSOMDERROR_ServerNotF **Server process notΓöé
  15567.   Γöé                     running**           Γöé
  15568.   Γöé                                         Γöé
  15569.   ΓöéSOMDERROR_NotProcess **Cannot stop       Γöé
  15570.   Γöé                     server; Not process Γöé
  15571.   Γöé                     owner**             Γöé
  15572.   Γöé                                         Γöé
  15573.   ΓöéSOMDERROR_NoSocketsC **Cannot find       Γöé
  15574.   Γöé                     Sockets class**     Γöé
  15575.   Γöé                                         Γöé
  15576.   ΓöéSOMDERROR_NoRemoteCo **Not enabled for   Γöé
  15577.   Γöé                     Workgroup**         Γöé
  15578.   Γöé                                         Γöé
  15579.   ΓöéSOMDERROR_CommTimeOu **Client timed out**Γöé
  15580.   Γöé                                         Γöé
  15581.   ΓöéSOMDERROR_SendError  **Send Error**      Γöé
  15582.   Γöé                                         Γöé
  15583.   ΓöéSOMDERROR_SocketSend **Send Error**      Γöé
  15584.   Γöé                                         Γöé
  15585.   ΓöéSOMDERROR_ServerInac **Server activation Γöé
  15586.   Γöé                     pending**           Γöé
  15587.   Γöé                                         Γöé
  15588.   ΓöéSOMDERROR_NoSOMDInit **Unable to create  Γöé
  15589.   Γöé                     global              Γöé
  15590.   Γöé                     LocSerObject**      Γöé
  15591.   Γöé                                         Γöé
  15592.   ΓöéSOMDERROR_UnknownErr **Command not       Γöé
  15593.   Γöé                     supported by daemon*Γöé
  15594.   Γöé                                         Γöé
  15595.   ΓöéSOMDERROR_ServerDisa **Server process is Γöé
  15596.   Γöé                     currently disabled**Γöé
  15597.   Γöé                                         Γöé
  15598.   ΓöéSOMDERROR_CouldNotSt **Server process    Γöé
  15599.   Γöé                     cannot be started** Γöé
  15600.   Γöé                                         Γöé
  15601.   ΓöéSOMDERROR_ServerToBe **Current server    Γöé
  15602.   Γöé                     process marked for  Γöé
  15603.   Γöé                     deletion; try       Γöé
  15604.   Γöé                     again**             Γöé
  15605.   Γöé                                         Γöé
  15606.   ΓöéAny other error      **Request           Γöé
  15607.   Γöé                     unsuccessful;       Γöé
  15608.   Γöé                     Unknown error**     Γöé
  15609.   Γöé                                         Γöé
  15610.   Γöé                                         Γöé
  15611.   Γöé                                         Γöé
  15612.   ΓööΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÿ
  15613.  
  15614.  In addition, if the impl_alias specified with any dsom utility command is not 
  15615.  present in the Implementation Repository, DSOM will generate the message: 
  15616.  **Server alias not found in Implementation Repository**. 
  15617.  
  15618.  Programmatic interface to manage server processes 
  15619.  
  15620.  Server processes can also be managed by using the programmatic interface 
  15621.  provided by the SOMDServerMgr class. For descriptions of the SOMDServerMgr 
  15622.  class and its corresponding methods, see the DSOM section of the SOMobjects 
  15623.  Developer Toolkit Programmers Reference Manual. 
  15624.  
  15625.  
  15626. ΓòÉΓòÉΓòÉ 8.6.7. Verifying the DSOM environment with `somdchk' ΓòÉΓòÉΓòÉ
  15627.  
  15628. The somdchk program evaluates the environment to verify whether DSOM can 
  15629. operate correctly. As described in the preceding topic s of Sections 6.5 
  15630. "Implementing Classes" and 6.6 "Configuring DSOM Applications," to  operate 
  15631. correctly DSOM must be able to find the appropriate libraries (DLLs), the 
  15632. Interface Repository, and the Implementation Repository. The settings of 
  15633. various environment variables help DSOM find the path to the libraries and 
  15634. repositories. 
  15635.  
  15636. The somdchk program generates messages that evaluate the DSOM environment. It 
  15637. determines whether the necessary SOM DLLs can be located, whether DSOM is 
  15638. enabled for workgroup (cross-machine) communication, whether Interface and 
  15639. Implementation Repositories can be located, and it displays the settings of 
  15640. important environment variables. In its "verbose" mode, somdchk gives the 
  15641. default settings for DSOM environment variables and explains how DSOM uses 
  15642. them. 
  15643.  
  15644. On AIX or OS/2, the program is invoked from the command line using the syntax 
  15645. given below. The optional verbose setting can be turned on by including the -v 
  15646. option with the command: 
  15647.  
  15648. somdchk  [-v]
  15649.  
  15650. On Windows, the somdchk program can be invoked by double clicking on the 
  15651. SOMDCHK icon. The resulting messages will appear in the message window. 
  15652.  
  15653. The following example shows sample output from the somdchk -v  command on AIX. 
  15654. Output on other platforms would look similar. 
  15655.  
  15656.      D S O M    E N V I R O N M E N T   E V A L U A T I O N
  15657.  
  15658. SOMBASE = /usr/lpp/som
  15659. SOMBASE should not be set to the base directory of the SOMObjects Toolkit Enablers.
  15660.  
  15661. Searching for important DLLs.....
  15662. /usr/lpp/som/lib/som.dll found.
  15663. /usr/lpp/som/lib/somd.dll found.
  15664. /usr/lpp/som/lib/soms.dll found.
  15665. /usr/lpp/som/lib/somst.dll found.
  15666.  
  15667. /usr/lpp/som/lib/somd.dll IS Workgroup Enabled.
  15668. Workgroup Enabled DLL permits inter-machine communication.
  15669.  
  15670. SOMSOCKETS  = TCPIPSockets
  15671. SOMSOCKETS must be set. Valid settings are:
  15672.    TCPIPSockets for TCPIP.
  15673.    IPXSockets for NetWare.
  15674.  
  15675. SOMDDIR    = /u/raviv/impl_rep/
  15676. Valid Implementation Repository found in /u/raviv/impl_rep/
  15677. SOMDDIR may be set to a valid directory in which the Implementation Repository
  15678. resides.
  15679.    Default is /usr/lpp/som/etc/dsom
  15680.  
  15681.  
  15682. SOMIR    = /u/raviv/raviv.ir
  15683. SOMIR may be set to a list of file names which together form the Interface
  15684. Repository.
  15685.    Default is ./som.ir
  15686. /u/raviv/raviv.ir found.
  15687.  
  15688. SOMDPORT   = 3001
  15689. SOMDPORT may be set to a 'well-known port'. Default value is 9393.
  15690.  
  15691. SOMDTIMEOUT  = (null).
  15692. SOMDTIMEOUT may be set to the number of seconds to timeout.
  15693.    Default value is 600.
  15694.  
  15695. SOMDDEBUG    = 2
  15696. SOMDDEBUG may be set to 1 to enable runtime error messages.
  15697.    Default value is 0.
  15698.  
  15699. SOMDMESSAGELOG    = (null).
  15700. SOMDMESSAGELOG may be set to the name of a file where messages may be logged.
  15701.    Default is stdout.
  15702.  
  15703.  
  15704. ΓòÉΓòÉΓòÉ 8.7. Running DSOM Applications ΓòÉΓòÉΓòÉ
  15705.  
  15706. Prior to starting the DSOM processes, the DSOM executables should be installed 
  15707. and the DSOM environment variables should be set appropriately, as discussed in 
  15708. the earlier section, "Configuring DSOM Applications." 
  15709. Running the DSOM daemon (somdd) 
  15710.  
  15711. To run a DSOM application, the DSOM daemon, somdd, must be started: 
  15712.  
  15713.    o  On AIX or OS/2, the daemon can be started manually from the command line, 
  15714.       or could be started automatically from a start-up script run at boot 
  15715.       time. It may be run in the background with the commands somdd& on AIX, 
  15716.       and start somdd on OS/2. (The somdd command has the following syntax: 
  15717.  
  15718.             somdd [-q]
  15719.  
  15720.       where the optional -q flag signifies "quiet" mode.  By default, somdd 
  15721.       will produce a" ready" message when the DSOM daemon is ready to process 
  15722.       requests, and it will produce diagnostic messages as errors are 
  15723.       encountered if the SOMDDEBUG environment variable is set to 1. In quiet 
  15724.       mode, however, the "ready" message will not appear, and diagnostic 
  15725.       messages will not appear even if SOMDEBUG is set. Alternatively, if the 
  15726.       SOMDMESSAGELOG environment variable is set, diagnostic error messages 
  15727.       will be sent directly to the specified message log file, regardless of 
  15728.       whether the -q flag is specified. 
  15729.  
  15730.    o  On Windows, the daemon can be started with the DSOM Daemon icon in the 
  15731.       SOM icon group or started in Windows from the Run option of the file 
  15732.       menu.  The DSOM Daemon icon will change colors to indicate that the 
  15733.       daemon is ready, after which client and server programs can be started. 
  15734.  
  15735.  The somdd daemon is responsible for "binding" a client process to a server 
  15736.  process and will activate the desired server if necessary. The binding 
  15737.  procedure is such that the client will consult the Implementation Repository 
  15738.  to find out which machine contains a desired server, and will then contact the 
  15739.  DSOM daemon on the server's machine to retrieve the server's communications 
  15740.  address (a port). Servers are activated dynamically as separate processes. 
  15741.  Running DSOM servers 
  15742.  
  15743.  Once the somdd daemon is running, application programs can be started. If the 
  15744.  application uses the generic SOM server, somdsvr, it can be started either 
  15745.  from the command line or automatically upon demand. When starting somdsvr from 
  15746.  the command line, the server's implementation ID or alias must be supplied as 
  15747.  an argument. The command syntax for starting a generic SOM server is: 
  15748.  
  15749.      somdsvr  [ impl_id  | -a alias ]
  15750.  
  15751.  For example, the command 
  15752.  
  15753.   $   somdsvr  2ad2688fb-00389c00-7f-00-10005ac900d8
  15754.  
  15755.  would start a somdsvr for an implementation with the specified ID. Likewise, 
  15756.  the command 
  15757.  
  15758.   $   somdsvr  -a  myServer
  15759.  
  15760.  would start a somdsvr that represents an implementation of "myServer". 
  15761.  
  15762.  
  15763. ΓòÉΓòÉΓòÉ 8.8. DSOM as a CORBA-compliant Object Request Broker ΓòÉΓòÉΓòÉ
  15764.  
  15765. The Object Management Group (OMG) consortium defines the notion of an Object 
  15766. Request Broker (ORB) that supports access to remote objects in a distributed 
  15767. environment. Thus, Distributed SOM is an ORB. SOM and DSOM together comply with 
  15768. the OMG's specification of the Common Object Request Broker Architecture 
  15769. (CORBA). 
  15770.  
  15771. Since the interfaces of SOM and DSOM are largely determined by the CORBA 
  15772. specification, the CORBA components and interfaces are highlighted in this 
  15773. section. 
  15774.  
  15775. The CORBA specification defines the components and interfaces that must be 
  15776. present in an ORB, including the: 
  15777.  
  15778.    o  Interface Definition Language (IDL) for defining classes (discussed in 
  15779.       Chapter 4, "SOM IDL and the SOM Compiler"). 
  15780.  
  15781.    o  C usage bindings (procedure-call formats) for invoking methods on remote 
  15782.       objects, 
  15783.  
  15784.    o  Dynamic Invocation Interface and an Interface Repository, which support 
  15785.       the construction of requests (method calls) at run time (for example, for 
  15786.       interactive desktop applications), and 
  15787.  
  15788.    o  Object Request Broker run-time programming interfaces. 
  15789.  
  15790.  SOM and DSOM were developed to comply with these specifications (with only 
  15791.  minor extensions to take advantage of SOM services). Although the capabilities 
  15792.  of SOM are integral to the implementation of DSOM, the application programmer 
  15793.  need not be aware of SOM as the implementation technology for the ORB. 
  15794.  
  15795.  This section assumes some familiarity with The Common Object Request Broker: 
  15796.  Architecture and Specification, Revision 1.1 (also referred to as "CORBA 
  15797.  1.1"). The specification is published jointly by the Object Management Group 
  15798.  and x/Open. The mapping of some CORBA 1.1 terms and concepts to D SOM terms 
  15799.  and concepts is described in the remainder of this section. 
  15800.  
  15801.  
  15802. ΓòÉΓòÉΓòÉ 8.8.1. Mapping OMG CORBA terminology onto DSOM ΓòÉΓòÉΓòÉ
  15803.  
  15804. This section discusses how various CORBA concepts and terms are defined in 
  15805. terms of DSOM's implementation of the CORBA 1.1 standard. 
  15806. Object Request Broker run-time interfaces 
  15807.  
  15808. In the previous sections, the SOMDObjectMgr and SOMDServer classes were 
  15809. introduced. These are classes defined by DSOM to provide basic support in 
  15810. managing objects in a distributed application. These classes are built upon 
  15811. Object Request Broker interfaces defined  by  CORBA for building and 
  15812. dispatching requests on objects. The ORB interfaces, SOMDObjectMgr and 
  15813. SOMDServer, together provide the support for implementing distributed 
  15814. applications in DSOM. 
  15815.  
  15816. CORBA 1.1 defines the interfaces to the ORB components in IDL. In DSOM, the ORB 
  15817. components are implemented as SOM classes whose interfaces are expressed using 
  15818. the same CORBA 1.1 IDL. Thus, an application can make calls to the DSOM run 
  15819. time using the SOM language bindings of its choice. 
  15820.  
  15821. Interfaces for the following ORB run-time components are defined in CORBA 1.1, 
  15822. and are implemented in DSOM. They are introduced briefly here, and discussed in 
  15823. more detail throughout this chapter. (See the SOMobjects Developer Toolkit: 
  15824. Programmers Reference Manual for the complete interface definitions.) 
  15825.  
  15826.  Object               The Object interface defines operations on an "object 
  15827.                       reference", which is the information needed to specify an 
  15828.                       object within the ORB. 
  15829.  
  15830.                       In DSOM, the class SOMDObject implements the CORBA 1.1 
  15831.                       Object interface. (The"SOMD" prefix was added to 
  15832.                       distinguish this class from SOMObject.) The subclass 
  15833.                       SOMDClientProxy extends SOMDObject with support for proxy 
  15834.                       objects. 
  15835.  
  15836.  ORB                  (Object Request Broker) The ORB interface defines utility 
  15837.                       routines for building requests and saving references to 
  15838.                       distributed objects. The global variable SOMD_ORBObject 
  15839.                       is initialized by SOMD_Init and provides the reference to 
  15840.                       the ORB object. 
  15841.  
  15842.  ImplementationDef    An ImplementationDef object is used to describe an 
  15843.                       object's implementation. Typically, the ImplementationDef 
  15844.                       describes the program that implements an object's server, 
  15845.                       how the program is activated, and so on. 
  15846.  
  15847.                       (CORBA 1.1 introduces ImplementationDef as the name of 
  15848.                       the interface, but leaves the remainder of the IDL 
  15849.                       specification to the particular ORB. DSOM defines an 
  15850.                       interface for ImplementationDef.) 
  15851.  
  15852.                       ImplementationDef objects are stored in the 
  15853.                       Implementation Repository (defined in DSOM by the 
  15854.                       ImplRepository class). 
  15855.  
  15856.  InterfaceDef         An InterfaceDef object is used to describe an IDL 
  15857.                       interface in a manner that can be queried and manipulated 
  15858.                       at run time when building requests dynamically, for 
  15859.                       example. 
  15860.  
  15861.                       InterfaceDef objects are stored in the Interface 
  15862.                       Repository (described fully in Chapter 7, "The Interface 
  15863.                       Repository Framework"). 
  15864.  
  15865.  Request              A Request object represents a specific request on an 
  15866.                       object, constructed at run-time. The Request object 
  15867.                       contains the target object reference, operation (method) 
  15868.                       name, a list of input and output arguments. A Request can 
  15869.                       be invoked synchronously (wait for the response), 
  15870.                       asynchronously (initiate the call, and later, get the 
  15871.                       response), or as a "oneway" call (no response expected). 
  15872.  
  15873.  NVList               An NVList is a list of NamedValue structures, used 
  15874.                       primarily in building Request objects. A NamedValue 
  15875.                       structure consists of a name, typed value, and some flags 
  15876.                       indicating how to interpret the value, how to 
  15877.                       allocate/free the value's memory, and so on. 
  15878.  
  15879.  Context              A Context object contains a list of "properties" that 
  15880.                       represent information about an application process's 
  15881.                       environment. Each Context property consists of a 
  15882.                       <name,string_value> pair,and is used by application 
  15883.                       programs or methods much like the "environment variables" 
  15884.                       commonly found in operating systems like AIX and OS/2 and 
  15885.                       Windows. IDL method interfaces can explicitly list which 
  15886.                       properties are queried by a method, and the ORB will pass 
  15887.                       those property values to a remote target object when 
  15888.                       making a request. 
  15889.  
  15890.  Principal            A Principal object identifies the principal ("user") on 
  15891.                       whose behalf a request is being performed. 
  15892.  
  15893.                       (CORBA 1.1 introduces the name of the interface, 
  15894.                       Principal, but leaves the remainder of the IDL 
  15895.                       specification to the particular ORB. DSOM defines an 
  15896.                       interface for Principal.) 
  15897.  
  15898.  BOA                  (Basic Object Adapter) An Object Adapter provides the 
  15899.                       primary interface between an implementation and the ORB 
  15900.                       "core". An ORB may have a number of Object Adapters, with 
  15901.                       interfaces that are appropriate for specific kinds of 
  15902.                       objects. 
  15903.  
  15904.  The Basic Object Adapter is intended to be a general-purpose Object Adapter 
  15905.  available on all CORBA-compliant Object Request Brokers. The BOA interface 
  15906.  provides support for generation of object references, identification of the 
  15907.  principal making a call, activation and deactivation of objects and 
  15908.  implementations, and method invocation on objects. 
  15909.  
  15910.  In DSOM, BOA is defined as an abstract class. The SOMOA (SOM Object Adapter) 
  15911.  class, derived from BOA, is DSOM's primary Object Adapter implementation. The 
  15912.  SOMOA interface extends the BOA interface with several of its own methods that 
  15913.  are not defined by CORBA 1.1. 
  15914.  Object references and proxy objects 
  15915.  
  15916.  CORBA 1.1 defines the notion of an object reference, which is the information 
  15917.  needed to specify an object in the ORB. An object is defined by its 
  15918.  ImplementationDef, InterfaceDef, and application-specific "reference data" 
  15919.  used to identify or describe the object. An object reference is used as a 
  15920.  handle to a remote object in method calls. When a server wants to export a 
  15921.  reference to an object it implements, it supplies the object's 
  15922.  ImplementationDef, InterfaceDef, and reference data to the Object Adapter, 
  15923.  which returns the reference. 
  15924.  
  15925.  The structure of an object reference is opaque to the application, leaving its 
  15926.  representation up to the ORB. 
  15927.  
  15928.  In DSOM, an object reference is represented as an object that can simply be 
  15929.  used to identify the object on that server. The DSOM class that implements 
  15930.  simple object references is called SOMDObject (corresponding to Object in 
  15931.  CORBA 1.1.) However, in a client's address space, DSOM represents the remote 
  15932.  object with a proxy object in order to allow the client to invoke methods on 
  15933.  the target object as if it were local. When an object reference is passed from 
  15934.  a server to a client, DSOM dynamically and automatically creates a proxy in 
  15935.  the client for the remote object. Proxies are specialized forms of SOMDObject; 
  15936.  accordingly, the base proxy class in DSOM SOMDClientProxy, is derived from 
  15937.  SOMDObject. 
  15938.  
  15939.  In order to create a proxy object, DSOM must first build a proxy class. It 
  15940.  does so automatically using SOM facilities for building classes at run time. 
  15941.  The proxy class is constructed using multiple inheritance: the proxy object 
  15942.  functionality is inherited from SOMDClientProxy, while just the interface of 
  15943.  the target class is inherited. 
  15944.  
  15945.  In the newly derived proxy class, DSOM overrides each method inherited from 
  15946.  the target class with a "remote dispatch" method that forwards an invocation 
  15947.  request to the remote object. Consequently, the proxy object provides location 
  15948.  transparency, and the client code invokes operations (methods) on the remote 
  15949.  object using the same language bindings as if it were a local target object. 
  15950.  
  15951.  For example, recall the "Stack" class used in the tutorial example given 
  15952.  earlier. When a server returns a reference to a remote "Stack" object to the 
  15953.  client, DSOM builds a "Stack_ _Proxy" class (note two underscores in the 
  15954.  name), derived from SOMDClientProxy and "Stack", and creates a proxy object 
  15955.  from that class.  When the client invokes the "push" method on the proxy, 
  15956.  
  15957.  
  15958.   _push(stk, &ev, 100);
  15959.  
  15960.  the method is redispatched using the remote-dispatch method of the 
  15961.  SOMDClientProxy class, and the method is forwarded to the target object. 
  15962.  
  15963.  CORBA defines several special operations on object references that operate on 
  15964.  the local references (proxies) themselves, rather than on the remote objects. 
  15965.  These operations are defined by the classes SOMOA (SOM Object Adapter), 
  15966.  SOMDObject (which is DSOM's implementation of CORBA's Object "pseudo-class" 
  15967.  and ORB (Object Request Broker class). Some of these operations are listed 
  15968.  below, expressed in terms of their IDL definitions. 
  15969.  
  15970.  SOMOA methods (inherited from BOA): 
  15971.  
  15972.  
  15973.             sequence <octet,1024> ReferenceData;
  15974.             SOMDObject  create (in ReferenceData id, in InterfaceDef intf
  15975.                                 in ImplementationDef impl);
  15976.  
  15977.  Creates and returns an object reference. 
  15978.  
  15979.  SOMDObject methods: 
  15980.  
  15981.             SOMDObject  duplicate ( );
  15982.  
  15983.       Creates and returns a duplicate object reference. 
  15984.  
  15985.             void  release ( );
  15986.  
  15987.       Destroys an object reference. 
  15988.  
  15989.             boolean  is_nil ( );
  15990.  
  15991.       Tests to see if the object reference is NULL. 
  15992.  
  15993.  ORB methods: 
  15994.  
  15995.             string  object_to_string ( SOMDObject obj );
  15996.  
  15997.       Converts an object reference to a (storable) string form. 
  15998.  
  15999.             SOMDObject  string_to_object ( string str );
  16000.  
  16001.       Converts a string form back to the original object reference. 
  16002.  
  16003.  Creation of remote objects 
  16004.  
  16005.  The OMG has standardized an "object lifecycle service," built on top of the 
  16006.  ORB, for creating and destroying remote objects.  Currently, DSOM provides its 
  16007.  own interface for creating and destroying objects (see "Basic Client 
  16008.  Programming"), but a future release may provide an OMG-compliant lifecycle 
  16009.  service as well. 
  16010.  Interface definition language 
  16011.  
  16012.  The CORBA specification defines an Interface Definition Language, IDL, for 
  16013.  defining object interfaces. The SOM Compiler compiles standard IDL interface 
  16014.  specifications, but it also allows the class implementer to include 
  16015.  implementation information that will be used in the implementation bindings 
  16016.  for a particular language. 
  16017.  
  16018.  Note:  Before IDL, SOM (version 1.0) had its own Object Interface Definition 
  16019.         Language (OIDL). SOM classes specified using OIDL must be converted to 
  16020.         IDL before they can be used with DSOM. The SOMobjects Developer Toolkit 
  16021.         provides a migration tool for this purpose. 
  16022.  
  16023.  
  16024.  C language mapping 
  16025.  
  16026.  The CORBA specification defines the mapping of method interface definitions to 
  16027.  C language procedure prototypes, hence SOM defines the same mapping. This 
  16028.  mapping requires passing a reference to the target object and a reference to 
  16029.  an implementation-specific Environment structure as the first and second 
  16030.  parameters, respectively, in any method call. 
  16031.  
  16032.  The Environment structure is primarily used for passing error information from 
  16033.  a method back to its caller. See also the topic "Exceptions and Error 
  16034.  Handling" in Chapter 3, "Using SOM Classes in Client Programs," for a 
  16035.  description of how to "get" and "set" error information in the Environment 
  16036.  structure. 
  16037.  Dynamic Invocation Interface (DII) 
  16038.  
  16039.  The CORBA specification defines a Dynamic Invocation Interface (DII) that can 
  16040.  be used to dynamically build requests on remote objects. This interface is 
  16041.  described in section 6 (page 105) of the CORBA 1.1 document, and is 
  16042.  implemented in DSOM. The DSOM implementation of the DII is described later in 
  16043.  this chapter, in the topic entitled "Dynamic Invocation Interface" under 
  16044.  Section 6.9 "Advanced topics." Note that, in DSOM, somDispatch is overridden 
  16045.  so that method invocations on proxy objects are forwarded to the remote target 
  16046.  object. SOM applications can use the SOM somDispatch method for dynamic method 
  16047.  calls whether the object is local or remote. 
  16048.  Implementations and servers 
  16049.  
  16050.  The CORBA specification defines the term implementation as the code that 
  16051.  implements an object. The implementation usually consists of a program and 
  16052.  class libraries. 
  16053.  
  16054.  Servers are processes that execute object implementations. CORBA 1.1 defines 
  16055.  four activation policies for server implementations: shared, unshared, 
  16056.  server-per-method, and persistent, as follows. 
  16057.  
  16058.    o  A shared server implements multiple objects (of arbitrary classes the 
  16059.       same time, and allows multiple methods to be invoked at the same time. 
  16060.  
  16061.    o  An unshared  server, conversely, implements only a single object and 
  16062.       handles one request at a time. 
  16063.  
  16064.    o  The server-per-method  policy requires a separate process to be created 
  16065.       for each request on an object and, usually, a separate program implements 
  16066.       each method. 
  16067.  
  16068.       Under the shared, unshared, and server-per-method activation policies, 
  16069.       servers are activated automatically (on demand). 
  16070.  
  16071.    o  A persistent  server, by contrast, is a shared server that is activated 
  16072.       "by hand" (for example, from the command shell or from a startup script), 
  16073.       vs. being activated automatically when the first method is dispatched to 
  16074.       it. 
  16075.  
  16076.  The term "persistent server" refers to the relative lifetime of the server: it 
  16077.  is "always running" when DSOM is running. (CORBA implies that persistent 
  16078.  servers are usually started at ORB boot time.) It should not be assumed, 
  16079.  however, that a "persistent" server necessarily implements persistent objects 
  16080.  (that persist between ORB reboots). 
  16081.  
  16082.  In DSOM, specific process models are implemented by the server program. That 
  16083.  is, DSOM simply starts a specified program when a client attempts to connect 
  16084.  to a server. The four CORBA activation policies, or any other policies, can be 
  16085.  implemented by the application as necessary. For example, 
  16086.  
  16087.    o  an object that requires a server-per-method implementation could itself 
  16088.       spawn a process at the beginning of each method execution. Alternatively, 
  16089.       the server object in the "main" server can spawn a process before each 
  16090.       method dispatch. 
  16091.  
  16092.    o  a dedicated server could be registered for each object that requires an 
  16093.       unshared server implementation (separate process). This may be done 
  16094.       dynamically (see the topic "Programmatic interface to the Implementation 
  16095.       Repository" earlier in this chapter). 
  16096.  
  16097.  An ImplementationDef object, as defined by the CORBA specification, describes 
  16098.  the characteristics of a particular implementation. In DSOM, an 
  16099.  ImplementationDef identifies an implementation's unique ID, the program name, 
  16100.  its location, and so forth. The ImplementationDef objects are stored in an 
  16101.  Implementation Repository, which is represented in DSOM by an ImplRepository 
  16102.  object. 
  16103.  
  16104.  A CORBA-compliant ORB must provide the mechanisms for a server program to 
  16105.  register itself with the ORB. To "register itself with the ORB" simply means 
  16106.  to tell the ORB enough information about the server process so that the ORB 
  16107.  will be able to locate, activate, deactivate, and dispatch methods to the 
  16108.  server process. DSOM supports these mechanisms, so that server programs 
  16109.  written in arbitrary languages can be used with DSOM. (See also the next 
  16110.  topic, "Object Adapters.") 
  16111.  
  16112.  In addition to the generic registration mechanisms provided by all 
  16113.  CORBA-compliant ORBs, DSOM provides extra support for using SOM-class DLLs. 
  16114.  DSOM provides a generic server  program that automatically registers itself 
  16115.  with DSOM, loads SOM-class DLLs on demand, and dispatches incoming requests on 
  16116.  SOM objects. Thus, by using the generic server program (when appropriate), a 
  16117.  user may be able to avoid writing any server program code. 
  16118.  Object Adapters 
  16119.  
  16120.  An Object Adapter (OA) provides the mechanisms that a server process uses to 
  16121.  interact with DSOM, and vice versa. That is, an Object Adapter is responsible 
  16122.  for server activation and deactivation, dispatching methods, activation and 
  16123.  deactivation of individual objects, and providing the interface for 
  16124.  authentication of the principal making a call. 
  16125.  
  16126.  DSOM defines a Basic Object Adapter (BOA) interface, described in the CORBA 
  16127.  specification, as an abstract class (a class having no implementation, only an 
  16128.  interface specification). The BOA interface represents generic Object Adapter 
  16129.  methods that a server written in an arbitrary language can use to register 
  16130.  itself and its objects with the ORB. Because it is an abstract class having no 
  16131.  implementation, however, the BOA class should not be directly instantiated. 
  16132.  
  16133.  DSOM provides a SOM Object Adapter, SOMOA, derived from the BOA interface, 
  16134.  that uses SOM Compiler and run-time support to accomplish dispatching of 
  16135.  methods (that is, accepting messages, turning them into method invocations, 
  16136.  and routing the invocations to the target object in the server process). SOMOA 
  16137.  can be used to dispatch methods on either SOM or non-SOM object 
  16138.  implementations, as described in the sections "Implementing Classes" and 
  16139.  "Basic Server Programming." It is possible to use non-SOM based 
  16140.  implementations with SOMOA, and often there is no additional programming 
  16141.  required to use implementations (class libraries) already developed using SOM. 
  16142.  
  16143.  The SOMOA works in conjunction with the application-defined server object to 
  16144.  map between objects and object references, and to dispatch methods on objects. 
  16145.  By partitioning out these mapping and dispatching functions into the server 
  16146.  object, the application can more easily customize them, without having to 
  16147.  build object adapter subclasses. 
  16148.  
  16149.  SOMOA introduces two methods that handle execution of requests received by the 
  16150.  server: 
  16151.  
  16152.       execute_request_loop 
  16153.  
  16154.       execute_next_request 
  16155.  
  16156.  Typically, execute_request_loop is used to receive and execute requests, 
  16157.  continuously, in the server's main thread. The execute_next_request method 
  16158.  allows a single request to be executed. Both methods have a non-blocking 
  16159.  option: when there are no messages pending, the method call will return 
  16160.  instead of wait. 
  16161.  
  16162.  On OS/2, if the server implementation has been registered as "multi-threaded" 
  16163.  (via an IMPLDEF_MULTI_THREAD flag in the ImplementationDef), SOMOA will 
  16164.  automatically run each request in a separate thread. If the "multi-thread" 
  16165.  flag is not set, the server implementation can still choose to manage its own 
  16166.  threads. 
  16167.  
  16168.  The generic server program provided by DSOM (described in the preceding topic) 
  16169.  uses execute_request_loop to receive and execute requests on SOM objects. 
  16170.  Extensions and limitations 
  16171.  
  16172.  The DSOM implementation has the following extensions and limitations in its 
  16173.  implementation of the CORBA specification: 
  16174.  
  16175.    o  As just described, the current release of DSOM supports a simple server 
  16176.       activation policy, which is equivalent to the "shared" and "persistent" 
  16177.       policies defined by CORBA. DSOM does not explicitly support the 
  16178.       "unshared" or "server-per-method" server activation policies. Policies 
  16179.       other than the basic activation scheme must be implemented by the 
  16180.       application. 
  16181.  
  16182.    o  DSOM provides null implementations for the object_is_ready or 
  16183.       deactivate_obj methods, defined by the BOA interface for the unshared 
  16184.       server activation policy. 
  16185.  
  16186.    o  DSOM does not support the change_implementation method, defined by the 
  16187.       BOAinterface to allow an application to change the implementation 
  16188.       definition associated with an object. In DSOM, the ImplementationDef 
  16189.       identifies the server which implements an object.  In these terms, 
  16190.       changing an object's ImplementationDef would result in a change in the 
  16191.       object's server ID. Any existing object references that have the old 
  16192.       server ID would be rendered invalid. 
  16193.  
  16194.       It is possible, however, to change the program which implements an 
  16195.       object's server, or change the class library which implements an object's 
  16196.       class. To modify the program associated with an ImplementationDef, use 
  16197.       the update_impldef method defined on ImplRepository. To change the 
  16198.       implementation of an object's class, replace the corresponding class 
  16199.       library with a new (upward-compatible) one. 
  16200.  
  16201.    o  The OUT_list_MEMORY, IN_COPY_VALUE, and DEPENDENT_LIST flags, used with 
  16202.       the Dynamic Invocation Interface, are not yet supported. 
  16203.  
  16204.    o  The SOM Object Adapter (SOMOA) provides a method (change_id) to update 
  16205.       the ReferenceData  associated with an object reference created by the 
  16206.       create call This is useful if the information which describes the object 
  16207.       must be changed without invalidating copies of the existing object 
  16208.       reference. CORBA defines no such method;  change_id is an extension to 
  16209.       the standard BOA methods. 
  16210.  
  16211.    o  The SOMOA provides some specialized object reference types which, in 
  16212.       certain situations, are more efficient or easier-to-use than standard 
  16213.       object references. 
  16214.  
  16215.    o  DSOM supports the SOM extension to IDL that allows method parameters that 
  16216.       are pointers. Structure, sequence, and array parameters may only contain 
  16217.       pointers to objects (not arbitrary types). 
  16218.  
  16219.    o  The Context::get_values method currently does not support the 
  16220.       CTX_RESTRICT_SCOPE flag. 
  16221.  
  16222.  
  16223. ΓòÉΓòÉΓòÉ 8.9. Advanced Topics ΓòÉΓòÉΓòÉ
  16224.  
  16225.  
  16226. ΓòÉΓòÉΓòÉ 8.9.1. Peer vs. client/server processes ΓòÉΓòÉΓòÉ
  16227.  
  16228. The client/server model of distributed computing is appropriate when it is 
  16229. convenient (or necessary) to centralize the implementation and management of a 
  16230. set of shared objects in one or more servers. However, some applications 
  16231. require more flexibility in the distribution of objects among processes. 
  16232. Specifically, it is often useful to allow processes to manage and export some 
  16233. of their objects, as well as access remote objects owned by other processes. In 
  16234. these cases, the application processes do not adhere to a strict client/server 
  16235. relationship; instead, they cooperate as "peers", behaving both as clients and 
  16236. as servers. 
  16237.  
  16238. Peer applications must be written to respond to incoming asynchronous requests, 
  16239. in addition to performing their normal processing. In a multi-threaded system 
  16240. (like OS/2), this is best accomplished by dedicating a separate process thread 
  16241. that handles DSOM communications and dispatching. In systems that do not 
  16242. currently support multi-threading (like AIX), peer applications must be 
  16243. structured as event-driven programs. 
  16244. Multi-threaded DSOM programs 
  16245.  
  16246. In a system that supports multi-threading, like OS/2, the easiest way to write 
  16247. a peer DSOM program is to dedicate a separate thread to perform the usual 
  16248. "server" processing. This body of this thread would contain the same code as 
  16249. the simple servers described in section 6.4, "Basic Server Programming." 
  16250.  
  16251. DSOM_thread(void *params)
  16252. {
  16253.    Environment ev;
  16254.    SOM_InitEnvironment(&ev);
  16255.  
  16256. /* Initialize the DSOM run-time environment */
  16257.    SOMD_Init(&ev);
  16258.  
  16259. /* Retrieve its ImplementationDef from the Implementation
  16260.    Repository by passing its implementation ID as a key */
  16261.    SOMD_ImplDefObject =
  16262.       _find_impldef(SOMD_ImplRepObject, &ev, *(ImplId *)params);
  16263.  
  16264. /* Create SOM Object Adapter and begin executing requests */
  16265.    SOMD_SOMOAObject = SOMOANew();
  16266.    _impl_is_ready(SOMD_SOMOAObject, &ev, SOMD_ImplDefObject);
  16267.    _execute_request_loop(SOMD_SOMOAObject, &ev, SOMD_WAIT);
  16268. }
  16269.  
  16270. Note:  The DSOM run time is "thread safe"; that is, DSOM protects its own  data 
  16271.        structures and objects from race conditions and update conflicts. 
  16272.        However, it is the application's responsibility to implement its own 
  16273.        concurrency control for concurrent thread access to local shared 
  16274.        application objects. 
  16275.  
  16276.  
  16277.  Event-driven DSOM programs using EMan 
  16278.  
  16279.  EMan (see Chapter 9 on "The Event Management Framework") is not a replacement 
  16280.  for threads, but it supports processing of asynchronous requests. EMan allows 
  16281.  a program to handle events from multiple input sources; but the handlers run 
  16282.  on a single thread, under control of EMan's main loop. 
  16283.  
  16284.  DSOM provides a runtime function, SOMD_RegisterCallback, which is used by DSOM 
  16285.  to associate user-supplied event handlers with DSOM's communications sockets 
  16286.  and message queues with EMan. Example code is shown below. 
  16287.  
  16288.  DSOM server programs which use EMan must be very careful not to get into 
  16289.  deadlock situations. This is quite easy to do with DSOM, since method calls 
  16290.  are synchronous. If two cooperating processes simultaneously make calls on 
  16291.  each other, a deadlock could result. Likewise, if a method call on remote 
  16292.  object B from A requires a method call back to A, a deadlock cycle will exist. 
  16293.  (Of course, the number of processes and objects which create the cyclic 
  16294.  dependency could be greater than two.) 
  16295.  
  16296.  The application developer must be careful to avoid situations where 
  16297.  cooperating processes are likely to make calls upon each other, creating a 
  16298.  cyclic dependency. Some applications may find it appropriate to use oneway 
  16299.  messages to avoid deadlock cycles, since oneway messages do not cause a 
  16300.  process to block. It may also be possible for an application to defer the 
  16301.  actual processing of a method that may "call back" an originating process, by 
  16302.  scheduling work using EMan client events. 
  16303.  Sample server using EMan 
  16304.  
  16305.  The following server code has been distilled from one of the DSOM sample 
  16306.  applications provided with SOMobjects Developer Toolkit. It is an example of a 
  16307.  server which has an interval timer that signals another server (via DSOM) 
  16308.  whenever its timer "pops". Thus, it is both a client (of the server it 
  16309.  signals) and a server (because it can receive timer notifications from other 
  16310.  servers). 
  16311.  
  16312.  The IDL for the server object class to be used by this server program is as 
  16313.  follows. Note that the "noteTimeout" method is oneway, in order to avoid 
  16314.  deadlock. 
  16315.  
  16316.   interface PeerServer :SOMDServer
  16317.   { oneway void noteTimeout(in string serverName);
  16318.     // Notification that a timer event occurred in server serverName
  16319.   };
  16320.  
  16321.  The example server program is outlined as follows. It is assumed that "eman.h" 
  16322.  has been included by the program. 
  16323.  
  16324.    o  Perform DSOM initialization up to, but not including, asking SOMOA to 
  16325.       start handling requests. 
  16326.  
  16327.             MyEMan = SOMEEManNew();
  16328.             SOM_InitEnvironment(&ev);
  16329.             SOM_InitEnvironment(&peerEv);
  16330.             SOMD_Init(&ev);
  16331.  
  16332.             somPrintf("What is the alias for this server? ");
  16333.             gets(thisServer);
  16334.  
  16335.             SOMD_ImplDefObject = _find_impldef_by_alias(SOMD_ImplRepObject,
  16336.                                                          &ev, thisServer);
  16337.             SOMD_SOMOAObject = SOMOANew();
  16338.             _impl_is_ready(SOMD_SOMOAObject, &ev, SOMD_ImplDefObject);
  16339.  
  16340.    o  Register a "DSOM event" with EMan, having EMan callback to a procedure 
  16341.       that asks the SOMOA to process any pending DSOM requests. 
  16342.  
  16343.             void SOMD_RegisterCallback(SOMEEman emanObj, EMRegProc *func);
  16344.  
  16345.             void DSOMEventCallBack (SOMEEvent event, void *eventData)
  16346.             {   Environment ev;
  16347.                 SOM_InitEnvironment(&ev);
  16348.                 _execute_request_loop(SOMD_SOMOAObject, &ev, SOMD_NO_WAIT);
  16349.             }
  16350.  
  16351.             SOMD_RegisterCallback (MyEMan, DSOMEventCallBack);
  16352.  
  16353.    o  Ask user to provide "target server's alias", where the target server is 
  16354.       that this server will signal when its timer "pops". Then get a proxy for 
  16355.       that server. 
  16356.  
  16357.             somPrintf("What is the alias for the target server? ");
  16358.             gets(inbuf);
  16359.             RemotePeer = _somdFindServerByName(SOMD_ObjectMgr, &ev, inbuf);
  16360.  
  16361.    o  Ask user to provide the timer's interval (in milliseconds) 
  16362.  
  16363.             somPrintf("What is the timer interval, in milliseconds? ");
  16364.             gets(inbuf);
  16365.             Interval = atoi(inbuf);
  16366.  
  16367.    o  Register a timer event with EMan, having EMan call back a procedure that 
  16368.       will invoke the notification method on the target server. 
  16369.  
  16370.             void TimerEventCallBack (SOMEEvent event, void *eventData)
  16371.             { Environment ev;
  16372.               SOM_InitEnvironment(&ev);
  16373.               /* call the peer, with a oneway message */
  16374.               _noteTimeout(RemotePeer, &ev, thisServer);
  16375.             }
  16376.  
  16377.             data = SOMEEMRegisterDataNew();
  16378.             _someClearRegData(data, &ev);
  16379.             _someSetRegDataEventMask(data, &ev, EMTimerEvent, NULL);
  16380.             _someSetRegDataTimerInterval(data, &ev, Interval);
  16381.             somPrintf("Type <Enter> key when ready to go: ");
  16382.             gets(inbuf);
  16383.             regId = _someRegisterProc(MyEMan, &ev, data, TimerEventCallBack,
  16384.                                        NULL);
  16385.  
  16386.       Important  Do not use someRegister or someRegisterEV to register 
  16387.                  "callback methods" that would be executed on proxy objects. 
  16388.                  Instead, write a callback routine that invokes the desired 
  16389.                  method on the proxy, like the one shown above, and register 
  16390.                  that routine using the method someRegisterProc. 
  16391.  
  16392.       Note:  EMan currently uses the methods someRegister and someRegisterEv to 
  16393.              obtain the address of a method-procedure to call when a specified 
  16394.              event occurs. If EMan directly calls the method-procedure versus 
  16395.              somDispatch, the method call will not be forwarded to the remote 
  16396.              object as desired. 
  16397.  
  16398.    o  Start the EMan event processing loop. 
  16399.  
  16400.             _someProcessEvents(MyEMan, &ev);
  16401.  
  16402.  Before the sample is run, two server implementations should be registered with 
  16403.  regimpl. The implementations are identical except for their aliases. One may 
  16404.  be called "peerServer1" and the other "peerServer2". The "PeerServer" class 
  16405.  should be specified as their server-object class. 
  16406.  
  16407.  Whenever peerServer1's timer pops, the Event Manager causes a method, 
  16408.  "noteTimeout", to be sent to the server object in peerServer2. PeerServer2's 
  16409.  server object executes this method by displaying a message on its window. 
  16410.  Whenever peerServer2's timer pops, a similar sequence occurs with peerServer1. 
  16411.  The two servers will run continuously until interrupted. 
  16412.  
  16413.  
  16414. ΓòÉΓòÉΓòÉ 8.9.2. Dynamic Invocation Interface ΓòÉΓòÉΓòÉ
  16415.  
  16416. DSOM supports the CORBA dynamic invocation interface (DII), which clients can 
  16417. use to dynamically build and invoke requests on objects. This section describes 
  16418. how to use the DSOM DII. Currently, DSOM supports dynamic request invocation 
  16419. only on objects outside the address space of the request initiator, via 
  16420. proxies. The somDispatch method (non-CORBA) can be used to invoke methods 
  16421. dynamically on either local or remote objects, however. 
  16422.  
  16423. To invoke a request on an object using the DII, the client must explicitly 
  16424. construct and initiate the request. A request is comprised of an object 
  16425. reference, an operation, a list of arguments for the operation, and a return 
  16426. value from the operation. A key to proper construction of the request is the 
  16427. correct usage of the NamedValue structure and the NVList object. The return 
  16428. value for an operation is supplied to the request in the form of a NamedValue 
  16429. structure. In addition, it is usually most convenient to supply the arguments 
  16430. for a request in the form of an NVList object, which is an ordered set of 
  16431. NamedValues. This section begins with a description of NamedValues and NVLists 
  16432. and then details the procedure for building and initiating requests. 
  16433. The NamedValue structure 
  16434.  
  16435. The NamedValue structure is defined in C as: 
  16436.  
  16437. typedef unsigned long Flags;
  16438.  
  16439. struct NamedValue {
  16440.         Identifier  name;         // argument name
  16441.         any         argument;     // argument
  16442.         long        len;          // length/count of arg value
  16443.         Flags       arg_modes;    // argument mode flags
  16444. };
  16445.  
  16446. where: name is an Identifier string as defined in the CORBA specification, and 
  16447. arg is an any structure with the following declaration: 
  16448.  
  16449.  
  16450.         struct any {
  16451.                 TypeCode        _type;
  16452.                 void*           _value;
  16453.         };
  16454.  
  16455. _type  is a TypeCode, which has an opaque representation with operations 
  16456. defined on it to allow access to its constituent parts. Essentially the 
  16457. Typecode is composed of a field specifying the CORBA type represented and 
  16458. possibly additional fields needed to fully describe the type. See Chapter 7 of 
  16459. this manual for a complete explanation of TypeCodes. 
  16460.  
  16461. _value  is a pointer to the value of the any structure. Important: The contents 
  16462. of "_value" should always be a pointer to the value, regardless of whether the 
  16463. value is a primitive, a structure, or is itself a pointer (as in the case of 
  16464. object references, strings and arrays). For object references, strings and 
  16465. arrays, _value should contain pointer to the pointer that references the value. 
  16466. For example: 
  16467.  
  16468.  
  16469.         string          testString;
  16470.         any             testAny;
  16471.  
  16472.         testAny._value = &testString;
  16473.  
  16474. len is the number of bytes that the argument value occupies. The following 
  16475. table gives the length of data values for the C language bindings. The value of 
  16476. len must be consistent with the TypeCode. 
  16477.  
  16478.  
  16479. Data type               Length
  16480. short                   sizeof(short)
  16481. unsigned short          sizeof(unsigned short)
  16482. long                    sizeof(long)
  16483. unsigned long           sizeof(unsigned long)
  16484. float                   sizeof(float)
  16485. double                  sizeof(double)
  16486. char                    sizeof(char)
  16487. boolean                 sizeof(boolean)
  16488. octet                   sizeof(octet)
  16489. string                  strlen(string) - does not include '\0' byte
  16490. enum E{}                sizeof(unsigned long)
  16491. union U                 sizeof(U)
  16492. struct S{}              sizeof(S)
  16493. Object                  1
  16494. array N of type T1      Length(T1)*N
  16495. sequence V of type T2   Length(T2)*V - V is the actual # of elements
  16496.  
  16497. The arg_modes field is a bitmask (unsigned long) and may contain the following 
  16498. flag values: 
  16499.  
  16500. ARG_IN              the associated value is an input-only argument
  16501. ARG_OUT             the associated value is an output-only argument
  16502. ARG_INOUT           the associated argument is an in/out argument
  16503.  
  16504. These flag values identify the parameter passing mode for the arguments. 
  16505. Additional flag values have specific meanings for Request and NVList methods 
  16506. and are listed with their associated methods. 
  16507. The NVList class 
  16508.  
  16509. An NVList contains an ordered set of NamedValues. The CORBA specification 
  16510. defines several operations that the NVList supports. The IDL prototypes for 
  16511. these methods are as follows: 
  16512.  
  16513.  
  16514. // get the number of elements in the NVList
  16515. ORBStatus get_count(
  16516.                 out  long count );
  16517.  
  16518. // add an element to an NVList
  16519. ORBStatus add_item(
  16520.                 in  Identifier      item_name,
  16521.                 in  TypeCode    item_type,
  16522.                 in  void* value,
  16523.                 in  Flags item_flags );
  16524.  
  16525. // frees the NVList and any associated memory
  16526. ORBStatus free();
  16527.  
  16528.  
  16529. // frees dynamically allocated memory associated with the list
  16530. ORBStatus free_memory();
  16531.  
  16532. In DSOM, the NVList is a full-fledged object with methods for getting and 
  16533. setting elements: 
  16534.  
  16535.  
  16536. //set the contents of an element in an NVList
  16537. ORBStatus set_item(
  16538.                 in  long            item_number, /* element # to set */
  16539.                 in  Identifier      item_name,
  16540.                 in  TypeCode        item_type,
  16541.                 in  void*           item_value,
  16542.                 in  long            value_len,
  16543.                 in  Flags           item_flags );
  16544.  
  16545.  
  16546. // get the contents of an element in an NVList
  16547. ORBStatus get_item(
  16548.                 in  long            item_number, /* element # to get */
  16549.                 out Identifier      item_name,
  16550.                 out TypeCode        item_type,
  16551.                 out void*           item_value,
  16552.                 out long            value_len,
  16553.                 out Flags           item_flags );
  16554.  
  16555.  
  16556. Creating argument lists 
  16557.  
  16558. A very important use of the NVList is to pass the argument list for an 
  16559. operation when creating a request. CORBA 1.1 specifies two methods, defined in 
  16560. the ORB class, to build an argument list: create_list and 
  16561. create_operation_list. The IDL prototypes for these methods are as follows: 
  16562.  
  16563. ORBStatus create_list(
  16564.                         in  long        count,        /* # of items */
  16565.                         out NVList      new_list );
  16566.  
  16567. ORBStatus create_operation_list(
  16568.                         in  OperationDef oper,
  16569.                         out NVList       new_list );
  16570.  
  16571. The create_list method returns an NVList with the specified number of elements. 
  16572. Each of the elements is empty. It is the client's responsibility to fill the 
  16573. elements in the list with the correct information using the set_item method. 
  16574. Elements in the NVList must contain the arguments in the same order as they 
  16575. were defined for the operation. Elements are numbered from 0 to count-1. 
  16576.  
  16577. The create_operation_list method returns an NVList initialized with the 
  16578. argument descriptions for a given operation (specified by the OperationDef). 
  16579. The arguments are returned in the same order as they were defined for the 
  16580. operation. The client only needs to fill in the item_value and value_len in the 
  16581. elemens of the NVList. 
  16582.  
  16583. In addition to these CORBA-defined methods, DSOM provides a third version, 
  16584. defined in the SOMDObject class. The IDL prototype for this method is as 
  16585. follows: 
  16586.  
  16587.  
  16588. ORBStatus create_request_args(
  16589.                         in Identifier operation,
  16590.                         out NVList arg_list,
  16591.                         out NamedValue result );
  16592.  
  16593. Like create_operation_list, the create_request_args method creates the 
  16594. appropriate NVList for the specified operation.  In addition, 
  16595. create_request_args initializes the NamedValue that will hold the result with 
  16596. the expected return type. The create_request_args method is defined as a 
  16597. companion to the create_request method, and has the advantage that the 
  16598. InterfaceDef for the operation does not have to be retrieved from the Interface 
  16599. Repository. 
  16600.  
  16601. Note:  The create_request_args method is not  defined in CORBA 1.1. Hence, the 
  16602.        create_operation_list method, defined on the ORB class, should be used 
  16603.        instead when writing portable CORBA-compliant programs. 
  16604.  
  16605.  
  16606.  Building a Request 
  16607.  
  16608.  There are two ways to build a Request object. Both begin by calling the 
  16609.  create_request method defined by the SOMDObject class. The IDL prototype for 
  16610.  create_request is as follows: 
  16611.  
  16612.   ORBStatus create_request(
  16613.                   in  Context            ctx,
  16614.                   in  Identifier         operation,
  16615.                   in  NVList             arg_list,
  16616.                   inout NamedValue       result,
  16617.                   out Request            request,
  16618.                   in  Flags              req_flags );
  16619.  
  16620.  The arg_list can be constructed using the procedures described above and is 
  16621.  passed to the Request object in the create_request call. Alternatively, 
  16622.  arg_list can be specified as NULL and repetitive calls to add_arg  can be used 
  16623.  to specify the argument list. The add_arg method, defined by the Request 
  16624.  class, has the following IDL prototype: 
  16625.  
  16626.   ORBStatus add_arg(
  16627.                   in  Identifier  name,
  16628.                   in  TypeCode    arg_type,
  16629.                   in  void*       value,
  16630.                   in  long        len,
  16631.                   in  Flags       arg_flags );
  16632.  
  16633.  
  16634.  Initiating a Request 
  16635.  
  16636.  There are two ways to initiate a request, using either the invoke or send 
  16637.  method defined by the Request class. The IDL prototypes for these two 
  16638.  operations ar as follows: 
  16639.  
  16640.  
  16641.   ORBStatus invoke(
  16642.                   in Flags        invoke_flags );
  16643.  
  16644.   ORBStatus send(
  16645.                   in Flags        send_flags );
  16646.  
  16647.  The invoke method calls the ORB, which handles the remote method invocation 
  16648.  and returns the result. This method will block while awaiting return of the 
  16649.  result. 
  16650.  
  16651.  The send method calls the ORB but does not wait for the operation to complete 
  16652.  before returning. To determine when the operation is complete, the client must 
  16653.  call the get_response method (also defined by the Request class), which has 
  16654.  this IDL prototype: 
  16655.  
  16656.  
  16657.   ORBStatus get_response(
  16658.                   in Flags        response_flags );
  16659.  
  16660.  The following flag is defined for get_response:  RESP_NO_WAIT       Means that 
  16661.  the caller does not want to wait for a                  response. 
  16662.  
  16663.  get_response determines whether a request has competed. If the RESP_NO_WAIT 
  16664.  flag is set, get_response returns immediately even if the request is still in 
  16665.  progress. If RESP_NO_WAIT is not set, get_response waits until the request is 
  16666.  done before returning. 
  16667.  Example code 
  16668.  
  16669.  Following is an incomplete example showing how to use the DII to invoke a 
  16670.  request having the method procedure prototype shown here: 
  16671.  
  16672.  
  16673.   string _testMethod( testObject              obj,
  16674.                       Environment             *ev,
  16675.                       long                    input_value,
  16676.   );
  16677.  
  16678.   main()
  16679.   {
  16680.      ORBStatus rc;
  16681.      Environment ev;
  16682.      SOMDObject obj;
  16683.      NVList arglist;
  16684.      NamedValue result;
  16685.      Context ctx;
  16686.      Request reqObj;
  16687.      OperationDef opdef;
  16688.      Description desc;
  16689.      OperationDescription opdesc;
  16690.      static long input_value = 999;
  16691.  
  16692.      SOM_InitEnvironment(&ev);
  16693.      SOMD_Init(&ev);
  16694.  
  16695.   /* create the argument list */
  16696.   /* get the operation description from the interface repository */
  16697.      opdef = _lookup_id(SOM_InterfaceRepository, *ev,
  16698.                     "testObject::testMethod");
  16699.      desc = _describe(opdef, &ev);
  16700.      opdesc = (OperationDescription *) desc.value._value;
  16701.  
  16702.   /* fill in the TypeCode field for the result */
  16703.      result.argument._type = opdesc->result;
  16704.  
  16705.   /* Initialize the argument list */
  16706.      rc = _create_operation_list(SOMD_ORBObject, &ev, opdef,
  16707.                                  &arglist);
  16708.  
  16709.   /* get default context */
  16710.      rc = _get_default_context(SOMD_ORBObject, &ev, &ctx);
  16711.  
  16712.   /* put value and length into the NVList */
  16713.      _get_item(arglist, &ev, 0, &name, &tc, &dummy, &dummylen,
  16714.                &flags);
  16715.  
  16716.      _set_item(arglist, &ev, 0, name, tc, &input_value,
  16717.                sizeof(input_value),flags);
  16718.       ...
  16719.   /* create the request - assume the object reference came from
  16720.      somewhere -- from a file or returned by a previous request*/
  16721.      rc = _create_request(obj, &ev, ctx,
  16722.                           "testMethod", arglist, &result, &reqObj,
  16723.                           (Flags)0);
  16724.  
  16725.   /* invoke request */
  16726.      rc = invoke(reqObj, &ev, (Flags)0);
  16727.  
  16728.   /* print result */
  16729.      printf("result: %s\n",*(string*)(result.argument._value));
  16730.      return(0);
  16731.   }
  16732.  
  16733.  
  16734. ΓòÉΓòÉΓòÉ 8.9.3. Creating user-supplied proxies ΓòÉΓòÉΓòÉ
  16735.  
  16736. DSOM uses a proxy object in the client's address space to represent the remote 
  16737. object. As mentioned earlier in this chapter, the proxy object encapsulates the 
  16738. operations necessary to forward and invoke methods on the remote object and 
  16739. return the results. By default, proxy generation is done automatically by the 
  16740. DSOM run time. However, if desired, the programmer can cause a user-supplied 
  16741. proxy class to be loaded instead of letting the run time dynamically generate a 
  16742. default proxy class. User-supplied proxies can be useful in specialized 
  16743. circumstances when local processing or data caching is desired. 
  16744.  
  16745. To build a user-supplied proxy class, it is necessary to understand a bit about 
  16746. how dynamic proxy classes are constructed by the DSOM run time. The DSOM run 
  16747. time constructs a proxy class by creating an instance of a class that inherits 
  16748. the interface and implementation of SOMDClientProxy, and the interface (but not 
  16749. the implementation) of the target class. The methods in the interface of the 
  16750. target object are all overridden to call the somDispatch method (For more 
  16751. details, see "Object references and proxy objects" in section 6.8.) 
  16752.  
  16753. Every SOM object contains the somDispatch method, inherited from SOMObject. 
  16754. This method is used to dynamically dispatch a method on an object, and can be 
  16755. overridden with application-specific dispatching mechanisms. In 
  16756. SOMDClientProxy, the somDispatch method is overridden to forward method calls 
  16757. to the corresponding remote target object. 
  16758.  
  16759. So, in effect, when a method is called on a default proxy object created by the 
  16760. DSOM run time, it redispatches the method to the remote object using DSOM's 
  16761. version of somDispatch. 
  16762.  
  16763. Below is a simple example of a user-supplied proxy class. In this particular 
  16764. example, the proxy object maintains a local, unshared copy of an attribute 
  16765. ("attribute_long") defined in the remote object ("Foo"), while forwarding 
  16766. method invocations ("method1") on to the remote object. The result is that, 
  16767. when multiple clients are talking to the same remote "Foo" object, each client 
  16768. has a local copy of the attribute but all clients share the "Foo" object's 
  16769. implementation of "method1". 
  16770.  
  16771. Note:  It is important to understand that simply setting the attribute in one 
  16772.        client's proxy does not affect the value of the attribute in other 
  16773.        proxies. Maintaining consistency of the cached data values, if desired, 
  16774.        is the responsibility of the user-supplied proxy class. 
  16775.  
  16776.  Following is the IDL file for the "Foo" class: 
  16777.  
  16778.  
  16779.   // foo.idl
  16780.  
  16781.  
  16782.   #include <somdtype.idl>
  16783.   #include <somobj.idl>
  16784.  
  16785.  
  16786.   interface Foo : SOMObject
  16787.   {
  16788.           string  method1(out string a, inout long b,
  16789.                           in ReferenceData c);
  16790.           attribute long attribute_long;
  16791.  
  16792.  
  16793.     implementation
  16794.     {
  16795.        releaseorder: method1, _set_attribute_long,
  16796.                      _get_attribute_long;
  16797.        dllname="foo.dll";
  16798.        somDefaultInit: override;
  16799.     };
  16800.   };
  16801.  
  16802.  The user-supplied proxy class is created by using multiple inheritance between 
  16803.  SOMDClientProxy and the target object (in this case "Foo"). Thus, the IDL file 
  16804.  for the user-supplied proxy class "Foo__Proxy" (note the two underscores) is 
  16805.  as follows: 
  16806.  
  16807.  
  16808.   // fooproxy.idl
  16809.  
  16810.  
  16811.   #include <somdcprx.idl>
  16812.   #include <foo.idl>
  16813.  
  16814.  
  16815.   interface Foo__Proxy : SOMDClientProxy, Foo
  16816.   {
  16817.     implementation
  16818.     {
  16819.        dllname="fooproxy.dll";
  16820.        method1: override;
  16821.     };
  16822.   };
  16823.  
  16824.  When a dynamic proxy class is created by the DSOM run time, the methods 
  16825.  inherited from the target class are automatically overridden to use 
  16826.  somDispatch. When you build a user-supplied proxy, you need to do this 
  16827.  explicitly. This is why "method1" is overridden in the implementation section 
  16828.  of the "fooproxy.idl" file. 
  16829.  
  16830.  The implementation of "method1", which was added to the template produced by 
  16831.  the SOM Compiler, simply calls the somDispatch method on "somSelf" Because 
  16832.  "Foo__Proxy" has inherited the implementation of SOMDClientProxy, calling 
  16833.  somDispatch within "method1" sends the method to the remote "Foo" object. 
  16834.  
  16835.   /* foo.c */
  16836.  
  16837.   #include <somdtype.h>
  16838.   #include <fooproxy.ih>
  16839.  
  16840.   SOM_Scope string  SOMLINK method1(Foo__Proxy somSelf,
  16841.                                     Environment *ev,
  16842.                                     string* a, long* b,
  16843.                                     ReferenceData* c)
  16844.   {
  16845.       string ret_str;
  16846.       somId  methodId;
  16847.  
  16848.  
  16849.   /*  Foo__ProxyData *somThis = Foo__ProxyGetData(somSelf); */
  16850.       Foo__ProxyMethodDebug("Foo__Proxy","method1");
  16851.  
  16852.  
  16853.       /* redispatch method, remotely */
  16854.       methodId = somIdFromString("method1");
  16855.       _somDispatch(somSelf, (void**)&ret_str,
  16856.                    methodId, somSelf, ev, a, b, c);
  16857.       SOMFree(methodId);
  16858.  
  16859.  
  16860.       return ret_str;
  16861.   }
  16862.  
  16863.  In summary, to build a user-supplied proxy class: 
  16864.  
  16865.    o  Create the .idl file with the proxy class inheriting from both 
  16866.       SOMDClientProxy and from the target class. Important: The user-supplied 
  16867.       proxy class must be named "<targetClassName>_ _Proxy" (with two 
  16868.       underscores in the name) and SOMDClientProxy must be the first class in 
  16869.       the list of parent classes; for example, 
  16870.  
  16871.  
  16872.                     interface Foo_ _Proxy : SOMDClientProxy, Foo
  16873.  
  16874.       Putting SOMDClientProxy first ensures that its version of somDispatch 
  16875.       will be used to dispatch remote method calls. 
  16876.  
  16877.       In the implementation section of the .idl file, override all methods that 
  16878.       are to be invoked on the target class. Do not override methods that are 
  16879.       to be invoked on the local proxy. 
  16880.  
  16881.    o  Compile the .idl file. Be sure the Interface Repository gets updated with 
  16882.       the .idl file. In the implementation file, for each overridden method, 
  16883.       call somDispatch with the method name and parameters passed into the 
  16884.       overridden method. If the proxy class provides an implementation for the 
  16885.       somInit or somDefaultInit method, then it is important to ensure that 
  16886.       calling that method more than once on the same proxy object has no 
  16887.       negative effect. 
  16888.  
  16889.    o  Build the DLL and place it the LIBPATH for AIX and OS/2, or listed in 
  16890.       PATH for Windows. Before creating the default proxy, the DSOM run time 
  16891.       checks the LIBPATH for a DLL containing the class named 
  16892.       "<targetClassName>_ _Proxy" If such a DLL is found, DSOM loads it instead 
  16893.       of dynamically generating a proxy class. 
  16894.  
  16895.  
  16896. ΓòÉΓòÉΓòÉ 8.9.4. Customizing the default base proxy class ΓòÉΓòÉΓòÉ
  16897.  
  16898. Continuing the example from the previous topic, imagine that an application 
  16899. derives 100 subclasses from the "Foo" class. If the application wishes to cache 
  16900. the "Foo::attribute_long" attribute in the proxies for all remote Foo-based 
  16901. objects, the application could supply 100 user-supplied proxy classes, 
  16902. developed in the manner described above. However, this would become a very 
  16903. tedious and repetitive task! 
  16904.  
  16905. Alternatively, it is possible to provide a customized base proxy class for use 
  16906. in the dynamic generation of DSOM proxy classes. This allows an application to 
  16907. provide a customized base proxy class, from which other dynamic DSOM proxy 
  16908. classes can be derived. This is particularly useful in situations where an 
  16909. application would like to enhance many or all dynamically generated proxy 
  16910. classes with a common feature. 
  16911.  
  16912. As described in the previous topic, proxy classes are derived from the 
  16913. SOMDClientProxy class by default. It is the SOMDClientProxy class that 
  16914. overrides somDispatch in order to forward method calls to remote objects. 
  16915.  
  16916. The SOMDClientProxy class can be customized by deriving a subclass in the usual 
  16917. way (being careful not to replace somDispatch or other methods that are 
  16918. fundamental to implementing the proxy's behavior). To extend the above example 
  16919. further, the application might define a base proxy class called "MyClientProxy" 
  16920. that defines a long attribute called "attribute_long," which will be inherited 
  16921. by Foo-based proxy classes. 
  16922.  
  16923. The SOM IDL modifier baseproxyclass can be used to specify which base proxy 
  16924. class DSOM should use during dynamic proxy-class generation. To continue the 
  16925. example, if the class "MyClientProxy" were used to construct the proxy class 
  16926. for a class "XYZ," then the baseproxyclass modifier would be specified s 
  16927. follows: 
  16928.  
  16929. // xyz.idl
  16930.  
  16931. #include <somdtype.idl>
  16932. #include <foo.idl>
  16933.  
  16934. interface XYZ : Foo
  16935. {
  16936.   ...
  16937.   implementation
  16938.   {
  16939.      ...
  16940.      baseproxyclass = MyClientProxy;
  16941.   };
  16942. };
  16943.  
  16944. It should be noted that: 
  16945.  
  16946.    o  Base proxy classes must be derived from SOMDClientProxy. 
  16947.  
  16948.    o  If a class "XYZ" specifies a custom base-proxy class, as in the above 
  16949.       example, subclasses of "XYZ" do not  inherit the value of the 
  16950.       baseproxyclass modifier. If needed, the  baseproxyclass modifier must be 
  16951.       specified explicitly in each class. 
  16952.  
  16953.  
  16954. ΓòÉΓòÉΓòÉ 8.9.5. Sockets class ΓòÉΓòÉΓòÉ
  16955.  
  16956. To aid in portability, DSOM has been written to use a common communications 
  16957. interface, which is implemented by one or more available local protocols. 
  16958.  
  16959. The common communications interface is represented as an abstract class, called 
  16960. Sockets, and is based on the familiar "sockets" interface. Several protocol 
  16961. implementations are supported as Sockets subclasses: TCPIPSockets (and 
  16962. TCPIPSockets32 for OS/2) for TCP/IP, the class NBSockets for Netbios, and the 
  16963. class IPXSockets for Netware IPX/SPX. (The libraries included in a particular 
  16964. SOMobjects run-time package will vary.) 
  16965.  
  16966. There is one case where a Sockets subclass is not required: the DSOM 
  16967. Workstation run-time package uses shared memory to pass messages within a 
  16968. single machine, and bypasses the use of a Sockets subclass. (The SOMSOCKETS 
  16969. environment variable is ignored.) 
  16970.  
  16971. When the Event Management Framework (EMan) is used with DSOM, a Sockets 
  16972. subclass will be needed to support EMan, whether or not the application runs 
  16973. completely within a single machine. 
  16974.  
  16975. Appendix C, "Implementing Sockets Subclasses," describes how an application 
  16976. might provide its own Sockets subclass implementation, for special 
  16977. circumstances. 
  16978.  
  16979.  
  16980. ΓòÉΓòÉΓòÉ 8.10. Error Reporting and Troubleshooting ΓòÉΓòÉΓòÉ
  16981.  
  16982. When the DSOM run-time environment encounters an error during execution of a 
  16983. method or procedure, a SYSTEM_EXCEPTION will be raised. The standard system 
  16984. exceptions are discussed in the topic "Exceptions and Error Handling" in 
  16985. Chapter 3 "Using SOM Classes in Client Programs." The "minor" field of the 
  16986. returned exception value will contain a DSOM error code. The DSOM error codes 
  16987. are listed below. 
  16988.  
  16989. Although a returned exception value can indicate that a DSOM run-time error 
  16990. occurred, it may be difficult for the user or application to determine what 
  16991. caused the error. Consequently, DSOM has been enabled to report run-time error 
  16992. information, for interpretation by IBM support personnel. These error messages 
  16993. take the following form: 
  16994.  
  16995.  
  16996. DSOM <type> error:  <code> [<name>] at  <file>:<line>
  16997.  
  16998. where the arguments are as follows: 
  16999.  
  17000.  
  17001. type    SYSTEM_EXCEPTION type,
  17002. code    DSOM error code,
  17003. name    symbol for DSOM error code (from "somderr.h"),
  17004. file    source-file name where the error occurred, and
  17005. line    line number where the error occurred.
  17006.  
  17007. For example, 
  17008.  
  17009.  
  17010. DSOM NO_MEMORY error: 30001 [SOMDERROR_NoMemory] at somdobj.c:250
  17011.  
  17012. indicates that a "NO_MEMORY" error (error code 30001) occurred in file 
  17013. "somdobj.c" at line 250. This information is not usually meaningful to the 
  17014. user; it provides IBM support personnel with a starting point for problem 
  17015. analysis. There will often be a sequence of error messages; together they 
  17016. indicate the context in which the error occurred. It is important to give all 
  17017. reported messages to IBM support personnel for analysis. 
  17018.  
  17019. There is an environment variable, SOMDDEBUG, which is used to activate error 
  17020. reporting. There is a corresponding global variable that can be set by an 
  17021. application program; it is declared as: 
  17022.  
  17023. extern long SOMD_DebugFlag;
  17024.  
  17025. Error reporting is normally disabled. To enable error reporting, the 
  17026. environment variable SOMDDEBUG should be set to a value greater than 0. To 
  17027. disable error reporting, SOMDDEBUG should be set to a value less than or equal 
  17028. to 0. 
  17029.  
  17030. By default, error messages will display on the standard output device. Error 
  17031. messages can also be redirected to a log file. For this, the environment 
  17032. variable SOMDMESSAGELOG should be set to the pathname of the log file. The 
  17033. SOMD_ Init procedure opens the file named in SOMDMESSAGELG (if any), during 
  17034. process initialization. 
  17035. Error codes 
  17036.  
  17037. The error codes that may be encountered when using DSOM are listed in Appendix 
  17038. A, "SOMobjects Error Codes," which contains the codes for the entire SOMobjects 
  17039. Toolkit. 
  17040.  
  17041.  
  17042. ΓòÉΓòÉΓòÉ 8.10.1. Troubleshooting hints ΓòÉΓòÉΓòÉ
  17043.  
  17044. The following hints may prove helpful as you develop and test your DSOM 
  17045. application. 
  17046. Checking the DSOM setup 
  17047.  
  17048. This checklist will help you make certain that the DSOM environment is set up 
  17049. correctly. 
  17050.  
  17051.    1. Use the somdchk tool to verify the settings of various DSOM environment 
  17052.       variables.  Note that if the SOMIR environment variable contains relative 
  17053.       pathnames, the client programs, server programs, and somdd daemon must be 
  17054.       started from the same directory. (Instead, it is recommended that SOMIR 
  17055.       contain full pathnames.) 
  17056.  
  17057.    2. For all application classes, IDL must be compiled into the Interface 
  17058.       Repository.  You can verify that a class exists in the Interface 
  17059.       Repository by executing "irdump<class>" on AIX or OS/2, or, on Windows, 
  17060.       click on the IRDUMP icon and browse for the appropriate class.  See 
  17061.       "Registering class interfaces" for more information. 
  17062.  
  17063.    3. An implementation (a server program and class libraries) must be 
  17064.       registered with DSOM by running the regimpl utility. See "Registering 
  17065.       servers and classes" for more information. 
  17066.  
  17067.    4. Verify that all class libraries and networking libraries are in 
  17068.       directories specified in LIBPATH. 
  17069.  
  17070.  Analyzing problem conditions 
  17071.  
  17072.  The DSOM error codes mentioned below can be obtained directly by the 
  17073.  application from the "minor" field of the exception data returned in a system 
  17074.  exception, or from an error report message when SOMDDEBUG is set to a positive 
  17075.  integer value (see the previous topic, "Error reporting"). 
  17076.  
  17077.  Symptom:  When running regimpl, a "PERSIST_STORE" or "NO_IMPLEMENT" exception 
  17078.  is returned. The DSOM error code is SOMDERROR_IO or SOMDERROR_NoImplDatabase. 
  17079.  
  17080.    o  This may indicate that the Implementation Repository files are not found 
  17081.       or cannot be accessed. Verify that SOMDDIR is set correctly, to a 
  17082.       directory that has granted read/write permission to the DSOM user. (It is 
  17083.       best if the directory name is fully qualified.) If the SOMDDIR variable 
  17084.       is not set, verify that the default directory ($SOMBASE/etc/dsom on AIX, 
  17085.       and %SOMBASE%\etc\dsom on OS/2 or Windows) has been set up with the 
  17086.       correct permissions. Ensure that the the files contained in the directory 
  17087.       all have read/write permission granted to the DSOM user. 
  17088.  
  17089.  Symptom:  When starting somdd, an "INITIALIZE" exception is returned with 
  17090.  error code SOMDAlreadyRunning. 
  17091.  
  17092.    o  This indicates that there is already an instance of somdd running.  If 
  17093.       the current instance of somdd does not seem to be responding properly, 
  17094.       delete all instances of somdd and restart a new copy of somdd. 
  17095.  
  17096.  Symptom:  When starting up a server program, an exception is returned with a 
  17097.  DSOM error code of SOMDERROR_ServerAlreadyExists. 
  17098.  
  17099.    o  This may indicate that a server process that is already running has 
  17100.       already registered itself with the DSOM daemon, somdd, using the 
  17101.       implementation ID of the desired server program. 
  17102.  
  17103.  Symptom: On OS/2, an operating system error occurs indicating a "stack 
  17104.  overflow" condition soon after a the first call to a class DLL. Rebuilding the 
  17105.  DLL with a larger stack size does not help. 
  17106.  
  17107.    o  This sometimes occurs when a DLL uses, but does not initialize, the  run 
  17108.       time for OS/2. To perform the proper initialization, a function named 
  17109.       "_DLL_InitTerm" must be included in the DLL, and it must invoke the C 
  17110.       Set/2 initialization function, "_CRT_Init."  The _DLL_InitTerm function 
  17111.       is invoked automatically when the DLL is loaded. 
  17112.  
  17113.       An example _DLL_InitTerm function is included in the DSOM sample code 
  17114.       shipped with the SOMobjects Developer Toolkit for OS/2, in the file 
  17115.       "initterm.c". 
  17116.  
  17117.  Symptom: When running a DSOM application that uses EMan, an error message is 
  17118.  displayed asking that the SOMSOCKETS be set. 
  17119.  
  17120.    o  This may indicate a need to specify the Sockets subclass to be used with 
  17121.       the application. Current choices are TCPIPSockets for TCP/IP (and 
  17122.       TCPIPSockets32 on OS/2), NBSockets for NetBios and IPXSockets for Netware 
  17123.       IPX/SPX. Note:Each SOMobjects package will contain an appropriate subset 
  17124.       of Sockets subclasses. Workstation DSOM includes TCPIPSockets (and 
  17125.       TCPIPSockets32 onOS/2 ) for TCP/IP. Workgroup DSOM also includes 
  17126.       NBSockets for NetBios and IPXSockets for Netware. 
  17127.  
  17128.  Symptom:  A remote method invocation fails and an "INTF_REPOS" exception is 
  17129.  returned. The DSOM error code is SOMDERROR_BadDescriptor or 
  17130.  SOMDERROR_ClassNotlnIR. 
  17131.  
  17132.    o  This may indicate that the interface describing the method or the method 
  17133.       itself cannot be found in the Interface Repository. Verify that SOMIR is 
  17134.       set correctly, and that the IR contains all interfaces used by your 
  17135.       application. 
  17136.  
  17137.       If the default SOM IR (supplied with the SOMobjects Toolkit and Runtimes) 
  17138.       is not used by the application, the user's IR must include the interface 
  17139.       definitions for the appropriate Sockets class, server class (derived from 
  17140.       SOMDServer), and the definitions of the standard DSOM exceptions (found 
  17141.       in file "stexcep.idl") that may be returned by a method call. 
  17142.  
  17143.  Symptom:  A SOMDERROR_ClassNotFound error is returned by a client either when 
  17144.  creating a remote object using somdNewObject, or when finding a server object 
  17145.  using somdFindAnyServerByClass. (The methods are defined on the SOMDObjectMgr 
  17146.  class.) 
  17147.  
  17148.    o  This occurs when the class name specified in calls to somdNewObject or 
  17149.       somdFindAnyServerByClass cannot be found in the Implementation 
  17150.       Repository. Make sure that the class name has been associated with at 
  17151.       least one of the server implementations. 
  17152.  
  17153.  Symptom:  A SOMDERROR_ClassNotlnlR error is returned by a server when creating 
  17154.  a new object using somdNewObject, somdCreateObj, or somdGetClassObj. 
  17155.  
  17156.    o  This error may result if the DLL for the class cannot be found. Verify 
  17157.       hat: 
  17158.  
  17159.            --the interface of the object can be found in the IR; 
  17160.  
  17161.            --the class name is spelled correctly and is appropriately scoped 
  17162.            (for example, the "Printer" class in the "PrintServer" module must 
  17163.            have the identifier "PrintServer:: Printer"). 
  17164.  
  17165.    o  This error can also result when the shared library is statically linked 
  17166.       to the server program, but the <className>NewClass procedures have not 
  17167.       been called to initialize the classes. 
  17168.  
  17169.  Symptom: When invoking a method returns a proxy for a remote object in the 
  17170.  client, a SOMDERROR_NoParentClass error occurs. 
  17171.  
  17172.    o  This error may result when the class libraries used to build the proxy 
  17173.       class are statically linked to the program, but the <className>NewClass 
  17174.       procedure have not been called to initialize the classes. 
  17175.  
  17176.  Symptom:  Following a method call, the SOM run-time error message, "A target 
  17177.  object failed basic validity checks during method resolution" is displayed. 
  17178.  
  17179.    o  Usually this means that the method call was invoked using a bad object 
  17180.       pointer, or the object has been corrupted. 
  17181.  
  17182.  Symptom:  A remote object has an attribute or instance variable that is, or 
  17183.  contains, a pointer to a value in memory (for example, a string, a sequence, 
  17184.  an "any"). The attribute or instance variable value is set by the client with 
  17185.  one method call. When the attribute or instance variable is queried in a 
  17186.  subsequent method call, the value referenced by the pointer is "garbage". 
  17187.  
  17188.    o  This may occur because DSOM makes a copy  of argument values in a client 
  17189.       call, for use in the remote call. The argument values are valid for the 
  17190.       duration of that call. When the remote call is completed, the copies of 
  17191.       the argument values are freed. 
  17192.  
  17193.       In a DSOM application, a class should not assume ownership of memory 
  17194.       passed to it in a method parameter unless the IDL description of the 
  17195.       method includes the SOM IDL modifier object_owns_parameters.  Otherwise, 
  17196.       if a parameter value is meant to persist between method invocations, then 
  17197.       the object is responsible for making a copy of the parameter value. 
  17198.  
  17199.  Symptom:  A method defines a (char *) parameter that is used to pass a string 
  17200.  input value to an object. The object attempts to print the string value, but 
  17201.  it appears to be "garbage". 
  17202.  
  17203.    o  DSOM will support method arguments that are of type "pointer-to-X" 
  17204.       (pointer types are a SOM extension), by dereference the pointer in the 
  17205.       call, and copying the base value. The pointer-to-value is reconstructed 
  17206.       on the server before the actual method call is made. 
  17207.  
  17208.       While (char *) is commonly used to refer to NULL-terminated strings in C 
  17209.       programs, (char *) could also be a pointer to a single character or to an 
  17210.       array of characters. Thus, DSOM interprets the argument type literally as 
  17211.       a pointer-to-one-character. 
  17212.  
  17213.       To correctly pass strings or array arguments, the appropriate CORBA type 
  17214.       should be used (for example, "string" or "char foo[4 ]"). 
  17215.  
  17216.  Symptom:  A segmentation violation occurs when passing an "any" argument to a 
  17217.  method call, where the "any" value is a string, array, or object reference. 
  17218.  Note: The NamedValues used in DII calls use "any" fields for the argument 
  17219.  values. 
  17220.  
  17221.    o  This error may occur because the  "_value"  field of the "any" structure 
  17222.       does not contain the address of a pointer to the target string, array, or 
  17223.       object reference, as it should. (A common mistake is to set the "_value" 
  17224.       field to the address of the string, array, or object reference itself.) 
  17225.  
  17226.  Symptom:  When a server program or a server object makes a call to get_id or 
  17227.  to get_SOM_object on a SOMDObject, a "BAD_OPERATION" exception is returned 
  17228.  with an error code of SOMDERROR_WrongRefType. 
  17229.  
  17230.    o  This error may occur when the operation get_id is called on a SOMDObject 
  17231.       that does not have any user-supplied ReferenceData (that is, the 
  17232.       SOMDObject is a proxy, is nil, or is a simple "SOM ref" created by 
  17233.       create_SOM_ref). Likewise, this error may occur when the operation 
  17234.       get_SOM_object is called on a SOMDObject that was not created by the 
  17235.       create_SOM_ref method. 
  17236.  
  17237.  Symptom:  A segmentation fault occurs when a SOMD_Uninit call is executed. 
  17238.  
  17239.    o  This error could occur if the application has already freed any of the 
  17240.       DSOM run-time objects that were allocated by the SOMD_Init call, 
  17241.       including SOMD_ObjectMgr, SOMD_ImplRepObject and SOMD_ORBObject. 
  17242.  
  17243.  Symptom:  Unexplained program crashes. 
  17244.  
  17245.    o  Verify that all DSOM environment variables are set, as described in the 
  17246.       earlier section "Configuring DSOM Applications". Verify that all class 
  17247.       libraries are in directories specified in LIBPATH for AIX and OS/2, or 
  17248.       specified in PATH for Windows. Verify that the contents of the Interface 
  17249.       Repository, specified by SOMIR, are correct. Verify that the contents of 
  17250.       the Implementation Repository, specified by SOMDDIR, are correct. Verify 
  17251.       that somdd is running. Set SOMDDEBUG to 1 to obtain additional DSOM error 
  17252.       messages. 
  17253.  
  17254.  Symptom:  When starting somdd, an "INITIALIZE" error is returned with error 
  17255.  code SOMDERROR_NoSocketsClass. 
  17256.  
  17257.    o  If SOMSOCKETS is set, verify that the IR contains the appropriate Sockets 
  17258.       interface definition. 
  17259.  
  17260.  
  17261. ΓòÉΓòÉΓòÉ 8.11. Limitations ΓòÉΓòÉΓòÉ
  17262.  
  17263. The following list indicates known limitations of Distributed SOM at the time 
  17264. of this release. 
  17265.  
  17266.    1. Currently, objects cannot be moved from one server to another without 
  17267.       changing the object references (i.e., deleting the object, and creating 
  17268.       it anew in another server). This yields all copies of the previous 
  17269.       reference invalid. 
  17270.  
  17271.    2. The change_implementation method is not supported. This method, defined 
  17272.       by the BOA interface, is intended to allow an application to change the 
  17273.       implementation definition associated with an object. However, in DSOM, 
  17274.       changing the server implementation definition may render existing object 
  17275.       references (which contain the old server ID) invalid. 
  17276.  
  17277.    3. Currently, DSOM has a single server activation policy, which corresponds 
  17278.       to CORBA's "shared" activation policy for dynamic activation, and 
  17279.       "persistent" activation policy for manual activation. Other activation 
  17280.       policies, such as "server-per-method" and "unshared" are not directly 
  17281.       supported, and must be implemented by the application. 
  17282.  
  17283.       Since the unshared server policy is not directly supported, the 
  17284.       object_is_ready and deactivate_obj methods, defined in the BOA interface 
  17285.       have null implementations. 
  17286.  
  17287.    4. If a server program terminates without calling deactivate_impl, 
  17288.       subsequent attempts to start that server may fail. The DSOM daemon 
  17289.       believes the server is still running until it is told it has stopped. 
  17290.       Attempts to start a server that is believed to be exist results in an 
  17291.       error (SOMDERROR_ServerAlreadyExists). 
  17292.  
  17293.    5. Currently, file names used in ImplementationDefs are limited to 255 
  17294.       bytes. Implementations aliases used in ImplementationDefs are limited to 
  17295.       50 bytes. Class names used in the Implementation Repository are limited 
  17296.       to 50 bytes. Hostnames are limited to 32 bytes. 
  17297.  
  17298.    6. The OUT_LIST_MEMORY, IN_COPY_VALUE, and DEPENDENT_LIST flags, used with 
  17299.       Dynamic Invocation Interface, are not yet supported. 
  17300.  
  17301.    7. The Context::get_values method currently does not support the flag 
  17302.       CTX_restrict_SCOPE. 
  17303.  
  17304.  Other important notes concerning DSOM are documented in the "README" file in 
  17305.  the SOMBASE root directory ($SOMBASE on AIX, and %SOMBASE% on OS/2 or 
  17306.  Windows). 
  17307.  
  17308.  
  17309. ΓòÉΓòÉΓòÉ 9. The SOM Interface Repository Framework ΓòÉΓòÉΓòÉ
  17310.  
  17311.  
  17312. ΓòÉΓòÉΓòÉ 9.1. Introduction ΓòÉΓòÉΓòÉ
  17313.  
  17314. The SOM Interface Repository (IR) is a database that the SOM Compiler 
  17315. optionally creates and maintains from the information supplied in IDL source 
  17316. files. The Interface Repository contains persistent objects that correspond to 
  17317. the major elements in IDL descriptions. The SOM Interface Repository Framework 
  17318. is a set of classes that provide methods whereby executing programs can access 
  17319. these objects to discover everything known about the programming interfaces of 
  17320. SOM classes. 
  17321.  
  17322. The programming interfaces used to interact with Interface Repository objects, 
  17323. as well as the format and contents of the information they return, are 
  17324. architected and defined as part of the Object Management Group's CORBA 
  17325. standard. The classes composing the SOM Interface Repository Framework 
  17326. implement the programming interface to the CORBA Interface Repository. 
  17327. Accordingly, the SOM Interface Repository Framework supports all of the 
  17328. interfaces described in The Common Object Request Broker: Architecture and 
  17329. Specification (OMG Document Number 91.12.1, Revision 1.1, chapter 7). 
  17330.  
  17331. As an extension to the CORBA standard, the SOM Interface Repository Framework 
  17332. permits storage in the Interface Repository of arbitrary information in the 
  17333. form of SOM IDL modifiers. That is, within the SOM-unique implementation 
  17334. section of an IDL source file or through the use of the #pragma modifier 
  17335. statement, user-defined modifiers can be associated with any element of an IDL 
  17336. specification. (See the section entitled "SOM Interface Definition Language" in 
  17337. Chapter 4, "SOM IDL and the SOM Compiler.") When the SOM Compile creates the 
  17338. Interface Repository from an IDL specification, these potentially arbitrary 
  17339. modifiers are stored in the IR and can then be accessed via the methods 
  17340. provided by the Interface Repository Framework. 
  17341.  
  17342. This chapter describes, first, how to build and manage interface repositories, 
  17343. and second, the programming interfaces embodied in the SOM Interface Repository 
  17344. Framework. 
  17345.  
  17346.  
  17347. ΓòÉΓòÉΓòÉ 9.2. Using the SOM Compiler to Build an Interface Repository ΓòÉΓòÉΓòÉ
  17348.  
  17349. The SOMobjects Toolkit includes an Interface Repository emitter that is invoked 
  17350. whenever the SOM Compiler is run using an sc command with the -u option (which 
  17351. "updates" the interface repository). The IR emitter can be used to create or 
  17352. update an Interface Repository file. The IR emitter expects that an environment 
  17353. variable, SOMIR, was first set to designate a file name for the Interface 
  17354. Repository. For example, to compile an IDL source file named "newcls.idl" and 
  17355. create an Interface Repository named "newcls.ir", use a command sequence 
  17356. similar to the following: 
  17357.  
  17358. For OS/2: 
  17359.  
  17360. set SOMIR=c:\myfiles\newcls.ir
  17361. sc -u newcls
  17362.  
  17363. For AIX: 
  17364.  
  17365. export SOMIR=~/newcls.ir
  17366. sc -u newcls
  17367.  
  17368. If the SOMIR environment variable is not set, the Interface Repository emitter 
  17369. creates a file named "som.ir" in the current directory. 
  17370.  
  17371. The sc or somc command runs the Interface Reposito emitter plus any other 
  17372. emitters indicated by the environment variable SMEMIT (described in the topic 
  17373. "Running the SOM Compiler" in Chapter 4, "Implementing SOM Classes"). To run 
  17374. the Interface Repository emitter by itself, issue the sc command with the -s 
  17375. option (which overrides SMEMIT) set to "ir". For example: 
  17376.  
  17377. sc -u -sir newcls        (ON OS/2 or AIX)
  17378. somc -u -sir newcls      (On Windows)
  17379. or equivalently, 
  17380.  
  17381. sc -usir newcls          (On OS/2 or AIX)
  17382. somc -usir newcls        (On Windows)
  17383.  
  17384. The Interface Repository emitter uses the SOMIR environment variable to locate 
  17385. the designated IR file. If the file does not exist, the IR emitter creates it. 
  17386. If the named interface repository already exists, the IR emitter checks all of 
  17387. the "type" information in the IDL source file being compiled for internal 
  17388. consistency, and then changes the contents of the interface repository file to 
  17389. agree with with the new IDL definition. For this reason, the use of the -u 
  17390. compiler flag requires that all of the types mentioned in the IDL source file 
  17391. must be fully defined within the scope of the compilation. Warning messages 
  17392. from the SOM Compiler about undefined types result in actual error messages 
  17393. when using the -u flag. 
  17394.  
  17395. The additional type checking and file updating activity implied by the -u flag 
  17396. increases the time it takes to run the SOM Compiler. Thus, when developing an 
  17397. IDL class description from scratch, where iterative changes are to be expected, 
  17398. it may be preferable not to use the -u compiler option until the class 
  17399. definition has stabilized. 
  17400.  
  17401.  
  17402. ΓòÉΓòÉΓòÉ 9.3. Managing Interface Repository files ΓòÉΓòÉΓòÉ
  17403.  
  17404. Just as the number of interface definitions contained in a single IDL source 
  17405. file is optional, similarly, the number of IDL files compiled into one 
  17406. interface repository file is also at the programmer's discretion. Commonly, 
  17407. however, all interfaces needed for a single project or class framework are kept 
  17408. in one interface repository. 
  17409.  
  17410.  
  17411. ΓòÉΓòÉΓòÉ 9.3.1. The SOM  IR file "som.ir" ΓòÉΓòÉΓòÉ
  17412.  
  17413. The SOMobjects Toolkit includes an Interface Repository file ("som.ir") that 
  17414. contains objects describing all of the types, classes, and methods provided by 
  17415. the various frameworks of the SOMobjects Toolkit. Since all new classes will 
  17416. ultimately be derived from these predefined SOM classes, some of this 
  17417. information also needs to be included in a programmer's own interface 
  17418. repository files. 
  17419.  
  17420. For example, suppose a new class, called "MyClass", is derived from SOMObject. 
  17421. When the SOM Compiler builds an Interface Repository for "MyClass", that IR 
  17422. will also include all of the information associated with the SOMObject class. 
  17423. This happens because the SOMObject class definition is inherited by each new 
  17424. class; thus, all of the SOMObject methods and typedefs are implicitly contained 
  17425. in the new class as well. 
  17426.  
  17427. Eventually, the process of deriving new classes from existing ones would lead 
  17428. to a great deal of duplication of information in separate interface repository 
  17429. files. This would be inefficient, wasteful of space, and extremely difficult to 
  17430. manage. For example, to make an evolutionary change to some class interface, a 
  17431. programmer would need to know about and subsequently update all of the 
  17432. interface repository files where information about that interface occurred. 
  17433.  
  17434. One way to avoid this dilemma would be to keep all interface definitions in a 
  17435. single interface repository (such as "som.ir"). This is not recommended, 
  17436. however. A single interface repository would soon grow to be unwieldy in size 
  17437. and become a source of frequent access contention. Everyone involved in 
  17438. developing class definitions would need update access to this one file, and 
  17439. simultaneous uses might result in longer compile times. 
  17440.  
  17441.  
  17442. ΓòÉΓòÉΓòÉ 9.3.2. Managing IRs via the SOMIR environment variable ΓòÉΓòÉΓòÉ
  17443.  
  17444. The SOMobjects Toolkit offers a more flexible approach to managing interface 
  17445. repositories. The SOMIR environment variable can reference an ordered list of 
  17446. separate IR files, which process from left to right. Taken as a whole, however, 
  17447. this gives the appearance of a single, logical interface repository. A 
  17448. programmer accessing the contents of "the interface repository" through the SOM 
  17449. Interface Repository framework would not be aware of the division of 
  17450. information across separate files. It would seem as though all of the objects 
  17451. resided in a single interface repository file. 
  17452.  
  17453. A typical way to utilize this capability is as follows: 
  17454.  
  17455.    o  The first (leftmost) Interface Repository in the SOMIR list would be 
  17456.       "som.ir". This file contains the basic interfaces and types needed in all 
  17457.       SOM classes. 
  17458.  
  17459.    o  The second file in the list might contain interface definitions that are 
  17460.       used globally across a particular enterprise. 
  17461.  
  17462.    o  A third interface repository file would contain definitions that are 
  17463.       unique to a particular department, and so on. 
  17464.  
  17465.    o  The final interface repository in the list should be set aside to hold 
  17466.       the interfaces needed for the project currently under development. 
  17467.  
  17468.  Developers working on different projects would each set their SOMIR 
  17469.  environment variables to hold slightly different lists. For the most part, the 
  17470.  leftmost portions of these lists would be the same, but the rightmost 
  17471.  interface repositories would differ. When any given developer is ready to 
  17472.  share his/her interface definitions with other people outside of the immediate 
  17473.  work group, that person's interface repository can be promoted to inclusion in 
  17474.  the master list. 
  17475.  
  17476.  With this arrangement of IR files, the more stable repositories are found at 
  17477.  the left end of the list. For example, a developer should never need to make 
  17478.  any significant changes to "som.ir", because these interfaces are defined by 
  17479.  IBM and would only change with a new release of the SOMobjects Toolkit. 
  17480.  
  17481.  The Interface Repository Framework only permits updates in the rightmost file 
  17482.  of the SOMIR interface repository list. That is, when the SOM Compiler -u flag 
  17483.  is used to update the Interface Repository, only the final file on the IR list 
  17484.  will be affected. The information in all preceding interface repository files 
  17485.  is treated as "read only".  Therefore, to change the definition of an 
  17486.  interface in one of the more global interface repository files, a developer 
  17487.  must overtly construct a special SOMIR list that omits all subsequent (that 
  17488.  is, further to the right) interface repository files, or else petition the 
  17489.  owner of that interface to make the change. 
  17490.  
  17491.  It is important the the rightmost filename in the SOMIR interface repository 
  17492.  list not appear elsewhere in the list.  For Example, the following setting for 
  17493.  SOMIR: 
  17494.  
  17495.        %SOMBASE5\ETC\SOM.IR;SOM.IR;C:\IR\COMPANY.IR;SOM.IR
  17496.  
  17497.  would cause problems when attempting to update the SOM.IR file, because SOM.IR 
  17498.  appears twice in the list. 
  17499.  
  17500.  Here is an example that illustrates the use of multiple IR files with the 
  17501.  SOMIR environment variable. In this example, the SOMBASE environment variable 
  17502.  represents the directory in which the SOMobjects Toolkit files have been 
  17503.  installed. Only the "myown.ir" interface repository file will be updated with 
  17504.  the interfaces found in files "myclass1.idl", "myclass2.idl", and 
  17505.  "myclass3.idl". 
  17506.  
  17507.  For OS/2: 
  17508.  
  17509.   set BASE_IRLIST=%SOMBASE%\IR\SOM.IR;C:\IR\COMPANY.IR;C:\IR\DEPT10.IR
  17510.   set SOMIR=%BASE_IRLIST%;D:\MYOWN.IR
  17511.   set SMINCLUDE=.;%SOMBASE%\INCLUDE;C:\COMPANY\INCLUDE;C:\DEPT10\INCLUDE
  17512.   sc -usir myclass1
  17513.   sc -usir myclass2
  17514.   sc -usir myclass3
  17515.  
  17516.  For AIX: 
  17517.  
  17518.   export BASE_IRLIST=$SOMBASE/ir/som.ir:/usr/local/ir/comany.ir:\
  17519.       /usr/local/ir/dept10.ir
  17520.   export SOMIR=$BASE_IRLIST:~/myown.ir
  17521.   export SMINCLUDE=.:$SOMBASE/INCLUDE:/usr/local/company/include:\
  17522.       /usr/local/dept10/include
  17523.   sc -usir myclass1
  17524.   sc -usir myclass2
  17525.   sc -usir myclass3
  17526.  
  17527.  
  17528. ΓòÉΓòÉΓòÉ 9.3.3. Placing `private' information in the Interface Repository ΓòÉΓòÉΓòÉ
  17529.  
  17530. When the SOM Compiler updates the Interface Repository in response to the -u 
  17531. flag, it uses all of the information available from the IDL source file. 
  17532. However, if the __PRIVATE__ preprocessor variable is used to designate certain 
  17533. portions of the IDL file as private, the preprocessor actually removes that 
  17534. information before the SOM Compiler sees it. Consequently, private information 
  17535. will not appear in the Interface Repository unless the -p compiler option is 
  17536. also used in conjunction with -u. For example: 
  17537.  
  17538. sc -up myclass1          (On AIX or OS/2)
  17539. somc -up myclass1        (On Windows)
  17540.  
  17541. This command will place all of the information in the "myclass1.idl" file, 
  17542. including the private portions, in the Interface Repository. 
  17543.  
  17544. If you are using tools that understand SOM and rely on the Interface Repository 
  17545. to describe the types and instance data in your classes, you may need to 
  17546. include the private sections from your IDL source files when building the 
  17547. Interface Repository. 
  17548.  
  17549.  
  17550. ΓòÉΓòÉΓòÉ 9.4. Programming with the Interface Repository Objects ΓòÉΓòÉΓòÉ
  17551.  
  17552. The SOM Interface Repository Framework provides an object-oriented programming 
  17553. interface to the IDL information processed by the SOM Compiler. Unlike many 
  17554. frameworks that require you to inherit their behavior in order to use it, the 
  17555. Interface Repository Framework is useful in its own right as a set of 
  17556. predefined objects that you can access to obtain information. Of course, if you 
  17557. need to subclass a class to modify its behavior, you can certainly do so; but 
  17558. typically this is not necessary. 
  17559.  
  17560. The SOM Interface Repository contains the fully-analyzed (compiled) contents of 
  17561. all information in an IDL source file. This information takes the the form of 
  17562. persistent objects that can be accessed from a running program. There are ten 
  17563. classes of objects in the Interface Repository that correspond directly to the 
  17564. major elements in IDL source files; in addition, one instance of another class 
  17565. exists outside of the IR itself, as follows: 
  17566.  
  17567.  Contained                All objects in the Interface Repository are instances 
  17568.                           of classes derived from this class and exhibit the 
  17569.                           common behavior defined in this interface. 
  17570.  
  17571.  Container                Some objects in the Interface Repository hold (or 
  17572.                           contain) other objects. (For example, a module 
  17573.                           [ModuleDef] can contain an interface [InterfaceDef].) 
  17574.                           All Interface Repository objects that hold other 
  17575.                           objects are instances of classes derived from this 
  17576.                           class and exhibit the common behavior defined by this 
  17577.                           class. 
  17578.  
  17579.  ModuleDef                An instance of this class exists for each module 
  17580.                           defined in an IDL source file. ModuleDefs are 
  17581.                           Containers, and they can  hold ConstantDefs, 
  17582.                           TypeDefs,  ExceptionDefs, InterfaceDefs, and other 
  17583.                           ModuleDefs. 
  17584.  
  17585.  InterfaceDef             An instance of this class exists for each interface 
  17586.                           named in an IDL source file. (One InterfaceDef 
  17587.                           corresponds to one SOM class.)  InterfaceDefs are 
  17588.                           Containers, and they can hold ConstantDefs, TypeDefs, 
  17589.                           ExceptionDefs, AttributeDefs, and OperationDefs. 
  17590.  
  17591.  AttributeDef             An instance of this class exists for each attribute 
  17592.                           defined in an IDL source file. AttributeDefs are 
  17593.                           found only inside of (contained by) InterfaceDefs. 
  17594.  
  17595.  OperationDef             An instance of this class exists for each operation 
  17596.                           (method) defined in an IDL source file. OperationDefs 
  17597.                           are Containers that can hold ParameterDefs. 
  17598.                           OperationDefs are found only inside of (contained by) 
  17599.                           InterfaceDefs. 
  17600.  
  17601.  ParameterDef             An instance of this class exists for each parameter 
  17602.                           of each operation (method) defined in an IDL source 
  17603.                           file. ParameterDefs are found only inside of 
  17604.                           (contained by) OperationDefs. 
  17605.  
  17606.  TypeDef                  An instance of this class exists for each typedef, 
  17607.                           struct, union, or enum defined in an IDL source file. 
  17608.                           TypeDefs may be found inside of (contained by) any 
  17609.                           Interface Repository Container except an 
  17610.                           OperationDef. 
  17611.  
  17612.  ConstantDef              An instance of this class exists for each constant 
  17613.                           defined in an IDL source file. ConstantDefs may be 
  17614.                           found inside (contained by) of any Interface 
  17615.                           Repository Container except an OperationDef. 
  17616.  
  17617.  ExceptionDef             An instance of this class exists for each exception 
  17618.                           defined in an IDL source file. ExceptionDefs may be 
  17619.                           found inside of (contained by) any Interface 
  17620.                           Repository Container except an OperationDef. 
  17621.  
  17622.  Repository               One instance of this class exists for the entire SOM 
  17623.                           Interface Repository, to hold IDL elements that are 
  17624.                           global in scope. The instance of this class does not, 
  17625.                           however, reside within the IR itself. 
  17626.  
  17627.  
  17628. ΓòÉΓòÉΓòÉ 9.4.1. Methods introduced by Interface Repository classes ΓòÉΓòÉΓòÉ
  17629.  
  17630. The Interface Repository classes introduce nine new methods, which are briefly 
  17631. described below. Many of the classes simply override methods to customize them 
  17632. for the corresponding IDL element; this is particularly true for classes 
  17633. representing IDL elements that are only contained within another syntactic 
  17634. element. Full descriptions of each method are found in the SOMobjects Developer 
  17635. Toolkit: Programmers Reference Manual. 
  17636.  
  17637.    o  Contained class methods (all IR objects are instances of this class and 
  17638.       exhibit this behavior): 
  17639.  
  17640.            describe                 Returns a structure of type Description 
  17641.                                     containing all information defined in the 
  17642.                                     IDL specification of the syntactic element 
  17643.                                     corresponding to the target Contained 
  17644.                                     object. For example, for a target 
  17645.                                     InterfaceDef object, the describe method 
  17646.                                     returns information about the IDL interface 
  17647.                                     declaration. The Description structure 
  17648.                                     contains a "name" field with an identifier 
  17649.                                     that categorizes the description (such as, 
  17650.                                     "InterfaceDescription") and a "value" field 
  17651.                                     holding an "any" structure that points to 
  17652.                                     another structure containing the IDL 
  17653.                                     information for that particular element (in 
  17654.                                     this example, the interface's IDL 
  17655.                                     specifications). 
  17656.  
  17657.            within                   Returns a sequence designating the 
  17658.                                     object(s) of the IR within which the target 
  17659.                                     Contained object is contained. For example, 
  17660.                                     for a target TypeDef object, it might be 
  17661.                                     contained within any other IR object(s) 
  17662.                                     except an OperationDef object. 
  17663.  
  17664.    o  Container class methods (some IR objects contain other objects and 
  17665.       exhibit this behavior): 
  17666.  
  17667.            contents                 Returns a sequence of pointers to the 
  17668.                                     object(s) of the IR that the target 
  17669.                                     Container object contains. (For example, 
  17670.                                     for a target InterfaceDef object, the 
  17671.                                     contents method returns a pointer to each 
  17672.                                     IR object that corresponds to a part of the 
  17673.                                     IDL interface declaration.) The method 
  17674.                                     provides options for excluding inherited 
  17675.                                     objects or for limiting the search to only 
  17676.                                     a specified kind of object (such as 
  17677.                                     AttributeDefs). 
  17678.  
  17679.            describe_contents        Combines the describe and contents methods; 
  17680.                                     returns a sequence of ContainerDescription 
  17681.                                     structures, one for each object contained 
  17682.                                     by the target Container object. Each 
  17683.                                     structure has a pointer to the related 
  17684.                                     object, as well as "name" and "value" 
  17685.                                     fields resulting from the describe method. 
  17686.  
  17687.            lookup_name              Returns a sequence of pointers to objects 
  17688.                                     of a given name contained within a 
  17689.                                     specified Container object, or within 
  17690.                                     (sub)objects contained in the specified 
  17691.                                     Container object. 
  17692.  
  17693.    o  ModuleDef class methods: 
  17694.  
  17695.                                     Override describe and within. 
  17696.  
  17697.    o  InterfaceDef class methods: 
  17698.  
  17699.            describe_interface       Returns a description of all methods and 
  17700.                                     attributes of a given interface definition 
  17701.                                     object that are held in the Interface 
  17702.                                     Repository. 
  17703.  
  17704.                                     Also overrides describe and within. 
  17705.  
  17706.    o  AttributeDef class method: 
  17707.  
  17708.                                     Overrides describe. 
  17709.  
  17710.    o  OperationDef class method: 
  17711.  
  17712.                                     Overrides describe. 
  17713.  
  17714.    o  ParameterDef class method: 
  17715.  
  17716.                                     Overrides describe. 
  17717.  
  17718.    o  TypeDef  class method: 
  17719.  
  17720.                                     Overrides describe. 
  17721.  
  17722.    o  ConstantDef class method: 
  17723.  
  17724.                                     Overrides describe. 
  17725.  
  17726.    o  ExceptionDef class method: 
  17727.  
  17728.                                     Overrides describe. 
  17729.  
  17730.    o  Repository class methods: 
  17731.  
  17732.            lookup_id                Returns the Contained object that has a 
  17733.                                     specified RepositoryId. 
  17734.  
  17735.            lookup_modifier          Returns the string value held by a SOM or 
  17736.                                     user-defined modifier, given the name and 
  17737.                                     type of the modifier, and the name of the 
  17738.                                     object that contains the modifier. 
  17739.  
  17740.            release_cache            Releases, from the internal object cache, 
  17741.                                     the storage used by all currently 
  17742.                                     unreferenced Interface Repository objects. 
  17743.  
  17744.  
  17745. ΓòÉΓòÉΓòÉ 9.4.2. Accessing objects in the Interface Repository ΓòÉΓòÉΓòÉ
  17746.  
  17747. As mentioned above, one instance of the Repository  class exists for the entire 
  17748. SOM Interface Repository. This object does not, itself, reside in the Interface 
  17749. Repository (hence it does not exhibit any of the behavior defined by the 
  17750. Contained class). It is, however, a Container, and it holds all ConstantDefs, 
  17751. TypeDefs, ExceptionDefs, InterfaceDefs, and ModuleDefs that are global in scope 
  17752. (that is, not contained inside of any other Containers). 
  17753.  
  17754. When any method provided by the Repository class is used to locate other 
  17755. objects in the Interface Repository, those objects are automatically 
  17756. instantiated and activated. Consequently, when the program is finished using an 
  17757. object from the Interface Repository, the client code should release the object 
  17758. using the somFree method. 
  17759.  
  17760. All objects contained in the Interface Repository have both a "name" and a 
  17761. "Repository ID" associated with them. The name is not guaranteed to be unique, 
  17762. but it does uniquely identify an object within the context of the object that 
  17763. contains it. The Repository ID of each object is guaranteed to uniquely 
  17764. identify that object, regardless of its context. 
  17765.  
  17766. For example, two TypeDef objects may have the same name, provided they occur in 
  17767. separate name scopes (ModuleDefs or InterfaceDefs). In this case, asking the 
  17768. Interface Repository to locate the TypeDef object based on its name would 
  17769. result in both TypeDef objects being returned. On the other hand, if the name 
  17770. is looked up from a particular  ModuleDef or InterfaceDef object, only the 
  17771. TypeDef object within the scope of that ModuleDef or InterfaceDef would be 
  17772. returned. By contrast, once the Repository ID of an object is known, that 
  17773. object can always be directly obtained from the Repository object via its 
  17774. Repository ID. 
  17775.  
  17776. C or C++ programmers can obtain an instance of the Repository class using the 
  17777. RepositoryNew macro. Programmers using other languages (and C/C++ programmers 
  17778. without static linkage to the Repository class) should invoke the method 
  17779. somGetInterfaceRepository on the SOMClassMgrObject . For example, 
  17780.  
  17781. For C or C++ (static linkage): 
  17782.  
  17783. #include <repostry.h>
  17784. Repository repo;
  17785.  
  17786. repo = RepositoryNew();
  17787.  
  17788. From other languages (and for dynamic linkage in C/C++): 
  17789.  
  17790.    1. Use the somEnvironmentNew function to obtain a pointer to the 
  17791.       SOMClassMgrObject, as described in Chapter 3, "Using SOM Classes." 
  17792.  
  17793.    2. Use the somResolve or somResolveByName function to obtain a pointer to 
  17794.       the somGetInterfaceRepository method procedure. 
  17795.  
  17796.    3. Invoke the method procedure on the SOMClassMgrObject, with no additional 
  17797.       arguments, to obtain a pointer to the Repository object. 
  17798.  
  17799.  After obtaining a pointer to the Repository object, use the methods it 
  17800.  inherits from Container or its own lookup_id method to instantiate objects in 
  17801.  the Interface Repository. As an example, the contents method shown in the C 
  17802.  fragment below activates every object with global scope in the Interface 
  17803.  Repository and returns a sequence containing a pointer to every global object: 
  17804.  
  17805.   #include <containd.h>      /* Behavior common to all
  17806.   IR objects */
  17807.   Environment *ev;
  17808.   int i;
  17809.   sequence(Contained) everyGlobalObject;
  17810.  
  17811.   ev = SOM_CreateLocalEnvironment(); /* Get an environment to use */
  17812.   printf ("Every global object in the Interface Repository:\n");
  17813.  
  17814.   everyGlobalObject = Container_contents (repo, ev, "all", TRUE);
  17815.  
  17816.   for (i=0; i < everyGlobalObject._length; i++) {
  17817.       Contained aContained;
  17818.  
  17819.       aContained = (Contained) everyGlobalObject._buffer[i];
  17820.       printf ("Name: %s, Id: %s\n",
  17821.           Contained__get_name (aContained, ev),
  17822.           Contained__get_id (aContained, ev));
  17823.       SOMObject_somFree (aContained);
  17824.   }
  17825.  
  17826.  Taking this example one step further, here is a complete program that accesses 
  17827.  every object in the entire Interface Repository. It, too, uses the contents 
  17828.  method, but this time recursively calls the contents method until every object 
  17829.  in every container has been found: 
  17830.  
  17831.   #include <stdio.h>
  17832.   #include <containd.h>
  17833.   #include <repostry.h>
  17834.  
  17835.   void showContainer (Container c, int *next);
  17836.  
  17837.   main ()
  17838.   {
  17839.       int count = 0;
  17840.       Repository repo;
  17841.  
  17842.       repo = RepositoryNew ();
  17843.       printf ("Every object in the Interface Repository:\n\n");
  17844.       showContainer ((Container) repo, &count);
  17845.       SOMObject_somFree (repo);
  17846.       printf ("%d objects found\n", count);
  17847.       exit (0);
  17848.   }
  17849.  
  17850.   void showContainer (Container c, int *next)
  17851.   {
  17852.       Environment *ev;
  17853.       int i;
  17854.       sequence(Contained) everyObject;
  17855.  
  17856.       ev = SOM_CreateLocalEnvironment (); /* Get an environment */
  17857.       everyObject = Container_contents (c, ev, "all", TRUE);
  17858.  
  17859.       for (i=0; i<everyObject._length; i++) {
  17860.           Contained aContained;
  17861.  
  17862.           (*next)++;
  17863.           aContained = (Contained) everyObject._buffer[i];
  17864.           printf ("%6d. Type: %-12s id: %s\n", *next,
  17865.               SOMObject_somGetClassName (aContained),
  17866.               Contained__get_id (aContained, ev));
  17867.           if (SOMObject_somIsA (aContained, _Container))
  17868.               showContainer ((Container) aContained, next);
  17869.           SOMObject_somFree (aContained);
  17870.       }
  17871.   }
  17872.  
  17873.  Once an object has been retrieved, the methods and attributes appropriate for 
  17874.  that particular object can then be used to access the information contained in 
  17875.  the object. The methods supported by each class of object in the Interface 
  17876.  Repository, as well as the classes themselves, are documented in the 
  17877.  SOMobjects Developer Toolkit: Programmers Reference Manual. 
  17878.  
  17879.  
  17880. ΓòÉΓòÉΓòÉ 9.4.3. A word about memory management ΓòÉΓòÉΓòÉ
  17881.  
  17882. Several conventions are built into the SOM Interface Repository with regard to 
  17883. memory management. You will need to understand these conventions to know when 
  17884. it is safe and appropriate to free memory references and also when it is your 
  17885. responsibility to do so. 
  17886.  
  17887. All methods that access attributes (such as, the _get_<attribute> methods) 
  17888. always return either simple values or direct references to data within the 
  17889. target object. This is necessary because these methods are heavily used and 
  17890. must be fast and efficient. Consequently, you should never free any of the 
  17891. memory references obtained through attributes. This memory will be released 
  17892. automatically when the object that contains it is freed. 
  17893.  
  17894. For all methods that give out object references (there are five: within, 
  17895. contents, lookup_name, lookup_id, and describe_contents), when finished with 
  17896. the object, you are expected to release the object reference by invoking the 
  17897. somFree method. (This is illustrated in the sample program that accesses all 
  17898. Interface Repository objects.) Do not release the object reference until you 
  17899. have either copied or finished using all of the information obtained from the 
  17900. object. 
  17901.  
  17902. The describe methods (describe, describe_contents, and describe_interface) 
  17903. return structures and sequences that contain information. The actual structures 
  17904. returned by these methods are passed by value (and hence should only be freed 
  17905. if you have allocated the memory used to receive them). However, you may be 
  17906. required to free some of the information contained in the returned structures 
  17907. when you are finished. Consult the specific method in the SOMobjects Developer 
  17908. Toolkit: Programmers Reference Manual for more details about what to free. 
  17909.  
  17910. During execution of the describe and lookup methods, sometimes intermediate 
  17911. objects are activated automatically. These objects are kept in an internal 
  17912. cache of objects that are in use, but for which no explicit object references 
  17913. have been returned as results. Consequently, there is no way to identify or 
  17914. free these objects individually. However, whenever your program is finished 
  17915. using all of the information obtained thus far from the Interface Repository, 
  17916. invoking the release_cache method causes the Interface Repository to purge its 
  17917. internal cache of these implicitly referenced objects. This cache will 
  17918. replenish itself automatically if the need to do so subsequently arises. 
  17919.  
  17920.  
  17921. ΓòÉΓòÉΓòÉ 9.4.4. Using TypeCode pseudo-objects ΓòÉΓòÉΓòÉ
  17922.  
  17923. Much of the detailed information contained in Interface Repository objects is 
  17924. represented in the form of TypeCodes. TypeCodes are complex data structures 
  17925. whose actual representation is hidden. A TypeCode is an architected way of 
  17926. describing in complete detail everything that is known about a particular data 
  17927. type in the IDL language, regardless of whether it is a (built-in) basic type 
  17928. or a  (user-defined) aggregate  type. 
  17929.  
  17930. Conceptually, every TypeCode contains a "kind" field (which classifies it), and 
  17931. one or more parameters that carry descriptive information appropriate for that 
  17932. particular category of TypeCode. For example, if the data type is long, its 
  17933. TypeCode would contain a "kind" field with the value tk_long. No additional 
  17934. parameters are needed to completely describe this particular data type, since 
  17935. long is a basic type in the IDL language. 
  17936.  
  17937. By contrast, if the TypeCode describes an IDL struct, its "kind" field would 
  17938. contain the value tk_struct, and it would possess the following parameters: a 
  17939. string giving the name of the struct, and two additional parameters for each 
  17940. member of the struct: a string giving the member name and another (inner) 
  17941. TypeCode representing the member's type. This example illustrates the fact that 
  17942. TypeCodes can be nested and arbitrarily complex, as appropriate to express the 
  17943. type of data they describe. Thus, a structure that has N members will have a 
  17944. TypeCode of tk_struct with 2N+1 parameters (a name and TypeCode parameter for 
  17945. each member, plus a name for the struct itself). 
  17946.  
  17947. A tk_union TypeCode representing a union with N members has 3N+2 parameters: 
  17948. the type name of the union, the switch TypeCode, and a label value, member name 
  17949. and associated TypeCode for each member. (The label values all have the same 
  17950. type as the switch, except that the default member, if present, has a label 
  17951. value of zero octet.) 
  17952.  
  17953. A tk_enum TypeCode  (which represents an enum) has  N+1 parameters: the name of 
  17954. the enum followed by a string for each enumeration identifier. A tk_string 
  17955. TypeCode has a single parameter: the maximum string length, as an integer. (A 
  17956. maximum length of zero signifies an unbounded string.) 
  17957.  
  17958. A tk_sequence TypeCode has two parameters: a TypeCode for the sequence 
  17959. elements, and the maximum size, as an integer.  (Again, zero signifies 
  17960. unbounded.) 
  17961.  
  17962. A tk_array TypeCode has two parameters: a TypeCode for the array elements, and 
  17963. the array length, as an integer. (Arrays must be bounded.) 
  17964.  
  17965. The tk_objref TypeCode represents an object reference; its parameter is a 
  17966. repository ID that identifies its interface. 
  17967.  
  17968. A complete table showing the parameters of all possible TypeCodes is given in 
  17969. the SOMobjects Base Toolkit Programmers Reference Manual; see the TypeCode_kind 
  17970. function of the Interface Repository Framework. 
  17971.  
  17972. TypeCodes are not actually "objects" in the formal sense. TypeCodes are 
  17973. referred to in the CORBA standard as pseudo-objects and described as "opaque". 
  17974. This means that, in reality, TypeCodes are special data structures whose 
  17975. precise definition is not fully exposed. Their implementation can vary from one 
  17976. platform to another, but all implementations must exhibit a minimal set of 
  17977. architected behavior. SOM TypeCodes support the architected behavior and have 
  17978. additional capability as well (for example, they can be copied and freed). 
  17979.  
  17980. Although TypeCodes are not objects, the programming interfaces that support 
  17981. them adhere to the same conventions used for IDL method invocations in SOM. 
  17982. That is, the first argument is always a TypeCode pseudo-object, and the second 
  17983. argument is a pointer to an Environment structure. Similarly, the names of the 
  17984. TypeCode functions are constructed like SOM's C-language method-invocation 
  17985. macros (all functions that operate on TypeCodes are named 
  17986. TypeCode_<function-name>). Because of this ostensible similarity to an IDL 
  17987. class, the TypeCode programming interfaces can be conveniently defined in IDL 
  17988. as shown below. 
  17989.  
  17990. A complete table showing the parameters of all possible  TypeCodes is given in 
  17991. the SOMobjects Developer Toolkit Programmers Reference Manual; see the 
  17992. TypeCode_kind function of the Interface Repository Framework. 
  17993.  
  17994. interface TypeCode {
  17995.  
  17996. enum TCKind {
  17997.     tk_null, tk_void,
  17998.     tk_short, tk_long, tk_ushort, tk_ulong,
  17999.     tk_float, tk_double, tk_boolean, tk_char,
  18000.     tk_octet, tk_any, tk_TypeCode, tk_Principal, tk_objref,
  18001.     tk_struct, tk_union, tk_enum, tk_string,
  18002.     tk_sequence, tk_array,
  18003.  
  18004.     // The remaining enumerators are SOM-unique extensions
  18005.     // to the CORBA standard.
  18006.     //
  18007.     tk_pointer, tk_self, tk_foreign
  18008. };
  18009.  
  18010. exception Bounds {};
  18011. // This exception is returned if an attempt is made
  18012. // by the parameter() operation (described below) to
  18013. // access more parameters than exist in the receiving
  18014. // TypeCode.
  18015.  
  18016. boolean equal (in TypeCode tc);
  18017. // Compares the argument with the receiver and returns TRUE
  18018. // if both TypeCodes are equivalent.  This is NOT a test for
  18019. // identity.
  18020.  
  18021. TCKind kind ();
  18022. // Returns the type of the receiver as a TCKind.
  18023.  
  18024. long param_count ();
  18025. // Returns the number of parameters that make up the
  18026. // receiving TypeCode.
  18027.  
  18028. any parameter (in long index) raises (Bounds);
  18029. // Returns the indexed parameter from the receiving TypeCode.
  18030. // Parameters are indexed from 0 to param_count()-1.
  18031. //
  18032. //  The remaining operations are SOM-unique extensions.
  18033. //
  18034.  
  18035. short alignment ();
  18036. // This operation returns the alignment required for an instance
  18037. // of the type described by the receiving TypeCode.
  18038.  
  18039. TypeCode copy (in TypeCode tc);
  18040. // This operation returns a copy of the receiving TypeCode.
  18041.  
  18042. void free (in TypeCode tc);
  18043. // This operation frees the memory associated with the
  18044. // receiving TypeCode. Subsequently, no further use can be
  18045. // made of the receiver, which, in effect, ceases to exist.
  18046.  
  18047. void print (in TypeCode tc);
  18048. // This operation writes a readable representation of the
  18049. // receiving TypeCode to stdout.  Useful for examining
  18050. // TypeCodes when debugging.
  18051.  
  18052. void setAlignment (in short align);
  18053. // This operation overrides the required alignment for an
  18054. // instance of the type described by the receiving TypeCode.
  18055.  
  18056. long size (in TypeCode tc);
  18057. // This operation returns the size of an instance of the
  18058. // type represented by the receiving TypeCode.
  18059. };
  18060.  
  18061. A detailed description of the programming interfaces for TypeCodes is given in 
  18062. the SOMobjects Developer Toolkit: Programmers Reference Manual. 
  18063. Providing `alignment' information 
  18064.  
  18065. In addition to the parameters in the TypeCodes that describe each type, a 
  18066. SOM-unique extension to the TypeCode functionality allows each TypeCode to 
  18067. carry alignment information as a "hidden" parameter. Use the TypeCode_alignment 
  18068. function to access the alignment value. The alignment value is a short integer 
  18069. that should evenly divide any memory address where an instance of the type will 
  18070. occur. 
  18071.  
  18072. If no alignment information is provided in your IDL source files, all TypeCodes 
  18073. carry default alignment information. The default alignment for a type is the 
  18074. natural boundary for the type, based on the natural boundary for the basic 
  18075. types of which it may be composed. This information can vary from one hardware 
  18076. platform to another. The  TypeCode will contain the default alignment 
  18077. information appropriate to the platform where it was defined. 
  18078.  
  18079. To provide alignment information for the types and instances of types in your 
  18080. IDL source file, use the "align=N" modifier, where N is your specified 
  18081. alignment. Use standard modifier syntax of the SOM Compiler to attach the 
  18082. alignment information to a particular element in the IDL source file. In the 
  18083. following example,  align=1 (that is, unaligned or no alignment) is attached to 
  18084. the struct "abc" and to one particular instance of struct "def" (the instance 
  18085. data item " y"). 
  18086.  
  18087. interface i {
  18088.     struct abc {
  18089.         long a;
  18090.         char b;
  18091.         long c;
  18092.     };
  18093.     struct def {
  18094.         char l;
  18095.         long m;
  18096.     };
  18097.  
  18098.     void foo ();
  18099.  
  18100.     implementation {
  18101.  
  18102.     //# instance data
  18103.         abc x;
  18104.         def y;
  18105.         def z;
  18106.  
  18107.     //# alignment modifiers
  18108.         abc: align=1;
  18109.         y: align=1;
  18110.     };
  18111. };
  18112.  
  18113. Be aware that assigning the required alignment information to a type does not 
  18114. guarantee that instances of that type will actually be aligned as indicated. To 
  18115. ensure that, you must find a way to instruct your compiler to provide the 
  18116. desired alignment. In practice, this can be difficult except in simple cases. 
  18117. Most compilers can be instructed to treat all data as aligned (that is, default 
  18118. alignment) or as unaligned, by using a compile-time option or #pragma. The more 
  18119. important consideration is to make certain that the TypeCodes going into the 
  18120. Interface Repository actually reflect the alignment that your compiler 
  18121. provides. This way, when programs (such as the DSOM Framework) need to 
  18122. interpret the layout of data during their execution, they will be able to 
  18123. accurately map your data structures. This happens automatically when using the 
  18124. normal default alignment. 
  18125.  
  18126. If you wish to use unaligned instance data when implementing a class, place an 
  18127. "unattached" align=1 modifier in the implementation section. An unattached 
  18128. align=N modifier is presumed to pertain to the class's instance data structure, 
  18129. and will by implication be attached to all of the instance data items. 
  18130.  
  18131. When designing your own public types, be aware that the best practice of all 
  18132. (and the one that offers the best opportunity for language neutrality) is to 
  18133. lay out your types carefully so that it will make no difference whether they 
  18134. are compiled as aligned or unaligned! 
  18135. Using the `tk_foreign' TypeCode 
  18136.  
  18137. TypeCodes can be used to partially describe types that cannot be described in 
  18138. IDL (for example, a FILE type in C, or a specific class type in C++). The 
  18139. SOM-unique extension tk_foreign is used for this purpose. A  tk_foreign 
  18140. TypeCode contains three parameters: 
  18141.  
  18142.    1. The name of the type, 
  18143.    2. An implementation context string, and 
  18144.    3. A length. 
  18145.  
  18146.  The implementation context string can be used to carry an arbitrarily long 
  18147.  description that identifies the context where the foreign type can be used and 
  18148.  understood. If the length of the type is also known, it can be provided with 
  18149.  the length parameter. If the length is not known or is not constant, it should 
  18150.  be specified as zero. If the length is not specified, it will default to the 
  18151.  size of a pointer. A tk_foreign TypeCode  can also have alignment information 
  18152.  specified, just like any other TypeCode. 
  18153.  
  18154.  Using the following steps causes the SOM Compiler to create a foreign TypeCode 
  18155.  in the Interface Repository: 
  18156.  
  18157.    1. Define the foreign type as a typedef SOMFOREIGN in the IDL source file. 
  18158.  
  18159.    2. Use the #pragma modifier statement to supply the additional information 
  18160.       for the TypeCode as modifiers. The implementation context information is 
  18161.       supplied using the "impctx" modifier. 
  18162.  
  18163.    3. Compile the IDL file using the -u option to place the information in the 
  18164.       Interface Repository. 
  18165.  
  18166.  For example: 
  18167.  
  18168.   typedef SOMFOREIGN Point;
  18169.   #pragma modifier Point: impctx="C++ Point class",length=12,align=4;
  18170.  
  18171.  If a foreign type is used to define instance data, structs, unions, 
  18172.  attributes, or methods in an IDL source file, it is your responsibility to 
  18173.  ensure that the implementation and/or usage bindings contain an appropriate 
  18174.  definition of the type that will satisfy your compiler. You can use the 
  18175.  passthru statement in your IDL file to supply this definition. However, it is 
  18176.  not recommended that you expose foreign data in attributes, methods, or any of 
  18177.  the public types, if this can be avoided, because there is no guarantee that 
  18178.  appropriate usage binding information can be provided for all languages. If 
  18179.  you know that all users of the class will be using the same implementation 
  18180.  language that your class uses, you may be able to disregard this 
  18181.  recommendation. 
  18182.  TypeCode constants 
  18183.  
  18184.  TypeCodes are actually available in two forms: In addition to the TypeCode 
  18185.  information provided by the methods of the Interface Repository, TypeCode 
  18186.  constants can be generated by the SOM Compiler in your C or C++ usage bindings 
  18187.  upon request. A TypeCode constant contains the same information found in the 
  18188.  corresponding IR TypeCode, but has the advantage that it can be used as a 
  18189.  literal in a C or C++ program anywhere a normal TypeCode would be acceptable. 
  18190.  
  18191.  TypeCode constants have the form TC_< typename>, where <typename> is the name 
  18192.  of a type (that is, a typedef, union, struct, or enum) that you have defined 
  18193.  in an IDL source file. In addition, all IDL basic types and certain types 
  18194.  dictated by the OMG CORBA standard come with pre-defined TypeCode constants 
  18195.  (such as TC_long, TC_short, TC_char, and so forth). A full list of the 
  18196.  pre-defined TypeCode constants can be found in the file "somtcnst.h". You must 
  18197.  explicitly include this file in your source program to use the pre-defined 
  18198.  TypeCode constants. 
  18199.  
  18200.  Since the generation of TypeCode constants can increase the time required by 
  18201.  the SOM Compiler to process your IDL files, you must explicitly request the 
  18202.  production of TypeCode constants if you need them. To do so, use the 
  18203.  "tcconsts" modifier with the -m option of the sc or somc command. For example, 
  18204.  the command 
  18205.  
  18206.   sc -sh -mtcconsts myclass.idl         (On AIX or Windows)
  18207.   somc -sh -mtcconsts myclass.idl       (On Windows)
  18208.  
  18209.  will cause the SOM Compiler to generate a "myclass.h" file that contains 
  18210.  TypeCode constants for the types defined in "myclass.idl". 
  18211.  Using the IDL basic type `any' 
  18212.  
  18213.  Some Interface Repository methods and TypeCode functions return information 
  18214.  typed as the IDL basic type any. Usually this is done when a wide variety of 
  18215.  different types of data may need to be returned through a common interface. 
  18216.  The type any actually consists of a structure with two fields: a _type field 
  18217.  and a _value field. The _value field is a pointer to the actual datum that was 
  18218.  returned, while the _type field holds a TypeCode  that describes the datum. 
  18219.  
  18220.  In many cases, the context in which an operation occurs makes the type of the 
  18221.  datum apparent. If so, there is no need to examine the TypeCode unless it is 
  18222.  simply as a consistency check. For example, when accessing the first parameter 
  18223.  of a tk_struct TypeCode, the type of the result will always be the name of the 
  18224.  structure (a string). Because this is known ahead of time, there is no need to 
  18225.  examine the returned TypeCode in the any_type field to verify that it is a 
  18226.  tk_string TypeCode. You can just rely on the fact that it is a string; or, you 
  18227.  can check the TypeCode in the _type field to verify it, if you so choose. 
  18228.  
  18229.  An IDL any type can be used in an interface as a way of bypassing the strong 
  18230.  type checking that occurs in languages like ANSI C and C++. Your compiler can 
  18231.  only check that the interface returns the any structure; it has no way of 
  18232.  knowing what type of data will be carried by the any during execution of the 
  18233.  program. Consequently, in order to write C or C++ code that accesses the 
  18234.  contents of the any correctly, you must always cast the _value field to 
  18235.  reflect the actual type of the datum at the time of the access. 
  18236.  
  18237.  Here is an example of a code fragment written in C that illustrates how the 
  18238.  casting must be done to extract various values from an any: 
  18239.  
  18240.   #include <som.h>    /* For "any" & "Environment" typedefs */
  18241.   #include <somtc.h>  /* For TypeCode_kind prototype        */
  18242.  
  18243.   any result;
  18244.   Environment *ev;
  18245.  
  18246.   printf ("result._value = ");
  18247.   switch (TypeCode_kind (result._type, ev)) {
  18248.  
  18249.       case tk_string:
  18250.           printf ("%s\n", *((string *) result._value));
  18251.           break;
  18252.  
  18253.       case tk_long:
  18254.           printf ("%ld\n", *((long *) result._value));
  18255.           break;
  18256.  
  18257.       case tk_boolean:
  18258.           printf ("%d\n", *((boolean *) result._value));
  18259.           break;
  18260.  
  18261.       case tk_float:
  18262.           printf ("%f\n", *((float *) result._value));
  18263.           break;
  18264.  
  18265.       case tk_double:
  18266.           printf ("%f\n", *((double *) result._value));
  18267.           break;
  18268.  
  18269.       default:
  18270.           printf ("something else!\n");
  18271.   }
  18272.  
  18273.  Note: Of course, an any has no restriction, per se, on the type of datum that 
  18274.  it can carry. Frequently, however, methods that return an any or that accept 
  18275.  an any as an argument do place semantic restrictions on the actual type of 
  18276.  data they can accept or return. Always consult the reference page for a method 
  18277.  that uses an any to determine whether it limits the range of types that may be 
  18278.  acceptable. 
  18279.  
  18280.  
  18281. ΓòÉΓòÉΓòÉ 10. The Metaclass Framework ΓòÉΓòÉΓòÉ
  18282.  
  18283. In SOM, classes are objects; metaclasses are classes and thus are objects, too. 
  18284.  
  18285. The important point to be aware of here is that any class that is a subclass of 
  18286. SOMClass is a metaclass This chapter describes metaclasses that are available 
  18287. in SOMobjects Toolkit. There are two kinds of metaclasses: 
  18288.  
  18289. Framework metaclasses--metaclasses for building new metaclasses and  Utility 
  18290. metaclasses--metaclasses to help you write applications 
  18291.  
  18292. Briefly, the SOMobjects Toolkit provides the following metaclasses of each 
  18293. category for use by programmers: 
  18294.  
  18295.    o  Framework metaclasses: 
  18296.  
  18297.     SOMMBeforeAfter  Used to create a metaclass that has "before" and "after" 
  18298.            methods for all methods (inherited or introduced) invoked on 
  18299.            instances of its classes. 
  18300.  
  18301.    o  Utility metaclasses: 
  18302.  
  18303.     SOMMSingleInstance  Used to create a class that may have at most one 
  18304.            instance. 
  18305.  
  18306.     SOMMTraced  Provides tracing for every invocation of all methods on 
  18307.            instances of its classes. 
  18308.  
  18309.  The following sections describe each metaclass more fully. 
  18310.  
  18311.  A note about metaclass programming 
  18312.  
  18313.  SOM metaclasses are carefully constructed so that they compose (see Section 
  18314.  8.1 below). If you need to create a metaclass, you can introduce new class 
  18315.  methods, and new class variables, but you should not override any of the 
  18316.  methods introduced by SOMClass. If you need more than this, request access to 
  18317.  the experimental Cooperative metaclass used to implement the Metaclass 
  18318.  Framework metaclasses described in this chapter. 
  18319.  
  18320.  
  18321. ΓòÉΓòÉΓòÉ 10.1. Framework Metaclasses for "Before/After" Behavior ΓòÉΓòÉΓòÉ
  18322.  
  18323.  
  18324. ΓòÉΓòÉΓòÉ 10.1.1. The `SOMMBeforeAfter' metaclass ΓòÉΓòÉΓòÉ
  18325.  
  18326. SOMMBeforeAfter is a metaclass that allows the user to create a class for which 
  18327. a particular method is invoked before each invocation of every method, nd for 
  18328. which a second method is invoked after each invocation. SOMMBeforeAfter defines 
  18329. two methods: sommBeforeMethod and sommAfterMethod.  These two methods are 
  18330. intended to be overridden in the child of SOMMBeforeAfter to define the 
  18331. particular "before" and "after" methods needed for the client application. 
  18332.  
  18333. For example, suppose a "Barking" metaclass (a subclass of SOMMBeforeAfter 
  18334. overrides the sommBeforeMethod and sommAfterMethod with a method that emits one 
  18335. bark when invoked. Thus, one can create the "BarkingDog" class, whose instances 
  18336. (such as "Lassie") bark twice when "disturbed" by a method invocation. 
  18337.  
  18338. The SOMMBeforeAfter metaclass is designed to be subclassed; a subclass (or 
  18339. child) of SOMMBeforeAfter is also a metaclass. The subclass overrides 
  18340. sommBeforeMethod or sommAfterMethod or both. These (redefned) methods are 
  18341. invoked before and after any method supported by instances of the subclass 
  18342. (these methods are called primary methods). That is, they are invoked before 
  18343. and after methods invoked on the ordinary objects that are instances of the 
  18344. class objects that are instances of the subclass of SOMMBeforeAfter. 
  18345.  
  18346. The sommBeforeMethod returns a boolean value. This allows the "before" method 
  18347. to control whether the "after" method and the primary method get invoked. If 
  18348. sommBeforeMethod returns TRUE, normal processing occurs. If FALSE is returned, 
  18349. neither the primary method nor the corresponding sommAfterMethod is invoked. In 
  18350. addition, no more deeply nested before/after methods are invoked (see 
  18351. "Composition of before/after metaclasses" below). This facility can be used, 
  18352. for example, to allow a before/after metaclass to provide secure access to an 
  18353. object. The implication of this convention is that, if sommBeforeMethod is 
  18354. going to return FALSE, it must do any post-processing that might otherwise be 
  18355. done in the "after" method. 
  18356.  
  18357. Caution: somInit and somFree are among the methods that get before/after 
  18358. behavior. This implies the following two obligations are imposed on the 
  18359. programmer of a SOMMBeforeAfter class. First, the implementation must guard 
  18360. against sommBeforeMethod being called before somInit has executed, and the 
  18361. object is not yet fully initialized. Second, the implementation must guard 
  18362. against sommAfterMethod being called after somFree, at which time the object no 
  18363. longer exists (see the example "C implementation for `Barking' metaclass" 
  18364. below). 
  18365.  
  18366. The following example shows the IDL needed to create a Barking metaclass. Just 
  18367. run the appropriate emitter to get an implementation binding, and then provide 
  18368. the appropriate "before" behavior and "after" behavior. 
  18369.  
  18370. SOM IDL for `Barking' metaclass 
  18371.  
  18372. #ifndef Barking_idl
  18373. #define Barking_idl
  18374.  
  18375. #include <sombacls.idl>
  18376. interface  Barking : SOMMBeforeAfter
  18377. {
  18378. #ifdef __SOMIDL__
  18379. implementation
  18380. {
  18381.   //# Class Modifiers
  18382.   filestem = barking;
  18383.   callstyle = idl;
  18384.  
  18385.   //# Method Modifiers
  18386.   sommBeforeMethod : override;
  18387.   sommAfterMethod : override;
  18388. };
  18389. #endif /* __SOMIDL__ */
  18390. };
  18391. #endif  /* Barking_idl */
  18392.  
  18393. The next example shows an implementation of the Barking metaclass in which no 
  18394. barking occurs when somFree is invoked. 
  18395.  
  18396. C implementation for `Barking' metaclass 
  18397.  
  18398. #define Barking_Class_Source
  18399. #include <barking.ih>
  18400.  
  18401. static char *somMN_somFree = "somFree";
  18402. static somId somId_somFree = &somMN_somFree;
  18403.  
  18404. SOM_Scope boolean  SOMLINK sommBeforeMethod(Barking somSelf,
  18405.                                             Environment *ev,
  18406.                                             SOMObject object,
  18407.                                             somId methodId,
  18408.                                             va_list ap)
  18409. {
  18410.     if ( !somCompareIds( methodId, somId_somFree )
  18411.        printf( "WOOF" );
  18412. }
  18413.  
  18414. SOM_Scope void  SOMLINK sommAfterMethod(Barking somSelf,
  18415.                                         Environment *ev,
  18416.                                         SOMObject object,
  18417.                                         somId methodId,
  18418.                                         somId descriptor,
  18419.                                         somToken returnedvalue,
  18420.                                         va_list ap)
  18421. {
  18422.     if ( !somCompareIds( methodId, somId_somFree )
  18423.        printf( "WOOF" );
  18424. }
  18425.  
  18426.  
  18427. ΓòÉΓòÉΓòÉ 10.1.2. Composition of before/after metaclasses ΓòÉΓòÉΓòÉ
  18428.  
  18429. When there are two before/after metaclasses--"Barking" (as before) and 
  18430. "Fierce", which has a sommBeforeMethod and sommAfterMethod that both growl 
  18431. (that is, both methods make a "grrrr" sound when executed). The preceding 
  18432. discussion demonstrated how to create a "FierceDog " or a "BarkingDog ", but 
  18433. has not yet addressed the question of how to compose these properties of fierce 
  18434. and barking. Composability means having the ability to easily create either a 
  18435. "FierceBarkingDog" that goes "grrr woof woof grrr " when it responds to a 
  18436. method call or a "BarkingFierceDog " that goes "woof grrr grrr woof" when it 
  18437. responds to a method call. 
  18438.  
  18439. There are several ways to express such compositions. Figure 1 depicts SOM IDL 
  18440. fragments for three techniques in which composition can be indicated by a 
  18441. programmer. These are denoted as Technique 1, Technique 2, and Technique 3, 
  18442. each of which creates a "FierceBarkingDog" class, named "FB-1", "FB-2", and 
  18443. "FB-3", respectively, as follows: 
  18444.  
  18445.    o  In Technique 1, a new metaclass ("FierceBarking") is created with both 
  18446.       the "Fierce" and "Barking" metaclasses as parents. An instance of this 
  18447.       new metaclass (that is, "FB-1") is a "FierceBarkingDog" (assuming "Dog " 
  18448.       is a parent). 
  18449.  
  18450.    o  In Technique 2, a new class is created which has parents that are 
  18451.       instances of "Fierce" and "Barking" respectively. That is, "FB-2" is a 
  18452.       "FierceBarkingDog" also (assuming "FierceDog" and "BarkingDog" do not 
  18453.       further specialize "Dog"). 
  18454.  
  18455.    o  In Technique 3, "FB-3", which also is a "FierceBarkingDog", is created by 
  18456.       declaring that its parent is a "BarkingDog" and that its explicit 
  18457.       (syntactically declared) metaclass is "Fierce". 
  18458.  
  18459.   ΓöîΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÉ
  18460.   ΓöéTechnique 1     Technique 2     Technique 3    Γöé
  18461.   Γöé                                               Γöé
  18462.   Γöéinterface       interface       interface      Γöé
  18463.   Γöé                                               Γöé
  18464.   ΓöéFB-1:Dog        FB-2:FierceDog, FB-3:BarkingDogΓöé
  18465.   Γöé                                               Γöé
  18466.   Γöé{               BarkingDog      {              Γöé
  18467.   Γöé                                               Γöé
  18468.   Γöé...             {               ...            Γöé
  18469.   Γöé                                               Γöé
  18470.   Γöéimplementation  ...             implemetaton   Γöé
  18471.   Γöé                                               Γöé
  18472.   Γöé{               Implementation  {              Γöé
  18473.   Γöé                                               Γöé
  18474.   Γöémetaclass       {               metaclass      Γöé
  18475.   Γöé=FierceBarking;                 =Fierce;       Γöé
  18476.   Γöé                                               Γöé
  18477.   Γöé...                ...             ...         Γöé
  18478.   Γöé                                               Γöé
  18479.   Γöé };              };              };            Γöé
  18480.   Γöé                                               Γöé
  18481.   Γöé};              };              };             Γöé
  18482.   Γöé                                               Γöé
  18483.   ΓööΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÿ
  18484.  
  18485.  Figure 1.Three techniques for composing before/after metaclasses. 
  18486.  
  18487.  Note that the explicit metaclass in the SOM IDL of "FB-1" is its derived 
  18488.  class, "FierceBarking". The derived metaclass of "FB-2" is also 
  18489.  "FierceBarking". Lastly, the derived metaclass of "FB-3" is  not  the 
  18490.  metaclass explicitly specified in the SOM IDL; rather, it  too is 
  18491.  "FierceBarking." 
  18492.  
  18493.  
  18494. ΓòÉΓòÉΓòÉ 10.1.3. Notes and advantages of `before/after' usage ΓòÉΓòÉΓòÉ
  18495.  
  18496. Notes on the dispatching of before/after methods: 
  18497.  
  18498.    o  A before (after) method is invoked just once per primary method 
  18499.       invocation. 
  18500.  
  18501.    o  The dispatching of before/after methods is thread-safe. 
  18502.  
  18503.    o  The dispatching of before/after methods is fast. The time overhead for 
  18504.       dispatching a primary method is on the order of N times the time to 
  18505.       invoke a before/after method as a procedure, where N is the total number 
  18506.       of before/after methods to be applied. 
  18507.  
  18508.  In conclusion, consider an example that clearly demonstrates the power of the 
  18509.  composition of before/after metaclasses. Suppose you are creating a class 
  18510.  library that will have n classes. Further suppose there are p properties that 
  18511.  must be included in all combinations for all classes. Potentially, the library 
  18512.  must have n2^p classes. Let us hypothesize that (fortunately) all these 
  18513.  properties can be captured by before/after metaclasses. In this case, the size 
  18514.  of the library is n+p. 
  18515.  
  18516.  The user of such a library need only produce those combinations necessary for 
  18517.  a given application. In addition, note that there is none of the usual 
  18518.  programming. Given the IDL for a combination of before/after metaclasses, the 
  18519.  SOM compiler generates the implementation of the combination (in either C or 
  18520.  C++) with no further manual intervention. 
  18521.  
  18522.  
  18523. ΓòÉΓòÉΓòÉ 10.2. The `SOMMSingleInstance' Metaclass ΓòÉΓòÉΓòÉ
  18524.  
  18525. Sometimes it is necessary to define a class for which only one instance can be 
  18526. created. This is easily accomplished with the SOMMSingleInstance metaclass. 
  18527. Suppose the class "Collie" is an instance of SOMMSingleInstance. The first call 
  18528. to CollieNew creates the one possible instance of "Collie"; hence, subsequent 
  18529. calls to CollieNew return the first (and only) instance. 
  18530.  
  18531. Any class whose metaclass is SOMMSingleInstance gets this requisite behavior; 
  18532. nothing further needs to be done. The first instance created is always returned 
  18533. by the <className>New maro. 
  18534.  
  18535. Alternatively, the method sommGetSingleInstance does the same thing as the 
  18536. <className>New macro. This method invoked on a class object (for example, 
  18537. "Collie") is useful because the call site explicitly shows that something 
  18538. special is occurring and that a new object is not necessarily being created. 
  18539. For this reason, one might prefer the second form of creating a single-instance 
  18540. object to the first. 
  18541.  
  18542. Instances of SOMMSingleInstance keep a count of the number of times somNew and 
  18543. sommGetSingleInstance are invoked. Each invocation of somFree decrements this 
  18544. count. An invocation of somFree does not actually free the single instance 
  18545. until the count reaches zero. 
  18546.  
  18547. SOMMSingleInstance overrides somRenew, somRenewNoInit, somRenewNoInitNoZero, 
  18548. and somRenewNoZero so that a proxy is created in the space indicated in the 
  18549. somRenew* call. This proxy redispatches all methods to the single instance, 
  18550. which is always allocated in heap storage. Note that all of these methods 
  18551. (somRenew*) increment the reference count; therefore, somFree should be called 
  18552. on these objects, too. In this case, somFree decrements the reference and frees 
  18553. the single instance (and, of course, takes no action with respect to the 
  18554. storage indicated in the original somRenew* call). 
  18555.  
  18556. If a class is an instance of SOMMSingleInstance, all of its subclasse are also 
  18557. instances of SOMMSingleInstance. Be aware that this also means that each 
  18558. subclass is allowed to have only a single instance. (This may seem obvious. 
  18559. However, it is a common mistake to create a framework class that must have a 
  18560. single instance, while at the same time expecting users of the framework to 
  18561. subclass the single instance class. The result is that two single-instance 
  18562. objects are created: one for the framework class and one for the subclass. One 
  18563. technique that can mitigate this scenario is based on the use of 
  18564. somSubstituteClass. In this case, the creator of the subclass must substitute 
  18565. the subclass for the framework class--before the instance of the framework 
  18566. class is created.) 
  18567.  
  18568.  
  18569. ΓòÉΓòÉΓòÉ 10.3. The `SOMMTraced' Metaclass ΓòÉΓòÉΓòÉ
  18570.  
  18571. SOMMTraced is a metaclass that facilitates tracing of method invocations. If 
  18572. class "Collie" is an instance of SOMMTraced (if SOMMTraced is the metaclass of 
  18573. "Collie"), any method invoked on an instance of "Collie" is traced. That is, 
  18574. before the method begins execution, a message prints (to standard output) 
  18575. giving the actual parameters. Then, after the method completes execution, a 
  18576. second message prints giving the returned value. This behavior is attained 
  18577. merely by being an instance of the SOMMTraced metaclass. 
  18578.  
  18579. If the class being traced is contained in the Interface Repository, actual 
  18580. parameters are printed as part of the trace. If the class is not contained in 
  18581. the Interface Repository, an ellipsis is printed. 
  18582.  
  18583. To be more concrete, suppose that the class "Collie" is a child of "Dog" and is 
  18584. an instance of SOMMTraced. Because SOMMTraced is the metaclass of "Collie," any 
  18585. method invoked on "Lassie" (an instance of "Collie") is traced. 
  18586.  
  18587. It is easy to use SOMMTraced: Just make a class an instance of SOMMTraced in 
  18588. order to get tracing. 
  18589.  
  18590. There is one more step for using SOMMTraced: Nothing prints unless the 
  18591. environment variable SOMM_TRACED is set. If it is set to the empty string, all 
  18592. traced classes print. If SOMM_TRACED is not the empty string, it should be set 
  18593. to the list of names of classes that should be traced. For example, the 
  18594. following command turns on printing of the trace for "Collie", but not for any 
  18595. other traced class: 
  18596.  
  18597. export  SOMM_TRACED=Collie      (on AIX)
  18598. SET     SOMM_TRACED=Collie      (on OS/2 or Windows)
  18599.  
  18600. The example below shows the IDL needed to create a traced dog class: Just run 
  18601. the appropriate emitter to get an implementation binding. 
  18602.  
  18603. SOM IDL for `TracedDog' class 
  18604.  
  18605. #include "dog.idl"
  18606. #include <somtrcls.idl>
  18607. interface TracedDog : Dog
  18608. {
  18609. #ifdef __SOMIDL__
  18610. implementation
  18611. {
  18612.   //# Class Modifiers
  18613.   filestem = trdog;
  18614.   metaclass = SOMMTraced;
  18615. };
  18616. #endif /* __SOMIDL__ */
  18617. };
  18618.  
  18619.  
  18620. ΓòÉΓòÉΓòÉ 10.4. Error Codes ΓòÉΓòÉΓòÉ
  18621.  
  18622. It is possible to receive the following messages from the Metaclass Framework 
  18623. while an application is running. 
  18624.  
  18625.  60001     An attempt was made to construct a class with SOMMSingleInstance as 
  18626.            a metaclass constraint. (This may occur indirectly because of the 
  18627.            construction of a derived metaclass). The initialization of the 
  18628.            class failed because somInitMIClass defined by SOMMSingleInstance is 
  18629.            in conflict with another metaclass that has overridden somNew. That 
  18630.            is, some other metaclass has already claimed the right to return the 
  18631.            value for somNew. 
  18632.  
  18633.  60002     An attempt was made to construct a class with SOMMSingleInstance as 
  18634.            a metaclass constraint. (This may occur indirectly because of the 
  18635.            construction of a derived metaclass). The initialization of the 
  18636.            class failed because somInitMIClass defined by SOMMSingleInstance is 
  18637.            in conflict with another metaclass that has overridden somFree. That 
  18638.            is, some other metaclass has already claimed this right to override 
  18639.            somFree. 
  18640.  
  18641.  60004     An invocation of somrRepInit was made with a logging type other than 
  18642.            `o' or `v'. 
  18643.  
  18644.  60005     The sommBeforeMethod or the sommAfterMethod was invoke on a 
  18645.            SOMRReplicbleObject whose logging type is other than `o' or `v'. 
  18646.            This error cannot occur normally. The likely cause is that some 
  18647.            method invoked on another object has overwritten this object's 
  18648.            memory. 
  18649.  
  18650.  60006     A Before/After Metaclass must override both sommBeforeMethod an 
  18651.            sommAfterMethod. This message indicates an attempt to create a 
  18652.            Before/After Metaclass where only one of the above methods is 
  18653.            overridden. 
  18654.  
  18655.  
  18656. ΓòÉΓòÉΓòÉ 11. The Event Management Framework ΓòÉΓòÉΓòÉ
  18657.  
  18658. The Event Management Framework is a central facility for registering all events 
  18659. of an application. Such a registration facilitates grouping of various 
  18660. application events and waiting on multiple events in a single event-processing 
  18661. loop. This facility is used by the Replication Framework and by DSOM to wait on 
  18662. their respective events of interest. The Event Management Framework must also 
  18663. be used by any interactive application that contains DSOM or replicated 
  18664. objects. 
  18665.  
  18666.  
  18667. ΓòÉΓòÉΓòÉ 11.1. Event Management Basics ΓòÉΓòÉΓòÉ
  18668.  
  18669. The Event Management Framework consists of an Event Manager (EMan) class, a 
  18670. Registration Data class and several Event classes. It provides a way to 
  18671. organize various application events into groups and to process all events in a 
  18672. single event-processing loop. The need for this kind of facility is seen very 
  18673. clearly in interactive applications that also need to process some background 
  18674. events (say, messages arriving from a remote process). Such applications must 
  18675. maintain contact with the user while responding to events coming from other 
  18676. sources. 
  18677.  
  18678. One solution in a multi-threaded environment is to have a different thread 
  18679. service each different source of events. For a single-threaded environment it 
  18680. should be possible to recognize and process all events of interest in a single 
  18681. main loop. EMan offers precisely this capability. EMan can be useful even when 
  18682. multiple threads are available, because of its simple programming model. It 
  18683. avoids contention for common data objects between EMan event processing and 
  18684. other main-loop processing activity. 
  18685.  
  18686.  
  18687. ΓòÉΓòÉΓòÉ 11.1.1. Model of EMan usage ΓòÉΓòÉΓòÉ
  18688.  
  18689. The programming model of EMan is similar to that of many GUI toolkits. The main 
  18690. program initializes EMan and then registers interest in various types of 
  18691. events. The main program ends by calling a non-returning function of EMan that 
  18692. waits for events and dispatches them as and when they occur. In short, the 
  18693. model includes steps that: 
  18694.  
  18695.    1. Initialize the Event Manager, 
  18696.    2. Register with EMan for all events of interest, and 
  18697.    3. Hand over control to EMan to loop forever and to dispatch events. 
  18698.  
  18699.  The Event Manager is a SOM object and is an instance of the SOMEEMan class. 
  18700.  Since any application requires only one instance of this object, the SOMEEMan 
  18701.  class is an instance of the SOMMSingleInstance class. Creation and 
  18702.  initialization of the Event Manager is accomplished by a function call to 
  18703.  SOMEEmanNew. 
  18704.  
  18705.  Currently, EMan supports the four kinds of events described in the following 
  18706.  topic. An application can register or unregister for events in a callback 
  18707.  routine (explained below) even after control has been turned over to EMan. 
  18708.  
  18709.  
  18710. ΓòÉΓòÉΓòÉ 11.1.2. Event types ΓòÉΓòÉΓòÉ
  18711.  
  18712. Event types are categorized as follows: 
  18713.  
  18714.    o  Timer events 
  18715.  
  18716.       These can be either one-time timers or interval timers. 
  18717.  
  18718.    o  Sink events (sockets, file descriptors, and message queues) 
  18719.  
  18720.       On AIX, this includes file descriptors for input/output files, sockets, 
  18721.       pipes, and message queues. On OS/2 and Windows, only TCP/IP sockets are 
  18722.       supported. 
  18723.  
  18724.       Note:On OS/2 and Windows, the Sockets classes for NetBIOS (NBSockets) and 
  18725.       Novell IPX/SPX (IPXSockets) are primarily intended for use by DSOM and 
  18726.       the Replication Framework, not for general application programming. (The 
  18727.       Replication Framework is available as part of the full-capability 
  18728.       SOMobjects Developer Toolkit.) 
  18729.  
  18730.    o  Client events (any event that the application wants to queue with EMan) 
  18731.  
  18732.       These events are defined, created, processed, and destroyed by the 
  18733.       application. EMan simply acts as a place to queue these events for 
  18734.       processing. EMan dispatches these client events whenever it sees them. 
  18735.       Typically, this happens immediately after the event is queued. 
  18736.  
  18737.    o  Work procedure events (procedures that can be called when there is no 
  18738.       other event) 
  18739.  
  18740.       These are typically background procedures that the application intends to 
  18741.       execute when there are spare processor cycles. When there are no other 
  18742.       events to process, EMan calls all registered work procedures. 
  18743.  
  18744.  The Event Management Framework is extendible (that is, other event types can 
  18745.  be added to it) through subclassing. The event types currently supported by 
  18746.  EMan are at a sufficiently low level so as to enable building other higher 
  18747.  level application events on top of them. For example, you can build an X-event 
  18748.  handler by simply registering the file descriptor for the X connection with 
  18749.  EMan and getting notified when any X-event occurs. 
  18750.  
  18751.  
  18752. ΓòÉΓòÉΓòÉ 11.1.3. Registration ΓòÉΓòÉΓòÉ
  18753.  
  18754. This topic illustrates how to register for an event type. 
  18755. Callbacks 
  18756.  
  18757. The programmer decides what processing needs to be done when an event occurs 
  18758. and then places the appropriate code either in a procedure or in a method of an 
  18759. object. This procedure or method is called a callback. (The callback is 
  18760. provided to EMan at the time of registration and is called by EMan when a 
  18761. registered event occurs.) The signature of a callback is fixed by the framework 
  18762. and must have one of the following three signatures: 
  18763.  
  18764. void SOMLINK EMRegProc(SOMEEvent, void *);
  18765. void SOMLINK EMMethodProc(SOMObject, SOMEEvent, void *);
  18766. void SOMLINK EMMethodProcEv(SOMObject, Environment *Ev,
  18767.                             SOMEEvent, void *);
  18768. /* On OS/2, they all use "system" linkage  */
  18769. /* On Windows, the SOMLINK keyword is Not included if the
  18770.  * application is intended to support multiple instances. */
  18771.  
  18772. The three specified prototypes correspond to a simple callback procedure, a 
  18773. callback method using OIDL call style, and a callback method using IDL call 
  18774. style. The parameter type SOMEEvent refers to an event object passed by EMan to 
  18775. the callback.  Event objects are described below. 
  18776.  
  18777. NOTE: When the callbacks are methods, EMan calls these methods using 
  18778. Name-lookup Resolution (see Chapter 5 Section 5.3 on Method Resolution). One of 
  18779. the implications is that at the time of registration EMan queries the target 
  18780. object's class object to provide a method pointer for the method name supplied 
  18781. to it. Eman uses this pointer for making event callbacks. 
  18782. Event classes 
  18783.  
  18784. All event objects are instances of either the SOMEEvent class or a subclass of 
  18785. it. The hierarchy of event classes is as follows: 
  18786.  
  18787. SOMObjectхххххххххSOMEEventххххххххх&Ju.ххххххххххSOMETimerEvent
  18788.  
  18789.                                     ╤à╤à╤à╤à╤à╤à╤à╤à╤à╤àSOMEClientEvent
  18790.  
  18791.                                     ╤à╤à╤à╤à╤à╤à╤à╤à╤à╤àSOMESinkEvent
  18792.  
  18793.                                     ╤à╤à╤à╤à╤à╤à╤à╤à╤à╤àSOMEWorkProcEvent
  18794.  
  18795. When called by EMan, a callback expects the appropriate event instance as a 
  18796. parameter. For example, a callback registered for a timer event expects a 
  18797. SOMETimerEvent instance from EMan. 
  18798. EMan parameters 
  18799.  
  18800. Several method calls in the Event Management Framework make use of bit masks 
  18801. and constants as parameters (for example, EMSinkEvent or EMInputReadMask). 
  18802. These methods are defined in the include file "eventmsk.h". When a user plans 
  18803. to extend the Event Management Framework, care must be taken to avoid name and 
  18804. value collisions with the definitions in "eventmsk.h". For convenience, the 
  18805. contents of the "eventmsk.h" file are shown below. 
  18806.  
  18807. #ifndef H_EVENTMASKDEF
  18808. #define H_EVENTMASKDEF
  18809.  
  18810. /* Event Types */
  18811. #define EMTimerEvent                    54
  18812. #define EMSignalEvent                   55
  18813. #define EMSinkEvent                     56
  18814.  
  18815. #define EMWorkProcEvent                 57
  18816.  
  18817. #define EMClientEvent                   58
  18818.  
  18819. #define EMMsgQEvent                     59
  18820.  
  18821. /* Sink input/output condition mask */
  18822.  
  18823. #define EMInputReadMask                 (1L<0)
  18824. #define EMInputWriteMask                (1L<1)
  18825. #define EMInputExceptMask               (1L<2)
  18826.  
  18827. /* Process Event mask */
  18828.  
  18829. #define EMProcessTimerEvent             (1L<0)
  18830. #define EMProcessSinkEvent              (1L<1)
  18831. #define EMProcessWorkProcEvent          (1L<2)
  18832. #define EMProcessClientEvent            (1L<3)
  18833. #define EMProcessAllEvents              (1L<6)
  18834.  
  18835. #endif   /* H_EVENTMASKDEF */
  18836.  
  18837. Registering for events 
  18838.  
  18839. In addition to the event classes, the Event Management Framework uses a 
  18840. registration data class (SOMEEMRegisterData) to capture all event-related 
  18841. registration information. The procedure for registering interest in an event is 
  18842. as follows: 
  18843.  
  18844.    1. Create an instance of the SOMEEMRegisterData class (this will be referred 
  18845.       to as a "RegData" object). 
  18846.  
  18847.    2. Set the event type of "RegData." 
  18848.  
  18849.    3. Set the various fields of "RegData" to supply information about the 
  18850.       particular event for which an interest is being registered. 
  18851.  
  18852.    4. Call the registration method of EMan, using "RegData" and the callback 
  18853.       method information as parameters. The callback information varies, 
  18854.       depending upon whether it is a simple procedure, a method called using 
  18855.       OIDL call style, or a method called using IDL call style. 
  18856.  
  18857.  The following code segment illustrates how to register input interest in a 
  18858.  socket "sock" and provide a callback procedure "ReadMsg". 
  18859.  
  18860.   data = SOMEEMRegisterDataNew( );       /* create a RegData object */
  18861.   _someClearRegData(data, Ev);
  18862.   _someSetRegDataEventMask(data,Ev,EMSinkEvent,NULL); /* Event type */
  18863.   _someSetRegDataSink(data, Ev, sock);     /* provide the socket id */
  18864.   _someSetRegDataSinkMask(data,Ev, EMInputReadMask );
  18865.                                                    /*input interest */
  18866.   regId = _someRegisterProc(some_gEMan,Ev,data,ReadMsg,"UserData" );
  18867.   /* some_gEMan points to EMan. The last parameter "userData" is any
  18868.      data the user wants to be passed to the callback procedure as a
  18869.      second parameter */
  18870.  
  18871.  
  18872. ΓòÉΓòÉΓòÉ 11.1.4. Unregistering for events ΓòÉΓòÉΓòÉ
  18873.  
  18874. One can unregister interest in a given event type at any time. To unregister, 
  18875. you must provide the registration id returned by EMan at the time of 
  18876. registration. Unregistering a non-existent event (such as, an invalid 
  18877. registration id) is a no-op. The following example unregisters the socket 
  18878. registered above: 
  18879.  
  18880. _someUnRegister(some_gEMan, Ev, regId);
  18881.  
  18882.  
  18883. ΓòÉΓòÉΓòÉ 11.1.5. An example callback procedure ΓòÉΓòÉΓòÉ
  18884.  
  18885. The following code segment illustrates how to write a callback procedure: 
  18886.  
  18887. void SOMLINK ReadMsg( SOMEEvent  event, void  *targetData )
  18888. {
  18889. int sock;
  18890.     printf( "Data = %s\n", targetData );
  18891.     switch( _somevGetEventType( event )) {
  18892.     case  EMSinkEvent:
  18893.         printf("callback: Perceived Sink Event\n");
  18894.         sock = _somevGetEventSink(event);
  18895.         /* code to read the message off the socket */
  18896.         break;
  18897.     default: printf("Unknown Event type in socket callback\n");
  18898.     }
  18899. }
  18900. /* On OS/2, "system" linkage is also required.  */
  18901. /* On Windows, callbacks do not use the SOMLINK keyword if
  18902.  * the application is intended to support multiple instances. */
  18903.  
  18904.  
  18905. ΓòÉΓòÉΓòÉ 11.1.6. Generating client events ΓòÉΓòÉΓòÉ
  18906.  
  18907. While the other events are caused by the operating system (for example, Timer), 
  18908. by I/O devices, or by external processes, client events are caused by the 
  18909. application itself. The application creates these events and enqueues them with 
  18910. EMan. When client events are dispatched, they are processed in a callback 
  18911. routine just like any other event. The following code segment illustrates how 
  18912. to create and enqueue client events. 
  18913.  
  18914. clientEvent1 = SOMEClientEventNew();  /* create a client event */
  18915. _somevSetEventClientType( clientEvent1, Ev, "MyClientType" );
  18916. _somevSetEventClientData( clientEvent1, Ev,
  18917.                                    "I can give any data here");
  18918. /* assuming that "MyClientType" is already registered with EMan */
  18919. /* enqueue the above event with EMan */
  18920. _someQueueEvent(some_gEMan, Ev, clientEvent1);
  18921.  
  18922.  
  18923. ΓòÉΓòÉΓòÉ 11.1.7. Examples of using other events ΓòÉΓòÉΓòÉ
  18924.  
  18925. The sample program shipped with the Event Management Framework illustrates the 
  18926. tasks listed below. (Due to its large size, the source code is not included 
  18927. here.) 
  18928.  
  18929.    o  Registering and unregistering for Timer events. 
  18930.  
  18931.    o  Registering and unregistering for Workproc events. 
  18932.  
  18933.    o  Registering an AIX Message Queue, sending messages on it, and 
  18934.       unregistering the Message Queue. 
  18935.  
  18936.    o  Registering a stream socket that listens to incoming connection requests. 
  18937.       Also, sockets connecting, accepting a connection, and sending/receiving 
  18938.       messages through EMan. 
  18939.  
  18940.    o  Registering a file descriptor on AIX and reading one line of the file at 
  18941.       a time in a callback. 
  18942.  
  18943.  
  18944. ΓòÉΓòÉΓòÉ 11.1.8. Processing events ΓòÉΓòÉΓòÉ
  18945.  
  18946. After all registrations are finished, an application typically turns over 
  18947. control to EMan and is completely event driven thereafter. Typically, an 
  18948. application main program ends with the following call to EMan: 
  18949.  
  18950. _someProcessEvents(some_gEMan, Ev);
  18951.  
  18952. An equivalent way to process events is to write a main loop and call 
  18953. someProcessEvent from inside the main loop, as indicated: 
  18954.  
  18955. while (1) { /* do forever */
  18956.       _someProcessEvent( some_gEMan, Ev, EMProcessTimerEvent  Γöé
  18957.                                          EMProcessSinkEvent   Γöé
  18958.                                          EMProcessClientEvent Γöé
  18959.                                          EMProcessWorkProcEvent );
  18960.       /***  Do other main loop work, as needed. ***/
  18961. }
  18962.  
  18963. The second way allows more precise control over what type of events to process 
  18964. in each call. The example above enables all four types to be processed. The 
  18965. required subset is formed by logically OR'ing the appropriate bit constants 
  18966. (these are defined in "eventmsk.h)".  Another difference is that the second way 
  18967. is a non-blocking call to EMan. That is, if there are no events to process, 
  18968. control returns to the main loop immediately, whereas someProcessEvents is a 
  18969. non-returning blocking call. For most applications, the first way of calling 
  18970. EMan is better, since it does not waste processor cycles when there are no 
  18971. events to process. 
  18972.  
  18973.  
  18974. ΓòÉΓòÉΓòÉ 11.1.9. Interactive applications ΓòÉΓòÉΓòÉ
  18975.  
  18976. Interactive applications need special attention when coupled with EMan. Once 
  18977. control is turned over to EMan by calling someProcessEvents, a single-threaded 
  18978. application (for example, on AIX) has no way of responding to keyboard input. 
  18979. The user must register interest in "stdin" with EMan and provide a callback 
  18980. function that handles keyboard input. In a multi-threaded environment (for 
  18981. example, OS/2), this problem can be solved by spawning a thread to execute 
  18982. someProcessEvents and another to handle keyboard input. (These two options are 
  18983. illustrated in the sample program shipped with the Event Management Framework.) 
  18984.  
  18985.  
  18986. ΓòÉΓòÉΓòÉ 11.2. Event Manager Advanced Topics ΓòÉΓòÉΓòÉ
  18987.  
  18988.  
  18989. ΓòÉΓòÉΓòÉ 11.2.1. Threads and thread safety ΓòÉΓòÉΓòÉ
  18990.  
  18991. As indicated earlier, on OS/2, interactive programs call someProcessEvents in 
  18992. one thread and process keyboard input in a separate thread. (This recommended 
  18993. usage is illustrated in the sample program). The event manager object (EMan) is 
  18994. thread safe in the sense that concurrent method invocations on EMan are 
  18995. serialized. Even when someProcessEvents is invoked in a thread and other 
  18996. methods of EMan are invoked from other threads, EMan still preserves its data 
  18997. integrity. However, when Eman dispatches an event, a callback can call methods 
  18998. on the same data objects as the other interactive thread(s). The user must 
  18999. protect such data objects using appropriate concurrency control techniques (for 
  19000. example by using semaphores). 
  19001.  
  19002. One must also be aware of some deadlock possibilities. Consider the following 
  19003. situation. EMan code holds some SOMobjects Toolkit semaphores while it is 
  19004. running (for example, while in someProcessEvents). A user-defined object 
  19005. protects its data by requiring its methods to acquire and release a sempahore 
  19006. on the object. If a separate thread running in this object were to call an 
  19007. operation that requires a SOMobjects Toolkit semaphore (which is currently held 
  19008. by EMan) and if concurrently EMan dispatches an event whose callback invokes a 
  19009. method of this object, a deadlock occurs. Two possibilities exist to cope with 
  19010. such a situation: One is to acquire all needed semaphores ahead of time, and 
  19011. the other is to abort the operation when you fail to obtain a semaphore. To 
  19012. achieve mutual exclusion with EMan, you can call the methods someGetEManSem and 
  19013. someReleaseEmanSem. These methods acquire and release the SOMobject Developer 
  19014. Toolkit semaphores that EMan uses. 
  19015.  
  19016.  
  19017. ΓòÉΓòÉΓòÉ 11.2.2. Writing an X or MOTIF application ΓòÉΓòÉΓòÉ
  19018.  
  19019. Although the Event Manager does not recognize X events, an X or MOTIF 
  19020. application can be integrated with EMan as follows. First, the necessary 
  19021. initialization of X or MOTIF should be performed. Next, using the Xlib macro 
  19022. "ConnectionNumber" or the "XConnectionNumber" function, you can obtain the file 
  19023. descriptor of the X connection. This file descriptor can be registered with 
  19024. EMan as a sink. It can be registered for both input events and exception 
  19025. events. When there is any activity on this X file descriptor, the 
  19026. developer-provided callback is invoked. The callback can receive the X-event, 
  19027. analyze it, and do further dispatching. See the example program in Chapter 9, 
  19028. "The Replication Framework" (section 9.7). 
  19029.  
  19030.  
  19031. ΓòÉΓòÉΓòÉ 11.2.3. Extending EMan ΓòÉΓòÉΓòÉ
  19032.  
  19033. The current event manager can be extended without having access to the source 
  19034. code. The use of EMan in an X or MOTIF application mentioned above is just one 
  19035. such example. Several other extensions are possible. For example, new event 
  19036. types can be defined by subclassing either directly from SOMEEvent class or 
  19037. from any of its subclasses in the framework. There are three main problems to 
  19038. solve in adding a new event type: 
  19039.  
  19040.    o  How to register a new event type with EMan? 
  19041.  
  19042.    o  How to make EMan recognize the occurrence of the new event? 
  19043.  
  19044.    o  How to make EMan create and send the new event object (a subclass of 
  19045.       SOMEEvent) to the callback when the event is dispatched? 
  19046.  
  19047.  Because the registration information is supplied with appropriate "set" 
  19048.  methods of a RegData object, the RegData object should be extended to include 
  19049.  additional methods.  This can be achieved by subclassing from 
  19050.  SOMEEMRegisterData and building a new registration data class that has methods 
  19051.  to "set" and "get" additional fields of information that are needed to 
  19052.  describe the new event types fully. To handle registrations with instances of 
  19053.  new registration data subclass, we must also subclass from SOMEEMan and 
  19054.  override the someRegister and the someUnRegister methods. These methods should 
  19055.  handle the information in the new fields introduced by the new registration 
  19056.  data class and call parent methods to handle the rest. 
  19057.  
  19058.  Making EMan recognize the occurrence of the new event is primarily limited by 
  19059.  the primitive events EMan can wait on. Thus the new event would have to be 
  19060.  wrapped in a primitive event that EMan can recognize. For example, to wait on 
  19061.  a message queue on OS/2 concurrently with other EMan events, a separate thread 
  19062.  can be made to wait on the message queue and to enqueue a client event with 
  19063.  EMan when a message arrives on this message queue. We can thus bring multiple 
  19064.  event sources into the single EMan main loop. 
  19065.  
  19066.  The third problem of creating new event objects unknown to EMan can be easily 
  19067.  done by applying the previous technique of wrapping the new event in terms of 
  19068.  a known event. In a callback routine of the known event, we can create and 
  19069.  dispatch the new event unknown to EMan. Of course, this does introduce an 
  19070.  intermediate callback routine which would not be needed if EMan directly 
  19071.  understood the new event type. 
  19072.  
  19073.  A general way of extending EMan is to look for newly defined event types by 
  19074.  overriding someProcessEvent and someProcessEvents in a subclass of EMan. 
  19075.  
  19076.  
  19077. ΓòÉΓòÉΓòÉ 11.2.4. Using EMan from C++ ΓòÉΓòÉΓòÉ
  19078.  
  19079. The Event Management framework can be used from C++ just like any other 
  19080. framework in the SOMobjects Toolkit. You must ensure that the C++ usage 
  19081. bindings (that is, the .xh files) are available for the Event Management 
  19082. Framework classes. These .xh files are generated by the SOM Compiler in the 
  19083. SOMobjects Toolkit when the -s option includes an xh emitter. 
  19084.  
  19085.  
  19086. ΓòÉΓòÉΓòÉ 11.2.5. Using EMan from other languages ΓòÉΓòÉΓòÉ
  19087.  
  19088. The event manager and the other classes can be used from other languages, 
  19089. provided usage bindings are available for them. These usage bindings are 
  19090. produced from .idl files of the framework classes by the appropriate language 
  19091. emitter. 
  19092.  
  19093.  
  19094. ΓòÉΓòÉΓòÉ 11.2.6. Tips on using EMan ΓòÉΓòÉΓòÉ
  19095.  
  19096. The following are some do's and don'ts for EMan: 
  19097.  
  19098.    o  Eman callback procedures or methods must return quickly. You cannot wait 
  19099.       for long periods of time to return from the callbacks. If such long 
  19100.       delays occur, then the application may not notice some subsequent events 
  19101.       in time to process them meaningfully (for example, a timer event may not 
  19102.       be noticed until long after it occurred). 
  19103.  
  19104.    o  It follows from the previous tip that you should not do independent 
  19105.       "select" system calls on file descriptors while inside a callback.  (This 
  19106.       applies to sockets and message queues, as well.) In general, a callback 
  19107.       should not do any blocking of system calls. If an application must do 
  19108.       this, then it must be done with a small timeout value. 
  19109.  
  19110.    o  Since EMan callbacks must return quickly, no callback should wait on a 
  19111.       semaphore indefinitely. If a callback has to obtain some semaphores 
  19112.       during its processing, then the callback should try to acquire all of 
  19113.       them at the very beginning, and should be prepared to abort and return to 
  19114.       EMan if it fails to acquire the necessary semaphores. 
  19115.  
  19116.    o  EMan callback methods are called using name-lookup resolution. Therefore, 
  19117.       the parameters to an EMan registration call must be such that the class 
  19118.       object of the object parameter must be able to provide a pointer to the 
  19119.       method indicated by the method parameter. Although this requirement is 
  19120.       satisfied in a majority of cases, there are exceptions.  For example, if 
  19121.       the object is a proxy (in the DSOM sense) to a remote object, then the 
  19122.       "real" class object cannot provide a meaningful method pointer. Also note 
  19123.       that, when somDspatch is overridden, the effect of such an override will 
  19124.       not  apply  to the callback from EMan.  Do not use a method callback in 
  19125.       these situations; instead, use a procedure callback. 
  19126.  
  19127.  
  19128. ΓòÉΓòÉΓòÉ 11.3. Limitations ΓòÉΓòÉΓòÉ
  19129.  
  19130. The present implementation of the Event Management framework has the 
  19131. limitations described below. For a more up-to-date list of limitations, refer 
  19132. to the README file on EMan in the SOMobjects Developer Toolkit. 
  19133.  
  19134.    o  EMan supports registering a maximum of 64 AIX message queues. 
  19135.  
  19136.    o  EMan can only wait on file descriptors (including files, pipes, sockets, 
  19137.       and message queues) on AIX, and socket identifiers on OS/2. 
  19138.  
  19139.    o  EMan supports registering a maximum of FILENO (the AIX limit on maximum 
  19140.       number of open files) file descriptors on AIX, and FD_SETSIZE socket 
  19141.       identifiers on OS/2 (FD_SETSIZE is defined by the TCP/IP product). 
  19142.  
  19143.  
  19144. ΓòÉΓòÉΓòÉ 11.3.1. Use of EMan DLL ΓòÉΓòÉΓòÉ
  19145.  
  19146. The Event Manager Framework uses a Sockets "select" call to wait on multiple 
  19147. sockets.  At the time of EMan creation, the SOMEEMan class object loads one of 
  19148. the Sockets subclass DLLs, based on the value of the environment variable 
  19149. SOMSOCKETS. This environment variable should name the implementation class of 
  19150. sockets (see Appendix E describing the Sockets abstract class and the specific 
  19151. implementation DLLs available with the SOMobjects Toolkit.) The current choices 
  19152. for this environment variable are TCPIPSockets, (and TCPIPSockets32 for OS/2), 
  19153. NBSockets, and IPXSockets . 
  19154.  
  19155.  
  19156. ΓòÉΓòÉΓòÉ 12. Appendixes ΓòÉΓòÉΓòÉ
  19157.  
  19158.  
  19159. ΓòÉΓòÉΓòÉ 13. SOMobjects Error Codes ΓòÉΓòÉΓòÉ
  19160.  
  19161.  
  19162. ΓòÉΓòÉΓòÉ 13.1. SOM Kernel Error Codes ΓòÉΓòÉΓòÉ
  19163.  
  19164. Following are error codes with messages/explanations for the SOM kernel and the 
  19165. various frameworks of the SOMobjects Developer Toolkit. 
  19166.  
  19167.  Value     Symbolic Name and Description 
  19168.  
  19169.  20011     SOMERROR_CCNullClass 
  19170.            The somDescendedFrom method was passed a null class argument. 
  19171.  
  19172.  20029     SOMERROR_SompntOverflow 
  19173.            The internal buffer used in somPrintf overflowed. 
  19174.  
  19175.  20039     SOMERROR_MethodNotFound 
  19176.            somFindMethodOk failed to find the indicated method. 
  19177.  
  19178.  20049     SOMERROR_StaticMethodTableOverflow 
  19179.            A Method-table overflow occurred in somAddStaticMethod. 
  19180.  
  19181.  20059     SOMERROR_DefaultMethod 
  19182.            The somDefaultMethod was called; a defined method probably was not 
  19183.            added before it was invoked. 
  19184.  
  19185.  20069     SOMERROR_MissingMethod 
  19186.            The specified method was not defined on the target object. 
  19187.  
  19188.  20079     SOMERROR_BadVersion 
  19189.            An attempt to load, create, or use a version of a class-object 
  19190.            implementation is incompatible with the using program. 
  19191.  
  19192.  20089     SOMERROR_NullId 
  19193.            The SOM_CheckId was given a null ID to check. 
  19194.  
  19195.  20099     SOMERROR_OutOfMemory 
  19196.            Memory is exhausted. 
  19197.  
  19198.  20109     SOMERROR_TestObjectFailure 
  19199.            The somObjectTest found problems with the object it was testing. 
  19200.  
  19201.  20119     SOMERROR_FailedTest 
  19202.            The somTest detected a failure; generated only by test code. 
  19203.  
  19204.  20121     SOMERROR_ClassNotFound 
  19205.            The somFindClass could not find the requested class. 
  19206.  
  19207.  20131     SOMERROR_OldMethod 
  19208.            An old-style method name was used; change to an appropriate name. 
  19209.  
  19210.  20149     SOMERROR_CouldNotStartup 
  19211.            The somEnvironmentNew failed to complete. 
  19212.  
  19213.  20159     SOMERROR_NotRegistered 
  19214.            The somUnloadClassFile argument was not a registered class. 
  19215.  
  19216.  20169     SOMERROR_BadOverride 
  19217.            The somOverrideSMethod was invoked for a method that was not defined 
  19218.            in a parent class. 
  19219.  
  19220.  20179     SOMERROR_NotImplementedYet 
  19221.            The method raising the error message is not implemented yet. 
  19222.  
  19223.  20189     SOMERROR_MustOverride 
  19224.            The method raising the error message should have been overridden. 
  19225.  
  19226.  20199     SOMERROR_BadArgument 
  19227.            An argument to a core SOM method failed a validity test. 
  19228.  
  19229.  20219     SOMERROR_NoParentClass 
  19230.            During the creation of a class object, the parent class could not be 
  19231.            found. 
  19232.  
  19233.  20229     SOMERROR_NoMetaClass 
  19234.            During the creation of a class object, the metaclass object could 
  19235.            not be found. 
  19236.  
  19237.  
  19238. ΓòÉΓòÉΓòÉ 13.2. DSOM Error Codes ΓòÉΓòÉΓòÉ
  19239.  
  19240. The  following table lists the error codes that may be encountered when using 
  19241. DSOM. 
  19242.  
  19243.  Value     Description 
  19244.  
  19245.  30001     SOMDERROR_NoMemory 
  19246.            Memory is exhausted. 
  19247.  
  19248.  30002     SOMDERROR_NotImplemented 
  19249.            Function or method has a null implementation. 
  19250.  
  19251.  30003     SOMDERROR_UnexpectedNULL 
  19252.            Internal error:  a pointer variable was found to be NULL, 
  19253.            unexpectedly. 
  19254.  
  19255.  30004     SOMDERROR_IO 
  19256.            I/O error while accessing a file located in SOMDDIR. 
  19257.  
  19258.  30005     SOMDERROR_BadVersion 
  19259.            Internal error:  incorrect version of an object reference data 
  19260.            table. 
  19261.  
  19262.  30006     SOMDERROR_ParmSize 
  19263.            Internal error:  a parameter of incorrect size was detected. 
  19264.  
  19265.  30007     SOMDERROR_HostName 
  19266.            Communications error:  unable to retrieve local host name. 
  19267.  
  19268.  30008     SOMDERROR_HostAddress 
  19269.            Communications error:  unable to retrieve local host address. 
  19270.  
  19271.  30009     SOMDERROR_SocketCreate 
  19272.            Communications error:  unable to create socket. 
  19273.  
  19274.  30010     SOMDERROR_SocketBind 
  19275.            Communications error:  unable to bind address to socket. 
  19276.  
  19277.  30011     SOMDERROR_SocketName 
  19278.            Communications error:  unable to query socket information. 
  19279.  
  19280.  30012     SOMDERROR_SocketReceive 
  19281.            Communications error:  unable to receive message from socket. 
  19282.  
  19283.  30013     SOMDERROR_SocketSend 
  19284.            Communications error:  unable to send message to socket. 
  19285.  
  19286.  30014     SOMDERROR_SocketIoctl 
  19287.            Communications error:  unable to set socket blocking state. 
  19288.  
  19289.  30015     SOMDERROR_SocketSelect 
  19290.            Communications error:  unable to select on socket. 
  19291.  
  19292.  30016     SOMDERROR_PacketSequence 
  19293.            Communications error:  unexpected message packet received. 
  19294.  
  19295.  30017     SOMDERROR_PacketTooBig 
  19296.            Communications error:  packet too big for allocated message space. 
  19297.  
  19298.  30018     SOMDERROR_AddressNotFound 
  19299.            Uninitialized DSOM communications object. 
  19300.  
  19301.  30019     SOMDERROR_NoMessages 
  19302.            No messages available (and caller specified "no wait"). 
  19303.  
  19304.  30020     SOMDERROR_UnknownAddress 
  19305.            Invalid client or server address. 
  19306.  
  19307.  30021     SOMDERROR_RecvError 
  19308.            Communications error during receive. 
  19309.  
  19310.  30022     SOMDERROR_SendError 
  19311.            Communications error during send. 
  19312.  
  19313.  30023     SOMDERROR_CommTimeOut 
  19314.            Communications timeout. 
  19315.  
  19316.  30024     SOMDERROR_CannotConnect 
  19317.            Unable to initialize connection information. 
  19318.  
  19319.  30025     SOMDERROR_BadConnection 
  19320.            Invalid connection information detected. 
  19321.  
  19322.  30026     SOMDERROR_NoHostName 
  19323.            Unable to get host name. 
  19324.  
  19325.  30027     SOMDERROR_BadBinding 
  19326.            Invalid server location information in proxy object. 
  19327.  
  19328.  30028     SOMDERROR_BadMethodName 
  19329.            Invalid method name in request message. 
  19330.  
  19331.  30029     SOMDERROR_BadEnvironment 
  19332.            Invalid Environment value in request message. 
  19333.  
  19334.  30030     SOMDERROR_BadContext 
  19335.            Invalid Context object in request message. 
  19336.  
  19337.  30031     SOMDERROR_BadNVList 
  19338.            Invalid Named Value List (NVList). 
  19339.  
  19340.  30032     SOMDERROR_BadFlag 
  19341.            Bad flag in NVList item. 
  19342.  
  19343.  30033     SOMDERROR_BadLength 
  19344.            Bad length in NVList item. 
  19345.  
  19346.  30034     SOMDERROR_BadObjref 
  19347.            Invalid object reference. 
  19348.  
  19349.  30035     SOMDERROR_NullField 
  19350.            Unexpected null field in request message. 
  19351.  
  19352.  30036     SOMDERROR_UnknownReposId 
  19353.            Attempt to use Invalid Interface Repository ID. 
  19354.  
  19355.  30037     SOMDERROR_NVListAccess 
  19356.            Invalid NVList object in request message. 
  19357.  
  19358.  30038     SOMDERROR_NVIndexError 
  19359.            Attempt to use an out-of-range NVList index. 
  19360.  
  19361.  30039     SOMDERROR_SysTime 
  19362.            Error retrieving system time. 
  19363.  
  19364.  30040     SOMDERROR_SystemCallFailed 
  19365.            System call failed. 
  19366.  
  19367.  30041     SOMDERROR_CouldNotStartProcess 
  19368.            Unable to start a new process. 
  19369.  
  19370.  30042     SOMDERROR_NoServerClass 
  19371.            No SOMDServer (sub)class specified for server implementation. 
  19372.  
  19373.  30043     SOMDERROR_NoSOMDInit 
  19374.            Missing SOMD_Init call in program. 
  19375.  
  19376.  30044     SOMDERROR_SOMDDIRNotSet 
  19377.            SOMDDIR environment variable not set. 
  19378.  
  19379.  30045     SOMDERROR_NoImplDatabase 
  19380.            Could not open Implementation Repository database. 
  19381.  
  19382.  30046     SOMDERROR_ImplNotFound 
  19383.            Implementation not found in implementation repository. 
  19384.  
  19385.  30047     SOMDERROR_ClassNotFound 
  19386.            Class not found in implementation repository. 
  19387.  
  19388.  30048     SOMDERROR_ServerNotFound 
  19389.            Server not found in somdd's active server table. 
  19390.  
  19391.  30049     SOMDERROR_ServerAlreadyExists 
  19392.            Server already exists in somdd's active server table. 
  19393.  
  19394.  30050     SOMDERROR_ServerNotActive 
  19395.            Server is not active. 
  19396.  
  19397.  30051     SOMDERROR_CouldNotStartSOM 
  19398.            SOM initialization error. 
  19399.  
  19400.  30052     SOMDERROR_ObjectNotFound 
  19401.            Could not find desired object. 
  19402.  
  19403.  30053     SOMDERROR_NoParentClass 
  19404.            Unable to find / load parent class during proxy class creation. 
  19405.  
  19406.  30054     SOMDERROR_DispatchError 
  19407.            Unable to dispatch method. 
  19408.  
  19409.  30055     SOMDERROR_BadTypeCode 
  19410.            Invalid type code. 
  19411.  
  19412.  30056     SOMDERROR_BadDescriptor 
  19413.            Invalid method descriptor. 
  19414.  
  19415.  30057     SOMDERROR_BadResultType 
  19416.            Invalid method result type. 
  19417.  
  19418.  30058     SOMDERROR_KeyInUse 
  19419.            Internal object key is in use. 
  19420.  
  19421.  30059     SOMDERROR_KeyNotFound 
  19422.            Internal object key not found. 
  19423.  
  19424.  30060     SOMDERROR_CtxInvalidPropName 
  19425.            Illegal context property name. 
  19426.  
  19427.  30061     SOMDERROR_CtxNoPropFound 
  19428.            Could not find property name in context. 
  19429.  
  19430.  30062     SOMDERROR_CtxStartScopeNotFound 
  19431.            Could not find specified context start scope. 
  19432.  
  19433.  30063     SOMDERROR_CtxAccess 
  19434.            Error accessing context object. 
  19435.  
  19436.  30064     SOMDERROR_CouldNotStartThread 
  19437.            System error:  Could not start thread. 
  19438.  
  19439.  30065     SOMDERROR_AccessDenied 
  19440.            System error:  Access to a system resource (file, queue, shared 
  19441.            memory, etc.) denied. 
  19442.  
  19443.  30066     SOMDERROR_BadParm 
  19444.            System error:  invalid parameter supplied to a operating system 
  19445.            call. 
  19446.  
  19447.  30067     SOMDERROR_Interrupt 
  19448.            System error:  Interrupted system call. 
  19449.  
  19450.  30068     SOMDERROR_Locked 
  19451.            System error:  Drive locked by another process. 
  19452.  
  19453.  30069     SOMDERROR_Pointer 
  19454.            System error:  Invalid physical address. 
  19455.  
  19456.  30070     SOMDERROR_Boundary 
  19457.            OS/2 system error:  ERROR_CROSSES_OBJECT_BOUNDARY. 
  19458.  
  19459.  30071     SOMDERROR_UnknownError 
  19460.            System error:  Unknown error on operating system call. 
  19461.  
  19462.  30072     SOMDERROR_NoSpace 
  19463.            System error:  No space left on device. 
  19464.  
  19465.  30073     SOMDERROR_DuplicateQueue 
  19466.            System error:  Duplicate queue name. 
  19467.  
  19468.  30074     SOMDERROR_BadQueueName 
  19469.            System error:  Invalid queue name. 
  19470.  
  19471.  30075     SOMDERROR_DuplicateSem 
  19472.            System error:  Duplicate semaphore name used. 
  19473.  
  19474.  30076     SOMDERROR_BadSemName 
  19475.            System error:  Invalid semaphore name. 
  19476.  
  19477.  30077     SOMDERROR_TooManyHandles 
  19478.            System error:  Too many files open (no file handles left). 
  19479.  
  19480.  30078     SOMDERROR_BadAddrFamily 
  19481.            System error:  Invalid address family. 
  19482.  
  19483.  30079     SOMDERROR_BadFormat 
  19484.            System error:  Invalid format. 
  19485.  
  19486.  30080     SOMDERROR_BadDrive 
  19487.            System error:  Invalid drive. 
  19488.  
  19489.  30081     SOMDERROR_SharingViolation 
  19490.            System error:  Sharing violation. 
  19491.  
  19492.  30082     SOMDERROR_BadExeSignature 
  19493.            System error:  Program file contains a DOS mode program or invalid 
  19494.            program. 
  19495.  
  19496.  30083     SOMDERROR_BadExe 
  19497.            Executable file is invalid (linker errors occurred when program file 
  19498.            was created). 
  19499.  
  19500.  30084     SOMDERROR_Busy 
  19501.            System error:  Segment is busy. 
  19502.  
  19503.  30085     SOMDERROR_BadThread 
  19504.            System error:  Invalid thread id. 
  19505.  
  19506.  30086     SOMDERROR_SOMDPORTNotDefined 
  19507.            SOMDPORT not defined. 
  19508.  
  19509.  30087     SOMDERROR_ResourceExists 
  19510.            System resource (file, queue, shared memory segment,. etc.) already 
  19511.            exists. 
  19512.  
  19513.  30088     SOMDERROR_UserName 
  19514.            USER environment variable is not set. 
  19515.  
  19516.  30089     SOMDERROR_WrongRefType 
  19517.            Operation attempted on an object reference is incompatible with the 
  19518.            reference type. 
  19519.  
  19520.  30090     SOMDERROR_MustOverride 
  19521.            This method has no default implementation and must be overridden. 
  19522.  
  19523.  30091     SOMDERROR_NoSocketsClass 
  19524.            Could not find/load Sockets class. 
  19525.  
  19526.  30092     SOMDERROR_EManRegData 
  19527.            Unable to register DSOM events with the Event Manager. 
  19528.  
  19529.  30093     SOMDERROR_NoRemoteComm 
  19530.            Remote communications is disabled (for Workstation DSOM). 
  19531.  
  19532.  30096     SOMDERROR_GlobalAtomError 
  19533.            On Windows only, an error occurred while adding a segment name 
  19534.            to the Windows atom table. 
  19535.  
  19536.  30097     SOMDERROR_NamedMemoryTableError 
  19537.            On Windows only, an error occurred while creating or deleting a 
  19538.            (named) shared memory segment. 
  19539.  
  19540.  30098     SOMDERROR_WMQUIT 
  19541.            On Windows only, indicates DSOM received a Windows WM_QUIT message. 
  19542.            The developer of a server application should check for 
  19543.            SOMDERROR_WMQUIT returned from method execute_request_loop and 
  19544.            handle the error by cleaning up and exiting. 
  19545.  
  19546.  30105     SOMDERROR_DuplicateImplEntry 
  19547.            Implementation repository identifier already exists.  Add wait time 
  19548.            between `regimpl' calls. 
  19549.  
  19550.  30106     SOMDERROR_InvalidSOMSOCKETS 
  19551.            SOMSOCKETS environment variable set incorrectly. 
  19552.  
  19553.  30107     SOMDERR0R_IRNotFound 
  19554.            Interface Repository not found. 
  19555.  
  19556.  30108     SOMDERR0R_ClassNotInIR 
  19557.            Attempt to create an object whose Class is not in the Interface 
  19558.            Repository. 
  19559.  
  19560.  30110     SOMDERROR_SocketError 
  19561.            A communications socket error has occurred.  Make sure the DSOM 
  19562.            daemon is running. 
  19563.  
  19564.  30111     SOMDERROR_PacketError 
  19565.            A communications packet error has occurred. 
  19566.  
  19567.  30112     SOMDERROR_Marshal 
  19568.  
  19569.  30113     SOMDERROR_NotProcessOwner 
  19570.            On AIX only, the server cannot be killed because you are not the 
  19571.            process owner. 
  19572.  
  19573.  30114     SOMDERROR_ServerInactive 
  19574.            The requested server is not running. 
  19575.  
  19576.  30115     SOMDERROR_ServerDisabled 
  19577.            The server has been disabled by the program servmgr. 
  19578.  
  19579.  XXXXX     SOMDERROR_OperatingSystem 
  19580.            On AIX, this is the value of the C error variable "errno" defined in 
  19581.            errno.h; on OS/2 and Windows, it is the DOS API return code. 
  19582.  
  19583.  
  19584. ΓòÉΓòÉΓòÉ 13.3. Metaclass Framework Error Codes ΓòÉΓòÉΓòÉ
  19585.  
  19586. It is possible to receive the following messages from the Metaclass Framework 
  19587. while an application is running. 
  19588.  
  19589.  60001     An attempt was made to construct a class with SOMMSingleInstance as 
  19590.            a metaclass constraint. (This may occur indirectly because of the 
  19591.            construction of a derived metaclass). The initialization of the 
  19592.            class failed because somInitMIClass defined by SOMMSingleInstance is 
  19593.            in conflict with another metaclass that has overridden somNew. That 
  19594.            is, some other metaclass has already claimed the right to return the 
  19595.            value for somNew. 
  19596.  
  19597.  60002     An attempt was made to construct a class with SOMMSingleInstance as 
  19598.            a metaclass constraint. (This may occur indirectly because of the 
  19599.            construction of a derived metaclass). The initialization of the 
  19600.            class failed because somInitMIClass defined by SOMMSingleInstance is 
  19601.            in conflict with another metaclass that has overridden somFree. That 
  19602.            is, some other metaclass has already claimed this right to override 
  19603.            somFree. 
  19604.  
  19605.  60004     An invocation of somrRepInit was made with a logging type other tha 
  19606.            `o' or `v'. 
  19607.  
  19608.  60005     The sommBeforeMethod or the sommAfterMethod was invoked on a 
  19609.            SOMRReplicableObject whose logging type is other than `o' or `v'. 
  19610.            This error cannot occur normally. The likely cause is that some 
  19611.            method invoked on another object has overwritten this object's 
  19612.            memory. 
  19613.  
  19614.  60006     A Before/After Metaclass must override both sommBeforeMethod and 
  19615.            sommAfterMethod.  This message indicates an attempt to create a 
  19616.            Before/After Metaclass where only one of the above methods is 
  19617.            overridden. 
  19618.  
  19619.  
  19620. ΓòÉΓòÉΓòÉ 14. SOM IDL Language Grammar ΓòÉΓòÉΓòÉ
  19621.  
  19622.  
  19623.  specification         : [comment]
  19624.                        definition+
  19625.  
  19626.  definition            : type_dcl  ; [
  19627.                        comment] Γöé const_dcl
  19628.                        ; [comment] Γöé
  19629.                        interface ; [comment
  19630.                        ] Γöé module    ; [
  19631.                        comment] Γöé
  19632.                        pragma_stm
  19633.  
  19634.  module                : module identifier
  19635.                        [comment]   { [
  19636.                        comment] definition+
  19637.                        }
  19638.  
  19639.  interface             : interface
  19640.                        identifier Γöé
  19641.                        interface_dcl
  19642.  
  19643.  interface_dcl         : interface
  19644.                        identifier [
  19645.                        inheritance] [
  19646.                        comment]    { [
  19647.                        comment] export*  }
  19648.                        [comment]
  19649.  
  19650.  inheritance           : scoped_name {,
  19651.                        scoped_name}*
  19652.  
  19653.  export                : type_dcl ; [
  19654.                        comment] Γöé const_dcl
  19655.                        ; [comment] Γöé
  19656.                        attr_dcl ; [comment]
  19657.                        Γöé op_dcl ; [comment]
  19658.                        Γöé
  19659.                        implementation_body
  19660.                        ; [comment] Γöé
  19661.                        pragma_stm
  19662.  
  19663.  scoped_name           : identifier Γöé :
  19664.                        identifer Γöé
  19665.                        scoped_name :
  19666.                        identifer
  19667.  
  19668.  const_dcl             : const const_type
  19669.                        identifier =
  19670.                        const_expr
  19671.  
  19672.  const_type            : integer_type Γöé
  19673.                        char_type Γöé
  19674.                        boolean_type Γöé
  19675.                        floating_pt_type Γöé
  19676.                        string_type Γöé
  19677.                        scoped_name
  19678.  
  19679.  const_expr            : or_expr
  19680.  
  19681.  or_expr               : xor_expr Γöé or_expr
  19682.                        Γöé xor_expr
  19683.  
  19684.  xor_expr              : and_expr Γöé
  19685.                        xor_expr ^ and_expr
  19686.  
  19687.  and_expr              : shift_expr Γöé
  19688.                        and_expr &
  19689.                        shift_expr
  19690.  
  19691.  shift_expr            : add_expr: Γöé
  19692.                        shift_expr:: >>
  19693.                        add_expr Γöé
  19694.                        shift_expr: <<
  19695.                        add_expr
  19696.  
  19697.  add_expr              : mult_expr Γöé
  19698.                        add_expr + mult_expr
  19699.                        Γöé add_expr -
  19700.                        mult_expr
  19701.  
  19702.  mult_expr             : unary_expr Γöé
  19703.                        mult_expr *
  19704.                        unary_expr Γöé
  19705.                        mult_expr /
  19706.                        unary_expr Γöé
  19707.                        mult_expr %
  19708.                        unary_expr
  19709.  
  19710.  unary_expr            : unary_operator
  19711.                        primary_expr Γöé
  19712.                        primary_expr
  19713.  
  19714.  unary_operator        :  - Γöé  + Γöé  ~
  19715.  
  19716.  primary_expr          : scoped_name Γöé
  19717.                        literal Γöé (
  19718.                        const_expr )
  19719.  
  19720.  literal               : integer_literal Γöé
  19721.                        string_literal Γöé
  19722.                        character_literal Γöé
  19723.                        floating_pt_literal
  19724.                        Γöé boolean_literal
  19725.  
  19726.  type_dcl              : typedef
  19727.                        type_declarator Γöé
  19728.                        constr_type_spec
  19729.  
  19730.  type_declarator       : type_spec
  19731.                        declarator {,
  19732.                        declarator}*
  19733.  
  19734.  type_spec             : simple_type_spec Γöé
  19735.                        constr_type_spec
  19736.  
  19737.  simple_type_spec      : base_type_spec Γöé
  19738.                        template_type_spec Γöé
  19739.                        scoped_name
  19740.  
  19741.  base_type_spec        : floating_pt_type Γöé
  19742.                        integer_type Γöé
  19743.                        char_type Γöé
  19744.                        boolean_type Γöé
  19745.                        octet_type Γöé
  19746.                        any_type Γöé
  19747.                        voidptr_type
  19748.  
  19749.  template_type_spec    : sequence_type Γöé
  19750.                        string_type
  19751.  
  19752.  constr_type_spec      : struct_type Γöé
  19753.                        union_type Γöé
  19754.                        enum_type
  19755.  
  19756.  declarator            : [stars]
  19757.                        std_declarator
  19758.  
  19759.  std_declarator        : simple_declarator
  19760.                        Γöé complex_declarator
  19761.  
  19762.  simple_declarator     : identifier
  19763.  
  19764.  complex_declarator    : array_declarator
  19765.  
  19766.  array_declarator      : simple_declarator
  19767.                        fixed_array_size+
  19768.  
  19769.  fixed_array_size      : [ const_expr  ]
  19770.  
  19771.  floating_pt_type      : float Γöé double
  19772.  
  19773.  integer_type          : signed_int Γöé
  19774.                        unsigned_int
  19775.  
  19776.  signed_int            : long Γöé short
  19777.  
  19778.  unsigned_int          : unsigned
  19779.                        signed_int
  19780.  
  19781.  char_type             : char
  19782.  
  19783.  boolean_type          : boolean
  19784.  
  19785.  octet_type            : octet
  19786.  
  19787.  any_type              : any
  19788.  
  19789.  voidptr_type          : void stars
  19790.  
  19791.  struct_type           : ( structΓöéexception
  19792.                        ) identifier Γöé (
  19793.                        structΓöéexception) [
  19794.                        comment]   { [
  19795.                        comment] member* }
  19796.  
  19797.  member                : type_declarator ;
  19798.                        [comment]
  19799.  
  19800.  union_type            : union identifier Γöé
  19801.                        union identifier
  19802.                        switch   (
  19803.                        switch_type_spec ) [
  19804.                        comment]   { [
  19805.                        comment] case+ }
  19806.  
  19807.  switch_type_spec      : integer_type Γöé
  19808.                        char_type Γöé
  19809.                        boolean_type Γöé
  19810.                        enum_type Γöé
  19811.                        scoped_name
  19812.  
  19813.  case                  : case_label+
  19814.                        element_spec ; [
  19815.                        comment]
  19816.  
  19817.  case_label            : case const_expr :
  19818.                        [comment] Γöé default
  19819.                        : [comment]
  19820.  
  19821.  element_spec          : type_spec
  19822.                        declarator
  19823.  
  19824.  enum_type             : enum identifier {
  19825.                        identifier   {,
  19826.                        identifier}* [
  19827.                        comment] }
  19828.  
  19829.  sequence_type         : sequence <
  19830.                        simple_type_spec ,
  19831.                        const_expr > Γöé
  19832.                        sequence <
  19833.                        simple_type_spec >
  19834.  
  19835.  string_type           : string <
  19836.                        const_expr > Γöé
  19837.                        string
  19838.  
  19839.  attr_dcl              : [readonly]
  19840.                        attribute
  19841.                        simple_type_spec
  19842.                        declarator {,
  19843.                        declarator}*
  19844.  
  19845.  op_dcl                : [oneway]
  19846.                        op_type_spec [stars]
  19847.                        identifier
  19848.                        parameter_dcls [
  19849.                        raises_expr] [
  19850.                        context_expr]
  19851.  
  19852.  op_type_spec          : simple_type_spec Γöé
  19853.                        void
  19854.  
  19855.  parameter_dcls        : ( param_dcl {,
  19856.                        param_dcl}* [comment
  19857.                        ]  ) Γöé (  )
  19858.  
  19859.  param_dcl             : param_attribute
  19860.                        simple_type_spec
  19861.                        declarator
  19862.  
  19863.  param_attribute       : in Γöé out Γöé inout
  19864.  
  19865.  raises_expr           : raises (
  19866.                        scope_name+ )
  19867.  
  19868.  context_expr          : context  (
  19869.                        context_string{,
  19870.                        context_string}*  )
  19871.  
  19872.  implementation_body   : implementation [
  19873.                        comment]   { [
  19874.                        comment]
  19875.                        implementation+ }
  19876.  
  19877.  implementation        : modifier_stm Γöé
  19878.                        pragma_stm Γöé
  19879.                        passthru Γöé member
  19880.  
  19881.  pragma_stm            : #pragma modifier
  19882.                        modifier_stm Γöé
  19883.                        #pragma
  19884.                        somtemittypes on Γöé
  19885.                        #pragma
  19886.                        somtemittypes off
  19887.  
  19888.  modifier_stm          : smidentifier : [
  19889.                        modifier {, modifier
  19890.                        }*] ; [comment] Γöé
  19891.                        modifier ; [comment]
  19892.  
  19893.  modifier              : smidentifier Γöé
  19894.                        smidentifier =
  19895.                        modifier_value
  19896.  
  19897.  modifier_value        : smidentifier Γöé
  19898.                        string_literal Γöé
  19899.                        integer_literal Γöé
  19900.                        keyword
  19901.  
  19902.  passthru              :  passthru
  19903.                        identifier =
  19904.                        string_literal+  ;
  19905.                        [comment]
  19906.  
  19907.  smidentifier          : identifer Γöé _
  19908.                        identifier
  19909.  
  19910.  stars                 Γöé *+
  19911.  
  19912.  
  19913. ΓòÉΓòÉΓòÉ 15. Implementing Sockets Subclasses ΓòÉΓòÉΓòÉ
  19914.  
  19915. Distributed SOM (DSOM) and the Replication Framework require basic message 
  19916. services for inter-process communications. The Event Management Framework must 
  19917. be integrated with the same communication services in order to handle 
  19918. communications events. 
  19919.  
  19920. To maximize their portability to a wide variety of local area network transport 
  19921. protocols, the DSOM, Replication, and Event Management Frameworks have been 
  19922. written to use a common communications interface, which is implemented by one 
  19923. or more SOM class libraries using available local protocols. 
  19924.  
  19925. The common communications interface is based on the "sockets" interface used 
  19926. with TCP/IP, since its interface and semantics are fairly widespread and well 
  19927. understood. The IDL interface is named Sockets. There is no implementation 
  19928. associated with the Sockets interface by default; specific protocol 
  19929. implementations are supplied by subclass implementations. 
  19930.  
  19931. Note:  The Sockets classes supplied with the SOMobjects Developer Toolkit and 
  19932.        run-time packages are only intended to support the DSOM, Replication, 
  19933.        and Event Management Frameworks. These class implementations are not 
  19934.        intended for general application usage. 
  19935.  
  19936.  Available Sockets subclasses by SOMobjects product are as follows: 
  19937.  
  19938.    o  For AIX: 
  19939.  
  19940.            TCPIPSockets class for TCP/IP, 
  19941.            IPXSockets class for Netware IPX/SPX, and 
  19942.            NBSockets class for NetBIOS. 
  19943.  
  19944.    o  For OS/2 and Windows: 
  19945.  
  19946.            TCPIPSockets class (a) for TCP/IP for Windows or (b) for TCP/IP 
  19947.            1.2.1 on OS/2, 
  19948.            TCPIPSockets32 class for TCP/IP 2.0 on OS/2 only (see Note below), 
  19949.            IPXSockets class for NetWare IPX/SPX, and 
  19950.            NBSockets class for NetBIOS. 
  19951.  
  19952.  Note:  The TCPIPSocket32 class gives greater performance over the TCPIPSockets 
  19953.         class on OS/2, but requires the 32-bit version of TCPP/IP (version 2.0) 
  19954.         rather than the 16-bit version of TCP/IP (version 1.2.1). 
  19955.  
  19956.  Application developers may need to develop their own Sockets  subclass if the 
  19957.  desired transport protocol or product version is not one of those supported by 
  19958.  the SOMobjects run-time packages. This appendix explains how to approach the 
  19959.  implementation of a Sockets subclass, if necessary. Warning: this may be a 
  19960.  non-trivial exercise! 
  19961.  
  19962.  
  19963. ΓòÉΓòÉΓòÉ 15.1. Sockets IDL interface ΓòÉΓòÉΓòÉ
  19964.  
  19965. The base Sockets interface is expressed in IDL in the file somssock.idl, listed 
  19966. below. There is a one-to-one mapping between TCP/IP socket APIs and the methods 
  19967. defined in the Sockets interface. 
  19968.  
  19969. Please note the following: 
  19970.  
  19971.    o  The semantics of each of the Sockets methods must be that of the 
  19972.       corresponding TCP/IP call. Currently, only Internet address family 
  19973.       (AF_INET) addresses are used by the frameworks. 
  19974.  
  19975.       (The TCP/IP sockets API is not documented as part of the SOMobjects 
  19976.       Developer Toolkit. The implementor is referred to the programming 
  19977.       references for IBM TCP/IP for AIX or OS/2, or to similar references that 
  19978.       describe the sockets interface for TCP/IP.) 
  19979.  
  19980.    o  Data types, constants, and macros which are part of the Sockets interface 
  19981.       are defined in a C include file, soms.h. This file is supplied with the 
  19982.       SOMobjects Toolkit, and is not shown in this manual. 
  19983.  
  19984.    o  The Sockets interface is expressed in terms of a 32-bit implementation. 
  19985.  
  19986.    o  Some of the method parameters and return values are expressed using 
  19987.       pointer types, for example: 
  19988.  
  19989.             hostent *somsGethostent ();
  19990.  
  19991.       This has been done to map TCP/IP socket interfaces as directly as 
  19992.       possible to their IDL equivalent. (Use of strict CORBA IDL was not a 
  19993.       primary goal for the Sockets interface, since it is only used internally 
  19994.       by the frameworks.) 
  19995.  
  19996.    o  The Sockets class and its subclasses are  single instance classes. 
  19997.  
  19998.  Following is a listing of the file somssock.idl. Each socket call is briefly 
  19999.  described with a comment. 
  20000.  
  20001.   // 96F8647, 96F8648 (C) Copyright IBM Corp. 1992, 1993
  20002.   // All Rights Reserved
  20003.   // Licensed Materials - Property of IBM
  20004.  
  20005.   #ifndef somssock_idl
  20006.   #define somssock_idl
  20007.  
  20008.   #include <somobj.idl>
  20009.   #include <snglicls.idl>
  20010.  
  20011.   interface Sockets : SOMObject
  20012.   {
  20013.       //# The following typedefs are fully defined in <soms.h>.
  20014.       typedef SOMFOREIGN sockaddr;
  20015.       #pragma modifier sockaddr : impctx="C", struct;
  20016.       typedef SOMFOREIGN iovec;
  20017.       #pragma modifier iovec : impctx="C", struct;
  20018.       typedef SOMFOREIGN msghdr;
  20019.       #pragma modifier msghdr : impctx="C", struct;
  20020.       typedef SOMFOREIGN fd_set;
  20021.       #pragma modifier fd_set : impctx="C", struct;
  20022.       typedef SOMFOREIGN timeval;
  20023.       #pragma modifier timeval : impctx="C", struct;
  20024.       typedef SOMFOREIGN hostent;
  20025.       #pragma modifier hostent : impctx="C", struct;
  20026.       typedef SOMFOREIGN servent;
  20027.       #pragma modifier servent : impctx="C", struct;
  20028.       typedef SOMFOREIGN in_addr;
  20029.       #pragma modifier in_addr : impctx="C", struct;
  20030.  
  20031.       long somsAccept (in long s, out sockaddr name, out long namelen);
  20032.       // Accept a connection request from a client.
  20033.  
  20034.       long somsBind (in long s, inout sockaddr name, in long namelen);
  20035.       // Binds a unique local name to the socket with descriptor s.
  20036.  
  20037.       long somsConnect (in long s, inout sockaddr name,
  20038.                         in long namelen);
  20039.       // For streams sockets, attempts to establish a connection
  20040.       // between two sockets.  For datagram sockets, specifies the
  20041.       // socket's peer.
  20042.  
  20043.       hostent *somsGethostbyaddr (in char *addr, in long addrlen,
  20044.                                   in long domain);
  20045.       // Returns a hostent structure for the host address specified on
  20046.       // the call.
  20047.  
  20048.       hostent *somsGethostbyname (in string name);
  20049.       // Returns a hostent structure for the host name specified on
  20050.       // the call.
  20051.  
  20052.       hostent *somsGethostent ();
  20053.       // Returns a pointer to the next entry in the hosts file.
  20054.  
  20055.       unsigned long somsGethostid ();
  20056.       // Returns the unique identifier for the current host.
  20057.  
  20058.       long somsGethostname (in string name, in long namelength);
  20059.       // Retrieves the standard host name of the local host.
  20060.  
  20061.       long somsGetpeername (in long s, out sockaddr name,
  20062.                            out long namelen);
  20063.       // Gets the name of the peer connected to socket s.
  20064.  
  20065.       servent *somsGetservbyname (in string name, in string protocol);
  20066.       // Retrieves an entry from the /etc/services file using the
  20067.       // service name as a search key.
  20068.  
  20069.       long somsGetsockname (in long s, out sockaddr name,
  20070.                             out long namelen);
  20071.       // Stores the current name for the socket specified by the s
  20072.       // parameter into the structure pointed to by the name
  20073.       // parameter.
  20074.  
  20075.       long somsGetsockopt (in long s, in long level, in long optname,
  20076.                           in char *optval, out long option);
  20077.       // Returns the values of socket options at various protocol
  20078.       // levels.
  20079.  
  20080.       unsigned long somsHtonl (in unsigned long a);
  20081.       // Translates an unsigned long integer from host-byte order to
  20082.       // network-byte order.
  20083.  
  20084.       unsigned short somsHtons (in unsigned short a);
  20085.       // Translates an unsigned short integer from host-byte order to
  20086.       // network-byte order.
  20087.  
  20088.       long somsIoctl (in long s, in long cmd, in char *data,
  20089.                       in long length);
  20090.       // Controls the operating characteristics of sockets.
  20091.  
  20092.       unsigned long somsInet_addr (in string cp);
  20093.       // Interprets character strings representing numbers expressed
  20094.       // in standard '.' notation and returns numbers suitable for use
  20095.       // as internet addresses.
  20096.  
  20097.       unsigned long somsInet_lnaof (in in_addr addr);
  20098.       // Breaks apart the internet address and returns the local
  20099.       // network address portion.
  20100.  
  20101.       in_addr somsInet_makeaddr (in unsigned long net,
  20102.                                  in unsigned long lna);
  20103.       // Takes a network number and a local network address and
  20104.       // constructs an internet address.
  20105.  
  20106.       unsigned long somsInet_netof (in in_addr addr);
  20107.       // Returns the network number portion of the given internet
  20108.       // address.
  20109.  
  20110.       unsigned long somsInet_network (in string cp);
  20111.       // Interprets character strings representing numbers expressed
  20112.       // in standard '.' notation and returns numbers suitable for use
  20113.       // as network numbers.
  20114.  
  20115.       string somsInet_ntoa (in in_addr addr);
  20116.       // Returns a pointer to a string expressed in the dotted-decimal
  20117.       // notation.
  20118.  
  20119.       long somsListen (in long s, in long backlog);
  20120.       // Creates a connection request queue of length backlog to queue
  20121.       // incoming connection requests, and then waits for incoming
  20122.       // connection requests.
  20123.  
  20124.       unsigned long somsNtohl (in unsigned long a);
  20125.       // Translates an unsigned long integer from network-byte order
  20126.       // to host-byte order.
  20127.  
  20128.       unsigned short somsNtohs (in unsigned short a);
  20129.       // Translates an unsigned short integer from network-byte order
  20130.       // to host-byte order.
  20131.  
  20132.       long somsReadv (in long s, inout iovec iov, in long iovcnt);
  20133.       // Reads data on socket s and stores it in a set of buffers
  20134.       // described by iov.
  20135.  
  20136.       long somsRecv (in long s, in char *buf, in long len,
  20137.                      in long flags);
  20138.       // Receives data on streams socket s and stores it in buf.
  20139.  
  20140.       long somsRecvfrom (in long s, in char *buf, in long len,
  20141.           in long flags, out sockaddr name, out long namelen);
  20142.       // Receives data on datagram socket s and stores it in buf.
  20143.  
  20144.       long somsRecvmsg (in long s, inout msghdr msg, in long flags);
  20145.       // Receives messages on a socket with descriptor s and stores
  20146.       // them in an array of message headers.
  20147.  
  20148.       long somsSelect (in long nfds, inout fd_set readfds,
  20149.                        inout fd_set writefds, inout fd_set exceptfds,
  20150.                        inout timeval timeout);
  20151.       // Monitors activity on a set of different sockets until a
  20152.       // timeout expires, to see if any sockets are ready for reading
  20153.       // or writing, or if an exceptional condition is pending.
  20154.  
  20155.       long somsSend (in long s, in char *msg, in long len,
  20156.                      in long flags);
  20157.       // Sends msg on streams socket s.
  20158.  
  20159.       long somsSendmsg (in long s, inout msghdr msg, in long flags);
  20160.       // Sends messages passed in an array of message headers on a
  20161.       // socket with descriptor s.
  20162.  
  20163.       long somsSendto (in long s, inout char msg, in long len,
  20164.                        in long flags, inout sockaddr to, in long tolen);
  20165.       // Sends msg on datagram socket s.
  20166.  
  20167.       long somsSetsockopt (in long s, in long level, in long optname,
  20168.                            in char *optval, in long optlen);
  20169.       // Sets options associated with a socket.
  20170.  
  20171.       long somsShutdown (in long s, in long how);
  20172.       // Shuts down all or part of a full-duplex connection.
  20173.  
  20174.       long somsSocket (in long domain, in long type,
  20175.                        in long protocol);
  20176.       // Creates an endpoint for communication and returns a socket
  20177.       // descriptor representing the endpoint.
  20178.  
  20179.       long somsSoclose (in long s);
  20180.       // Shuts down socket s and frees resources allocated to the
  20181.       // socket.
  20182.  
  20183.       long somsWritev (in long s, inout iovec iov, in long iovcnt);
  20184.       // Writes data on socket s.  The data is gathered from the
  20185.       // buffers described by iov.
  20186.  
  20187.       attribute long serrno;
  20188.       // Used to pass error numbers.
  20189.  
  20190.   #ifdef __SOMIDL__
  20191.       implementation
  20192.       {
  20193.       releaseorder:
  20194.           somsAccept, somsBind, somsConnect, somsGethostbyaddr,
  20195.           somsGethostbyname, somsGethostent, somsGethostid,
  20196.           somsGethostname, somsGetpeername, somsGetsockname,
  20197.           somsGetsockopt, somsHtonl, somsHtons, somsIoctl,
  20198.           somsInet_addr, somsInet_lnaof, somsInet_makeaddr,
  20199.           somsInet_netof, somsInet_network, somsInet_ntoa,
  20200.           somsListen, somsNtohl, somsNtohs, somsReadv,
  20201.           somsRecv, somsRecvfrom, somsRecvmsg, somsSelect,
  20202.           somsSend, somsSendmsg, somsSendto, somsSetsockopt,
  20203.           somsShutdown, somsSocket, somsSoclose, somsWritev,
  20204.           _set_serrno, _get_serrno, somsGetservbyname;
  20205.  
  20206.       //# Class modifiers
  20207.       callstyle=idl;
  20208.       metaclass = SOMMSingleInstance;
  20209.       majorversion=1; minorversion=1;
  20210.       dll="soms.dll";
  20211.       };
  20212.   #endif /* __SOMIDL__ */
  20213.   };
  20214.   #endif  /* somssock_idl */
  20215.  
  20216.  
  20217. ΓòÉΓòÉΓòÉ 15.2. IDL for a Sockets subclass ΓòÉΓòÉΓòÉ
  20218.  
  20219. Sockets subclasses inherit their entire interface from Sockets. All methods are 
  20220. overridden. 
  20221.  
  20222. For example, here is a listing of the TCPIPSockets IDL description. 
  20223.  
  20224. // 96F8647, 96F8648 (C) Copyright IBM Corp. 1992, 1993
  20225. // All Rights Reserved
  20226. // Licensed Materials - Property of IBM
  20227.  
  20228. #ifndef tcpsock_idl
  20229. #define tcpsock_idl
  20230.  
  20231. #include <somssock.idl>
  20232. #include <snglicls.idl>
  20233.  
  20234. interface TCPIPSockets : Sockets
  20235. {
  20236. #ifdef __SOMIDL__
  20237.     implementation
  20238.     {
  20239.     //# Class modifiers
  20240.     callstyle=idl;
  20241.     majorversion=1; minorversion=1;
  20242.     dllname="somst.dll";
  20243.     metaclass=SOMMSingleInstance;
  20244.     //# Method modifiers
  20245.     somsAccept: override;
  20246.     somsBind: override;
  20247.     somsConnect: override;
  20248.     somsGethostbyaddr: override;
  20249.     somsGethostbyname: override;
  20250.     somsGethostent: override;
  20251.     somsGethostid: override;
  20252.     somsGethostname: override;
  20253.     somsGetpeername: override;
  20254.     somsGetservbyname: override;
  20255.     somsGetsockname: override;
  20256.     somsGetsockopt: override;
  20257.     somsHtonl: override;
  20258.     somsHtons: override;
  20259.     somsIoctl: override;
  20260.     somsInet_addr: override;
  20261.     somsInet_lnaof: override;
  20262.     somsInet_makeaddr: override;
  20263.     somsInet_netof: override;
  20264.     somsInet_network: override;
  20265.     somsInet_ntoa: override;
  20266.     somsListen: override;
  20267.     somsNtohl: override;
  20268.     somsNtohs: override;
  20269.     somsReadv: override;
  20270.     somsRecv: override;
  20271.     somsRecvfrom: override;
  20272.     somsRecvmsg: override;
  20273.     somsSelect: override;
  20274.     somsSend: override;
  20275.     somsSendmsg: override;
  20276.     somsSendto: override;
  20277.     somsSetsockopt: override;
  20278.     somsShutdown: override;
  20279.     somsSocket: override;
  20280.     somsSoclose: override;
  20281.     somsWritev: override;
  20282.     _set_serrno: override;
  20283.    _get_serrno: override;
  20284.    };
  20285. #endif /* __SOMIDL__ */
  20286.  };
  20287. #endif  /* tcpsock_idl */
  20288.  
  20289.  
  20290. ΓòÉΓòÉΓòÉ 15.3. Implementation considerations ΓòÉΓòÉΓòÉ
  20291.  
  20292.    o  Only the AF_INET address family must be supported. That is, the DSOM, 
  20293.       Replication, and Event Manager frameworks all use Internet addresses and 
  20294.       port numbers to refer to specific sockets. 
  20295.  
  20296.    o  On OS/2, the SOMobjects run-time libraries were built using the C Set/2 
  20297.       32-bit compiler. If the underlying subclass implementation uses a 16-bit 
  20298.       subroutine library, conversion of the method call arguments may be 
  20299.       required. (This mapping of arguments is often referred to as "thunking.") 
  20300.  
  20301.    o  Sockets subclasses to be used in multi-threaded environments should be 
  20302.       made thread-safe. That is, it is possible that concurrent threads may 
  20303.       make calls on the (single) Sockets object, so data structures must be 
  20304.       protected within critical regions, as appropriate. 
  20305.  
  20306.    o  Valid values for the serrno attribute are defined in the file soms.h. The 
  20307.       subclass implementation should map local error numbers into the 
  20308.       appropriate corresponding Sockets error numbers. 
  20309.  
  20310.  
  20311. ΓòÉΓòÉΓòÉ 15.4. Example code ΓòÉΓòÉΓòÉ
  20312.  
  20313. The following code fragment shows an example of the implementation of the 
  20314. somsBind method of the TCPIPSockets subclass, for both AIX and OS/2. The sample 
  20315. illustrates that, for TCP/IP, the implementation is basically a one-to-one 
  20316. mapping of Sockets methods onto TCP/IP calls. For other transport protocols, 
  20317. the mapping from the socket abstraction to the protocol's API may be more 
  20318. difficult. 
  20319.  
  20320. For AIX, the mapping from Sockets method to TCP/IP call is trivial. 
  20321.  
  20322. SOM_Scope long  SOMLINK somsBind(TCPIPSockets somSelf,
  20323.                                  Environment *ev,
  20324.                                  long s, Sockets_sockaddr* name,
  20325.                                  long namelen)
  20326. {
  20327.     long rc;
  20328.  
  20329.     TCPIPSocketsMethodDebug("TCPIPSockets","somsBind");
  20330.  
  20331.     rc = (long) bind((int)s, name, (int)namelen);
  20332.  
  20333.     if (rc == -1)
  20334.        __set_serrno(somSelf, ev, errno);
  20335.  
  20336.     return rc;
  20337. }
  20338.  
  20339. On OS/2, however, the TCP/IP Release 1.2.1 library is a 16-bit library. 
  20340. Consequently, many of the method calls require conversion ("thunking") of 
  20341. 32-bit parameters into 16-bit parameters, before the actual TCP/IP calls can be 
  20342. invoked. For example, the function prototype for the somsBind method is defined 
  20343. as: 
  20344.  
  20345. SOM_Scope long  SOMLINK somsBind(TCPIPSockets somSelf,
  20346.                                  Environment *ev,
  20347.                                  long s, Sockets_sockaddr* name,
  20348.                                  long namelen);
  20349.  
  20350. whereas the file socket.h on OS/2 declares the bind function with the following 
  20351. prototype: 
  20352.  
  20353. short _Far16 _Cdecl bind(short /*s*/, void * _Seg16 /*name*/,
  20354.                          short /*len*/);
  20355.  
  20356. In this case, the pointer to the "name" structure, passed as a 32-bit address, 
  20357. cannot be used directly in the bind call: a 16-bit address must be passed 
  20358. instead. This can be accomplished by dereferencing the 32-bit pointer provided 
  20359. by the "name" parameter in the somsBind call, copying the caller's 
  20360. Sockets_sockaddr structure into a local structure ("name16"), and then passing 
  20361. the address of the local structure ("&name16") as a 16-bit address in the bind 
  20362. call. 
  20363.  
  20364. SOM_Scope long  SOMLINK somsBind(TCPIPSockets somSelf,
  20365.                                  Environment *ev,
  20366.                                  long s, Sockets_sockaddr* name,
  20367.                                  long namelen)
  20368. {
  20369.     long rc;
  20370.     Sockets_sockaddr name16;
  20371.  
  20372.     TCPIPSocketsMethodDebug("TCPIPSockets","somsBind");
  20373.  
  20374.     /* copy user's parameter into a local structure */
  20375.     memcpy ((char *)&name16, (char *)((sockaddr32 *)name), namelen);
  20376.     rc = (long) bind((short)s, (void *)&name16, (short)namelen);
  20377.  
  20378.     if (rc == -1)
  20379.        __set_serrno(somSelf, ev, tcperrno());
  20380.  
  20381.     return rc;
  20382. }
  20383.  
  20384.  
  20385. ΓòÉΓòÉΓòÉ 16. Glossary ΓòÉΓòÉΓòÉ
  20386.  
  20387. Note: In the following definitions, words shown in italics are terms for which 
  20388. separate glossary entries are also defined. 
  20389.  
  20390.  abstract class A class that is not designed to be instantiated, but serves as 
  20391.                 a base class for the definition of subclasses. Regardless of 
  20392.                 whether an abstract class inherits instance data and methods 
  20393.                 from parent classes, it will always introduce methods that must 
  20394.                 be overridden in a subclass, in order to produce a class whose 
  20395.                 objects are semantically valid. 
  20396.  
  20397.  affinity group An array of class objects that were all registered with the 
  20398.                 SOMClassMgr object during the dynamic loading of a class. Any 
  20399.                 class is a member of at most one affinity group. 
  20400.  
  20401.  ancestor class A class from which another class inherits instance methods, 
  20402.                 attributes, and instance variables, either directly or 
  20403.                 indirectly. A direct descendant of an ancestor class is called 
  20404.                 a child class, derived class, or  subclass. A direct ancestor 
  20405.                 of a class is called a parent class, base class, or 
  20406.                 superclass. 
  20407.  
  20408.  aggregate type A user-defined data type that combines basic types (such as, 
  20409.                 char, short, float, and so on) into a more complex type (such 
  20410.                 as structs, arrays, strings, sequences, unions, or enums). 
  20411.  
  20412.  apply stub     A procedure corresponding to a particular method that accepts 
  20413.                 as arguments: the object on which the method is to be invoked, 
  20414.                 a pointer to a location in memory where the method's result 
  20415.                 should be stored, a pointer to the method's procedure, and the 
  20416.                 method's arguments in the form of a va_list. The apply stub 
  20417.                 extracts the arguments from the va_list, invokes the method 
  20418.                 with its arguments, and stores its result in the specified 
  20419.                 location. Apply stubs are registered with class objects when 
  20420.                 instance methods are defined, and are invoked using the 
  20421.                 somApply function. Typically, implementations that override 
  20422.                 somDispatch call somApply to invoke a method on a va_list of 
  20423.                 arguments. 
  20424.  
  20425.  attribute      A specialized syntax for declaring "set" and "get" methods. 
  20426.                 Method names corresponding to attributes always begin with 
  20427.                 "_set_" or "_get_". An attribute name is declared in the body 
  20428.                 of the interface statement for a class. Method procedures for 
  20429.                 get/set methods are automatically defined by the SOM Compiler 
  20430.                 unless an attribute is declared as "noget/noset". Likewise, a 
  20431.                 corresponding instance variable is automatically defined unless 
  20432.                 an attribute is declared as "nodata". IDL also supports 
  20433.                 "readonly" attributes, which specify only a "get" method. 
  20434.                 (Contrast an attribute with an instance variable.) 
  20435.  
  20436.  auxiliary class data structure A structure provided by the SOM API to support 
  20437.                 efficient static access to class-specific information used in 
  20438.                 dealing with SOM objects. The structure's name is 
  20439.                 <className>CClassData. Its first component (parentMtab) is a 
  20440.                 list of parent-class method tables (used to support efficient 
  20441.                 parent method calls). Its second component (instanceDataToken) 
  20442.                 is the instance token for the class (generally used to locate 
  20443.                 the instance data introduced by method procedures that 
  20444.                 implement methods defined by the class). 
  20445.  
  20446.  base class     See parent class. 
  20447.  
  20448.  behavior (of an object) The methods that an object responds to. These methods 
  20449.                 are those either introduced or inherited by the class of the 
  20450.                 object. See also state. 
  20451.  
  20452.  bindings       Language-specific macros and procedures that make implementing 
  20453.                 and using SOM classes more convenient. These bindings offer a 
  20454.                 convenient interface to SOM that is tailored to a particular 
  20455.                 programming language. The SOM Compiler generates binding files 
  20456.                 for C and C ++. These binding files include an implementation 
  20457.                 template for the class and two header files, one to be included 
  20458.                 in the class's implementation file and the other in client 
  20459.                 programs. 
  20460.  
  20461.  BOA (basic object adapter) class A CORBA interface (represented as an abstract 
  20462.                 class in DSOM), which defines generic object-adapter (OA) 
  20463.                 methods that a server can use to register itself and its 
  20464.                 objects with an ORB (object request broker). See also SOMOA 
  20465.                 (SOM object adapter) class. 
  20466.  
  20467.  callback       A user-provided procedure or method to the Event Management 
  20468.                 Framework that gets invoked when a registered event occurs. 
  20469.                 (See also event ). 
  20470.  
  20471.  casted dispatching A form of method dispatching that uses casted method 
  20472.                 resolution; that is, it uses a designated ancestor class of the 
  20473.                 actual target object's class to determine what procedure to 
  20474.                 call to execute a specified method. 
  20475.  
  20476.  casted method resolution A method resolution technique that uses a method 
  20477.                 procedure from the method table of an ancestor of the class of 
  20478.                 an object (rather than using a procedure from the method table 
  20479.                 of the object's own class). 
  20480.  
  20481.  child class    A class that inherits instance methods, attributes, and 
  20482.                 instance variables directly from another class, called the 
  20483.                 parent class, base class, or superclass, or indirectly from an 
  20484.                 ancestor class. A child class may also be called a derived 
  20485.                 class or subclass. 
  20486.  
  20487.  class          A way of categorizing objects based on their behavior (the 
  20488.                 methods they support) and shape (memory layout). A class is a 
  20489.                 definition of a generic object. In SOM, a class is also a 
  20490.                 special kind of object that can manufacture other objects that 
  20491.                 all have a common shape and exhibit similar behavior. The 
  20492.                 specification of what comprises the shape and behavior of a set 
  20493.                 of objects is referred to as the "definition" of a class. New 
  20494.                 classes are defined in terms of existing classes through a 
  20495.                 technique known as inheritance. See also class object. 
  20496.  
  20497.  class variable  Instance data of a class object. All instance data of an 
  20498.                 object is defined (through either introduction or inheritance) 
  20499.                 by the object's class. Thus, class variables are defined by 
  20500.                 metaclasses. 
  20501.  
  20502.  class data structure  A structure provided by the SOM API to support efficient 
  20503.                 static access to class-specific information used in dealing 
  20504.                 with SOM objects. The structure's name is <className>ClassData. 
  20505.                 Its first component (classObject) is a pointer to the 
  20506.                 corresponding class object. The remaining components (named 
  20507.                 after the instance methods and instance variables) are method 
  20508.                 tokens or data tokens, in order as specified by the class's 
  20509.                 implementation. Data tokens are only used to support data 
  20510.                 (public and private) introduced by classes declared using OIDL; 
  20511.                 IDL attributes are supported with method tokens. 
  20512.  
  20513.  class manager  An object that acts as a run-time registry for all SOM class 
  20514.                 objects that exist within the current process and which assists 
  20515.                 in the dynamic loading and unloading of class libraries. A 
  20516.                 class implementor can define a customized class manager by 
  20517.                 subclassing SOMClassMgr class to replace the SOM-supplied 
  20518.                 SOMClassMgrObject. This is done to augment the functionality of 
  20519.                 the default class-management registry (for example, to 
  20520.                 coordinate the automatic quiescing and unloading of classes). 
  20521.  
  20522.  class method   (Also known as factory method or constructor.) A class method 
  20523.                 is a method that a class object responds to (as opposed to an 
  20524.                 instance method). A class method that class <X> responds to is 
  20525.                 provided by the metaclass of class <X>. Class methods are 
  20526.                 executed without requiring any instances of class <X> to exist, 
  20527.                 and are frequently used to create instances of the class. 
  20528.  
  20529.  class object   The run-time object representing a SOM class. In SOM, a class 
  20530.                 object can perform the same behavior common to all objects, 
  20531.                 inherited from SOMObject. 
  20532.  
  20533.  client code    (Or client program or client.) An application program, written 
  20534.                 in the programmer's preferred language, which invokes methods 
  20535.                 on objects that are instances of SOM classes. In DSOM, this 
  20536.                 could be a program that invokes a method on a remote object. 
  20537.  
  20538.  constructor    See class method. 
  20539.  
  20540.  context expression An optional expression in a method's IDL declaration, 
  20541.                 specifying identifiers whose value (if any) can be used during 
  20542.                 SOM's method resolution  process and/or by the target object as 
  20543.                 it executes the method procedure. If a context expression is 
  20544.                 specified, then a related Context parameter is required when 
  20545.                 the method is invoked. (This Context parameter is an implicit 
  20546.                 parameter in the IDL specification of the method, but it is an 
  20547.                 explicit parameter of the method's procedure.) No SOM-supplied 
  20548.                 methods require context parameters. 
  20549.  
  20550.  CORBA          The Common Object Request Broker Architecture established by 
  20551.                 the Object Management Group. IBM's Interface Definition 
  20552.                 Language used to describe the interface for SOM classes is 
  20553.                 fully compliant with CORBA standards. 
  20554.  
  20555.  data token     A value that identifies a specific instance variable within an 
  20556.                 object whose class inherits the instance variable (as a result 
  20557.                 of being derived, directly or indirectly, from the class that 
  20558.                 introduces the instance variable). An object and a data token 
  20559.                 are passed to the SOM run-time procedure, somDataResolve, which 
  20560.                 returns is a pointer to the specific instance variable 
  20561.                 corresponding to the data token. (See also instance token.) 
  20562.  
  20563.  derived class  See subclass and subclassing. 
  20564.  
  20565.  derived metaclass (Or SOM-derived metaclass.) A metaclass  that SOM creates 
  20566.                 automatically (often even when the class implementor specifies 
  20567.                 an explicit metaclass) as needed to ensure that, for any code 
  20568.                 that executes without method-resolution error on an instance of 
  20569.                 a given class, the code will similarly execute without 
  20570.                 method-resolution error on instances of any subclass of the 
  20571.                 given class. SOM's ability to derive such metaclasses is a 
  20572.                 fundamental necessity in order to ensure binary compatibility 
  20573.                 for client programs despite any subsequent changes in class 
  20574.                 implementations. 
  20575.  
  20576.  descriptor     (Or method descriptor.) An ID representing the identifier of a 
  20577.                 method definition or an attribute definition in the Interface 
  20578.                 Repository. The IR definition contains information about the 
  20579.                 method's return type and the type of its arguments. 
  20580.  
  20581.  directive      A message (a pre-defined character constant) received by a 
  20582.                 replica from the Replication Framework. Indicates a potential 
  20583.                 failure situation. 
  20584.  
  20585.  dirty object   A persistent object that has been modified since it was last 
  20586.                 written to persistent storage. 
  20587.  
  20588.  dispatch-function resolution Dispatch-function resolution is the slowest, but 
  20589.                 most flexible, of the three method-resolution techniques SOM 
  20590.                 offers. Dispatch functions permit method resolution to be based 
  20591.                 on arbitrary rules associated with an object's class. Thus, a 
  20592.                 class implementor has complete freedom in determining how 
  20593.                 methods invoked on its instances are resolved. See also 
  20594.                 dispatch method and dynamic dispatching. 
  20595.  
  20596.  dispatch method A method (such as somDispatch or somClassDispatch) that is 
  20597.                 invoked (and passed an argument list and the ID of another 
  20598.                 method) in order to determine the appropriate method procedure 
  20599.                 to execute. The use of dispatch methods facilitates 
  20600.                 dispatch-function resolution in SOM applications and enables 
  20601.                 method invocation on remote objects in DSOM applications. See 
  20602.                 also dynamic dispatching. 
  20603.  
  20604.  dynamic dispatching  Method dispatching using dispatch-function resolution; 
  20605.                 the use of dynamic method resolution at run time. See also 
  20606.                 dispatch- function resolution and dynamic method. 
  20607.  
  20608.  Dynamic Invocation Interface ( DII) The CORBA-specified interface, implemented 
  20609.                 in DSOM, that is used to dynamically build requests on remote 
  20610.                 objects. Note that DSOM applications can also use the 
  20611.                 somDispatch method for dynamic method calls when the object is 
  20612.                 remote. See also dispatch method. 
  20613.  
  20614.  dynamic method A method that is not declared in the IDL interface statement 
  20615.                 for a class of objects, but is added to the interface at run 
  20616.                 time, after which instances of the class (or of its subclasses) 
  20617.                 will respond to the registered dynamic method. Because dynamic 
  20618.                 methods are not declared, usage bindings for SOM classes cannot 
  20619.                 support their use; thus, offset method resolution is not 
  20620.                 available. Instead, name-lookup or dispatch-function method 
  20621.                 resolution must be used to invoke dynamic methods. (There are 
  20622.                 currently no known uses of dynamic methods by any SOM 
  20623.                 applications.) See also method and static method. 
  20624.  
  20625.  encapsulation  An object-oriented programming feature whereby the 
  20626.                 implementation details of a class are hidden from client 
  20627.                 programs, which are only required to know the interface of a 
  20628.                 class (the signatures of its methods and the names of its 
  20629.                 attributes) in order to use the class's methods and attributes. 
  20630.  
  20631.  encoder/decoder In the Persistence Framework, a class that knows how to 
  20632.                 read/write the persistent object format of a persistent object. 
  20633.                 Every persistent object is associated with an Encoder/Decoder, 
  20634.                 and an encoder/decoder object is created for each attribute and 
  20635.                 instance variable. An Encoder/Decoder is supplied by the 
  20636.                 Persistence Framework by default, or an application can define 
  20637.                 its own. 
  20638.  
  20639.  entry class    In the Emitter Framework, a class that represents some 
  20640.                 syntactic unit of an interface definition in the IDL source 
  20641.                 file. 
  20642.  
  20643.  Environment parameter A CORBA-required parameter in all method procedures, it 
  20644.                 represents a memory location where exception information can be 
  20645.                 returned by the object of a method invocation. [Certain methods 
  20646.                 are exempt (when the class contains a modifier of 
  20647.                 callstyle=oidl), to maintain upward compatibility for client 
  20648.                 programs written using an earlier release.] 
  20649.  
  20650.  emitter        Generically, a program that takes the output from one system 
  20651.                 and converts the information into a different form. Using the 
  20652.                 Emitter Framework, selected output from the SOM Compiler 
  20653.                 (describing each syntactic unit in an IDL source file) is 
  20654.                 transformed and formatted according to a user-defined template. 
  20655.                 Example emitter output, besides the implementation template and 
  20656.                 language bindings, might include reference documentation, class 
  20657.                 browser descriptions, or "pretty" printouts. 
  20658.  
  20659.  event          The occurrence of a condition, or the beginning or ending of an 
  20660.                 activity that is of interest to an application. Examples are 
  20661.                 elapse of a time interval, sending or receiving of a message, 
  20662.                 and opening or closing a file. (See also event manager and 
  20663.                 callback.) 
  20664.  
  20665.  event manager (EMan)  The chief component of the Event Management Framework 
  20666.                 that registers interest in various events from calling modules 
  20667.                 and informs them through callbacks when those events occur. 
  20668.  
  20669.  factory method See class method. 
  20670.  
  20671.  ID             See somId. 
  20672.  
  20673.  IDL source file A user-written .idl file, expressed using the syntax of the 
  20674.                 Interface Definition Language (IDL), which describes the 
  20675.                 interface for a particular class (or classes, for a module). 
  20676.                 The IDL source file is processed by the SOM Compiler to 
  20677.                 generate the binding files specific to the programming 
  20678.                 languages of the class implementor and the client application. 
  20679.                 (This file may also be called the "IDL file," the "source 
  20680.                 file," or the "interface definition file.") 
  20681.  
  20682.  implementation (Or object implementation.) The specification of what instance 
  20683.                 variables implement an object's state and what procedures 
  20684.                 implement its methods (or behaviors). In DSOM, a remote 
  20685.                 object's implementation is also characterized by its server 
  20686.                 implementation (a program). 
  20687.  
  20688.  Implementation Repository A database used by DSOM to store the implementation 
  20689.                 definitions of DSOM servers. 
  20690.  
  20691.  implementation statement An optional declaration within the body of the 
  20692.                 interface  definition of a class in a SOM IDL source file, 
  20693.                 specifying information about how the class will be implemented 
  20694.                 (such as, version numbers for the class, overriding of 
  20695.                 inherited methods, or type of method resolution to be supported 
  20696.                 by particular methods). This statement is a SOM-unique 
  20697.                 statement; thus, it must be preceded by the term "#ifdef 
  20698.                 __SOMIDL__" and followed by "#endif". See also interface 
  20699.                 declaration. 
  20700.  
  20701.  implementation template A template file containing stub procedures for 
  20702.                 methods that a class introduces or overrides. The 
  20703.                 implementation template is one of the binding files generated 
  20704.                 by the SOM Compiler when it processes the IDL source file 
  20705.                 containing class interface declarations. The class implementor 
  20706.                 then customizes the implementation, by adding language-specific 
  20707.                 code to the method procedures. 
  20708.  
  20709.  implicit method parameter A method parameter that is not included in the IDL 
  20710.                 interface specification of a method, but which is a parameter 
  20711.                 of the method's procedure and which is required when the method 
  20712.                 is invoked from a client program. Implicit parameters include 
  20713.                 the required Environment parameter indicating where exception 
  20714.                 information can be returned, as well as a Context parameter, if 
  20715.                 needed. 
  20716.  
  20717.  incremental update A revision to an implementation template file that results 
  20718.                 from reprocessing of the IDL source file by the SOM Compiler. 
  20719.                 The updated implementation file will contain new stub 
  20720.                 procedures, added comments, and revised method prototypes 
  20721.                 reflecting changes made to the method definitions in the IDL 
  20722.                 specification. Importantly, these updates do not disturb 
  20723.                 existing code that the class implementor has defined for the 
  20724.                 prior method procedures. 
  20725.  
  20726.  inheritance    The technique of defining one class (called a subclass, derived 
  20727.                 class, or child class) as incremental differences from another 
  20728.                 class (called the  parent class, base class, superclass, or 
  20729.                 ancestor class). From its parents, the subclass inherits 
  20730.                 variables and methods for its instances. The subclass can also 
  20731.                 provide additional instance variables and methods. Furthermore, 
  20732.                 the subclass can provide new procedures for implementing 
  20733.                 inherited methods. The subclass is then said to override the 
  20734.                 parent class's methods. An overriding method procedure can 
  20735.                 elect to call the parent class's method procedure. (Such a call 
  20736.                 is known as a parent method call.) 
  20737.  
  20738.  inheritance hierarchy The sequential relationship from a root class to a 
  20739.                 subclass, through which the subclass inherits instance methods, 
  20740.                 attributes, and  instance variables from all of its ancestors, 
  20741.                 either directly or indirectly. The root class of all SOM 
  20742.                 classes is SOMObject. 
  20743.  
  20744.  instance       (Or object instance or just object.) A specific object, as 
  20745.                 distinguished from a class of objects. See also object. 
  20746.  
  20747.  instance method A method valid for an object instance (as opposed to a class 
  20748.                 method, which is valid for a class object). An instance method 
  20749.                 that an object responds to is defined by its class or inherited 
  20750.                 from an ancestor class. 
  20751.  
  20752.  instance token  A data token that identifies the first instance variable among 
  20753.                 those introduced by a given class. The somGetInstanceToken 
  20754.                 method  invoked on a class object returns that class's instance 
  20755.                 token. 
  20756.  
  20757.  instance variables (Or, instance data.) Variables declared for use within the 
  20758.                 method procedures of a class. An instance variable is declared 
  20759.                 within the body of the implementation statement in a SOM IDL 
  20760.                 source file. An instance variable is "private" to the class and 
  20761.                 should not be accessed by a client program. ( Contrast an 
  20762.                 instance variable with an attribute.) 
  20763.  
  20764.  interface      The information that a client  must know to use a class 
  20765.                 namely, the names of its attributes and the signatures of its 
  20766.                 methods . The interface is described in a formal language (the 
  20767.                 Interface Definition Language, IDL) that is independent of the 
  20768.                 programming language used to implement the class's methods. 
  20769.  
  20770.  interface declaration (Or interface statement.) The statement in the IDL 
  20771.                 source file that specifies the name of a new class and the 
  20772.                 names of its parent class(es). The "body" of the interface 
  20773.                 declaration defines the signature of each new method and any 
  20774.                 attribute(s) associated with the class. In SOM IDL, the body 
  20775.                 may also include an implementation statement (where instance 
  20776.                 variables are declared or a modifier is specified, for example 
  20777.                 to override a method). 
  20778.  
  20779.  Interface Definition Language (IDL) The formal language (independent of any 
  20780.                 programming language) by which the interface for a class of 
  20781.                 objects is defined in a .idl file, which the SOM Compiler then 
  20782.                 interprets to create an implementation template file and 
  20783.                 binding files. SOM's Interface Definition Language is fully 
  20784.                 compliant with standards established by the Object Management 
  20785.                 Group's Common Object Request Broker Architecture (CORBA). 
  20786.  
  20787.  Interface Repository (IR) The database that SOM optionally creates to provide 
  20788.                 persistent storage of objects representing the major elements 
  20789.                 of interface definitions. Creation and maintenance of the IR is 
  20790.                 based on information supplied in the IDL source file. The SOM 
  20791.                 IR Framework supports all interfaces described in the CORBA 
  20792.                 standard. 
  20793.  
  20794.  Interface Repository Framework A set of classes that provide methods whereby 
  20795.                 executing programs can access the persistent objects of the 
  20796.                 Interface Repository to discover everything known about the 
  20797.                 programming interfaces of SOM classes. 
  20798.  
  20799.  macro          An alias for executing a sequence of hidden instructions; in 
  20800.                 SOM, typically the means of executing a command known within a 
  20801.                 binding file created by the SOM Compiler. 
  20802.  
  20803.  metaclass      A class whose instances are classes. In SOM, any class 
  20804.                 descended from SOMClass is a metaclass. The methods a class 
  20805.                 inherits from its metaclass are sometimes called class methods 
  20806.                 (in Smalltalk) or factory methods (in Objective-C) or 
  20807.                 constructors. See also class method. 
  20808.  
  20809.  metaclass incompatibility  A situation where a subclass does not include all 
  20810.                 of the class variables or respond to all of the class methods 
  20811.                 of its ancestor classes. This situation can easily arise in OOP 
  20812.                 systems that allow programmers to explicitly specify 
  20813.                 metaclasses, but is not allowed to occur in SOM. Instead, SOM 
  20814.                 automatically prevents this by creating and using derived 
  20815.                 metaclasses whenever necessary. 
  20816.  
  20817.  method         A combination of a procedure and a name, such that many 
  20818.                 different procedures can be associated with the same name. In 
  20819.                 object-oriented programming, invoking a method on an object 
  20820.                 causes the object to execute a specific method procedure. The 
  20821.                 process of determining which method procedure to execute when a 
  20822.                 method is invoked on an object is called method resolution. 
  20823.                 (The CORBA standard uses the term "operation" for method 
  20824.                 invocation). SOM supports two different kinds of methods: 
  20825.                 static methods and dynamic methods. See also static method and 
  20826.                 dynamic method. 
  20827.  
  20828.  method descriptor See descriptor. 
  20829.  
  20830.  method ID      A number representing a zero-terminated string by which SOM 
  20831.                 uniquely represents a method name. See also somId. 
  20832.  
  20833.  method procedure A function or procedure, written in an arbitrary programming 
  20834.                 language, that implements a method of a class. A method 
  20835.                 procedure is defined by the class implementor within the 
  20836.                 implementation template file generated by the SOM Compiler. 
  20837.  
  20838.  method prototype A method declaration that includes the types of the 
  20839.                 arguments. Based on method definitions in an IDL source file, 
  20840.                 the SOM Compiler generates method prototypes in the 
  20841.                 implementation template. A class implementor uses the method 
  20842.                 prototype as a basis for writing the corresponding method 
  20843.                 procedure code. The method prototype also shows all arguments 
  20844.                 and their types that are required to invoke the method from a 
  20845.                 client program. 
  20846.  
  20847.  method resolution The process of selecting a particular method procedure, 
  20848.                 given a method name and an object instance. The process results 
  20849.                 in selecting the particular function/procedure that implements 
  20850.                 the abstract method in a way appropriate for the designated 
  20851.                 object. SOM supports a variety of method-resolution mechanisms, 
  20852.                 including offset method resolution, name-lookup resolution, and 
  20853.                 dispatch-function resolution. 
  20854.  
  20855.  method table   A table of pointers to the  method procedures that implement 
  20856.                 the methods that an object supports. See also method token. 
  20857.  
  20858.  method token   A value that identifies a specific method introduced by a 
  20859.                 class. A method token is used during method resolution to 
  20860.                 locate the method procedure that implements the identified 
  20861.                 method. The two basic method-resolution procedures are 
  20862.                 somResolve (which takes as arguments an object and a method 
  20863.                 token, and returns a pointer to a procedure that implements the 
  20864.                 identified method on the given object) and somClassResolve 
  20865.                 (which takes as arguments a class and a method token, and 
  20866.                 returns a pointer to a procedure that implements the identified 
  20867.                 method on an instance of the given class). 
  20868.  
  20869.  modifier       Any of a set of statements that control how a class, an 
  20870.                 attribute, or a method will be implemented. Modifiers can be 
  20871.                 defined in the implementation statement of a SOM IDL source 
  20872.                 file. The implementation statement is a SOM-unique extension of 
  20873.                 the CORBA specification. [User-defined modifiers can also be 
  20874.                 specified for use by user-written emitters or to store 
  20875.                 information in the Interface Repository, which can then be 
  20876.                 accessed via methods provided by the Interface Repository 
  20877.                 Framework.] 
  20878.  
  20879.  module         The organizational structure required within an IDL source file 
  20880.                 that contains interface declarations for two (or more) classes 
  20881.                 that are not a class-metaclass pair. Such interfaces must be 
  20882.                 grouped within a module declaration. 
  20883.  
  20884.  multiple inheritance The situation in which a class is derived from (and 
  20885.                 inherits interface and implementation from) multiple parent 
  20886.                 classes. 
  20887.  
  20888.  name-lookup method resolution Similar to the method resolution techniques 
  20889.                 employed by Objective-C and Smalltalk. It is significantly 
  20890.                 slower than offset resolution. Name-lookup resolution, unlike 
  20891.                 offset resolution, can be used when the name of the method to 
  20892.                 be invoked is not known until run time, or the method is added 
  20893.                 to the class interface at run time, or the name of the class 
  20894.                 introducing the method is not known until run time. 
  20895.  
  20896.  naming scope   See scope. 
  20897.  
  20898.  object         (Or object instance  or just instance.) An entity that has 
  20899.                 state (its data values) and behavior (its methods). An object 
  20900.                 is one of the elements of data and function that programs 
  20901.                 create, manipulate, pass as arguments, and so forth. An object 
  20902.                 is a way to encapsulate state and behavior. Encapsulation 
  20903.                 permits many aspects of the implementation of an object to 
  20904.                 change without affecting client programs that depend on the 
  20905.                 object's behavior. In SOM, objects are created by other objects 
  20906.                 called classes. 
  20907.  
  20908.  object adapter (OA) A CORBA term denoting the primary interface a server 
  20909.                 implementation uses to access ORB functions; in particular, it 
  20910.                 defines the mechanisms that a server uses to interact with 
  20911.                 DSOM, and vice versa. This includes server 
  20912.                 activation/deactivation, dispatching of methods, and 
  20913.                 authentication of the principal making a call. The basic object 
  20914.                 adapter described by CORBA is defined by the BOA (basic object 
  20915.                 adapter) abstract class; DSOM's primary object adapter 
  20916.                 implementation is provided by the SOMOA (SOM Object Adapter) 
  20917.                 class. 
  20918.  
  20919.  object definition See class. 
  20920.  
  20921.  object implementation See implementation. 
  20922.  
  20923.  object instance  See instance and object. 
  20924.  
  20925.  object reference A CORBA term denoting the information needed to reliably 
  20926.                 identify a particular object. This concept is implemented in 
  20927.                 DSOM with a proxy object in a client process, or a SOMDObject 
  20928.                 in a server process. See also proxy object and SOMDObject. 
  20929.  
  20930.  object request broker (ORB) See ORB. 
  20931.  
  20932.  offset method resolution The default mechanism for performing method 
  20933.                 resolution in SOM, because it is the fastest (nearly as fast as 
  20934.                 an ordinary procedure call). It is roughly equivalent to the C 
  20935.                 ++ "virtual function" concept. Using offset method resolution 
  20936.                 requires that the name of the method to be invoked must be 
  20937.                 known at compile time, the name of the class that introduces 
  20938.                 the method must be known at compile time (although not 
  20939.                 necessarily by the programmer), and the method to be invoked 
  20940.                 must be a static method. 
  20941.  
  20942.  OIDL           The original language used for declaring SOM classes. The 
  20943.                 acronym stands for Object Interface Definition Language. OIDL 
  20944.                 is still supported by SOM release 2, but it does not include 
  20945.                 the ability to specify multiple inheritance classes. 
  20946.  
  20947.  one-copy serializable  The consistency property of the Replication Framework 
  20948.                 which states that the concurrent execution of methods on a 
  20949.                 replicated object is equivalent to the serial execution of 
  20950.                 those same methods on a nonreplicated object. 
  20951.  
  20952.  OOP            An acronym for "object-oriented programming." 
  20953.  
  20954.  operation      See method. 
  20955.  
  20956.  operation logging In the Replication Framework, a technique for maintaining 
  20957.                 consistency among replicas of a replicated object, whereby the 
  20958.                 execution of a method that updates the object is repeated at 
  20959.                 the site of each replica. 
  20960.  
  20961.  ORB (object request broker) A CORBA term designating the means by which 
  20962.                 objects transparently make requests (that is, invoke methods) 
  20963.                 and receive responses from objects, whether they are local or 
  20964.                 remote. With SOMobjects Developer Toolkit and Runtimes, this 
  20965.                 functionality is implemented in the DSOM Framework. Thus, the 
  20966.                 DSOM (Distributed SOM) system is an ORB. See also BOA (basic 
  20967.                 object adapter) class and SOMOA (SOM object adapter) class. 
  20968.  
  20969.  override       (Or overriding method.) The technique by which a class replaces 
  20970.                 (redefines) the implementation of a method that it inherits 
  20971.                 from one of its parent classes. An overriding method can elect 
  20972.                 to call the parent class's method procedure as part of its own 
  20973.                 implementation. (Such a call is known as a parent method call.) 
  20974.  
  20975.  parent class   A class from which another class inherits instance methods, 
  20976.                 attributes, and instance variables. A parent class is sometimes 
  20977.                 called a base class or superclass. 
  20978.  
  20979.  parent method call A technique where an overriding method calls the method 
  20980.                 procedure of its parent class as part of its own 
  20981.                 implementation. 
  20982.  
  20983.  persistent object An object whose state can be preserved beyond the 
  20984.                 termination of the process that created it. Typically, such 
  20985.                 objects are stored in files. 
  20986.  
  20987.  polymorphism   An object-oriented programming feature that may take on 
  20988.                 different meanings in different systems. Under various 
  20989.                 definitions of polymorphism, (a) a method or procedure call can 
  20990.                 be executed using arguments of a variety of types, or (b) the 
  20991.                 same variable can assume values of different types at different 
  20992.                 times, or (c) a method name can denote more than one method 
  20993.                 procedure. The SOM system reflects the third definition (for 
  20994.                 example, when a SOM class  overrides a parent class definition 
  20995.                 of a method to change its behavior). The term literally means 
  20996.                 "having many forms." 
  20997.  
  20998.  principal      The user on whose behalf a particular (remote) method call is 
  20999.                 being performed. 
  21000.  
  21001.  procedure      A small section of code that executes a limited, 
  21002.                 well-understood task when called from another program. In SOM, 
  21003.                 a method procedure is often referred to as a procedure. See 
  21004.                 also method procedure. 
  21005.  
  21006.  process        A series of instructions (a program or part of a program) that 
  21007.                 a computer executes in a multitasking environment. 
  21008.  
  21009.  proxy object   In DSOM, a SOM object  in the client's address space that 
  21010.                 represents a remote object. The proxy object has the same 
  21011.                 interface  as the remote object, but each method invoked on the 
  21012.                 proxy is overridden by a dispatch method that forwards the 
  21013.                 invocation request to the remote object. Under DSOM, a proxy 
  21014.                 object is created dynamically and automatically in the client 
  21015.                 whenever a remote method returns a pointer to an object that 
  21016.                 happens to be remote. 
  21017.  
  21018.  readers and writers In the Replication Framework, different processes can 
  21019.                 access the same replicated object in different modes. A 
  21020.                 "reader" is a process that does not intend to update the 
  21021.                 object, but wants to continually watch the object as other 
  21022.                 processes update it. A "writer" is a process that wants to 
  21023.                 update the object, as well as continually watch the updates 
  21024.                 performed by others. 
  21025.  
  21026.  receiver       See target object. 
  21027.  
  21028.  redispatch stub A procedure, corresponding to a particular method, which has 
  21029.                 the same signature as the method's procedure but which invokes 
  21030.                 somDispatch to dispatch the method. The somOverrideMtab method 
  21031.                 can be used to replace the procedure pointers in a class's 
  21032.                 method table with the corresponding redispatch stubs. This is 
  21033.                 done when overriding somDispatch to customize method resolution 
  21034.                 so that all static method invocations will be routed through 
  21035.                 somDispatch for selection of an appropriate method procedure. 
  21036.                 (Dynamic methods have no entries in the method table, so they 
  21037.                 cannot be supported with redispatch functionality.) 
  21038.  
  21039.  reference data Application-specific data that a server uses to identify or 
  21040.                 describe an object in DSOM. The data, represented by a sequence 
  21041.                 of up to 1024 bytes, is registered with DSOM when a server 
  21042.                 creates an object reference. A server can later ask DSOM to 
  21043.                 return the reference data associated with an object reference. 
  21044.                 See also object reference. 
  21045.  
  21046.  replica        When an object is replicated among a set of processes (using 
  21047.                 the Replication Framework), each process is said to have a 
  21048.                 replica of the object. From the view point of any application 
  21049.                 model, the replicas together represent a single object. 
  21050.  
  21051.  replicated object An object for which replicas (copies) exist.  See replica. 
  21052.  
  21053.  run-time environment The data structures, objects, and global variables that 
  21054.                 are created, maintained, and used by the functions, procedures, 
  21055.                 and methods in the SOM run-time library. 
  21056.  
  21057.  scope          (Or naming scope.) That portion of a program within which an 
  21058.                 identifier name has "visibility" and denotes a unique variable. 
  21059.                 In SOM, an IDL source file forms a scope. An identifier can 
  21060.                 only be defined once within a scope; identifiers can be 
  21061.                 redefined within a nested scope. In a .idl file, modules, 
  21062.                 interface statements, structures, unions, methods, and 
  21063.                 exceptions form nested scopes. 
  21064.  
  21065.  serializable   See one-copy serializable. 
  21066.  
  21067.  server         (Or server implementation.) In DSOM, a process, running in a 
  21068.                 distributed environment, that executes the implementation of an 
  21069.                 object. DSOM provides a default server implementation that can 
  21070.                 dynamically load SOM class libraries, create SOM objects, and 
  21071.                 make those objects accessible to clients. Developers can also 
  21072.                 write application-specific servers for use with DSOM. 
  21073.  
  21074.  server object  In DSOM, every server has an object that defines methods for 
  21075.                 managing objects in that server. These methods include object 
  21076.                 creation, object destruction, and maintaining mappings between 
  21077.                 object references and the objects they reference. A server 
  21078.                 object must be an instance of the class SOMDServer (or one of 
  21079.                 its subclasses). See also object reference and SOMDObject. 
  21080.  
  21081.  shadowing      In the Emitter Framework, a technique that is required when any 
  21082.                 of the entry classes are subclassed. Shadowing causes instances 
  21083.                 of the new subclass(es) (rather than instances of the original 
  21084.                 entry classes) to be used as input for building the object 
  21085.                 graph, without requiring a recompile of emitter framework code. 
  21086.                 Shadowing is accomplished by using the macro 
  21087.                 SOM_SubstituteClass. 
  21088.  
  21089.  signature      The collection of types associated with a method (the type of 
  21090.                 its return value, if any, as well as the number, order, and 
  21091.                 type of each of its arguments). 
  21092.  
  21093.  sister class object A duplicate of a class object that is created in order to 
  21094.                 save a copy of the class's original method table before 
  21095.                 replacing the method table to customize method resolution. The 
  21096.                 sister class object is created so that some original method 
  21097.                 procedures can be called by the replacement method procedures. 
  21098.  
  21099.  Sockets class  A class that provides a common communications interface to 
  21100.                 Distributed SOM, the Replication Framework, and the Event 
  21101.                 Management Framework. The Sockets class provides the base 
  21102.                 interfaces (patterned after TCP/IP sockets); the subclasses 
  21103.                 TCPIPSockets, NBSockets, and IPXSockets provide actual 
  21104.                 implementations for TCP/IP, Netbios, and Netware IPX/SPX, 
  21105.                 respectively. 
  21106.  
  21107.  SOM Compiler   A tool provided by the SOM Toolkit that takes as input the 
  21108.                 interface definition file for a class (the .idl file) and 
  21109.                 produces a set of binding files that make it more convenient to 
  21110.                 implement and use SOM classes. 
  21111.  
  21112.  SOMClass       One of the three primitive class objects of the SOM run-time 
  21113.                 environment. SOMClass is the root (meta)class from which all 
  21114.                 subsequent metaclasses are derived. SOMClass defines the 
  21115.                 essential behavior common to all SOM class objects. 
  21116.  
  21117.  SOMClassMgr    One of the three primitive class objects of the SOM run-time 
  21118.                 environment. During SOM initialization, a single instance 
  21119.                 (object) of SOMClassMgr is created, called SOMClassMgrObject. 
  21120.                 This object maintains a directory of all SOM classes that exist 
  21121.                 within the current process, and it assists with dynamic loading 
  21122.                 and unloading of class libraries. 
  21123.  
  21124.  SOM-derived metaclass See derived metaclass. 
  21125.  
  21126.  SOMDObject     The class that implements the notion of a CORBA "object 
  21127.                 reference" in DSOM. An instance of SOMDObject contains 
  21128.                 information about an object's server implementation and 
  21129.                 interface, as well as a user-supplied identifier. 
  21130.  
  21131.  somId          A pointer to a number that uniquely represents a 
  21132.                 zero-terminated string. Such pointers are declared as type 
  21133.                 somId. In SOM, somId's are used to represent method names, 
  21134.                 class names, and so forth. 
  21135.  
  21136.  SOMObject      One of the three primitive class objects of the SOM run-time 
  21137.                 environment. SOMObject is the root class for all SOM 
  21138.                 (sub)classes. SOMObject defines the essential behavior common 
  21139.                 to all SOM objects. 
  21140.  
  21141.  SOMOA (SOM object adapter) class In DSOM, a class that dispatches methods on a 
  21142.                 server's objects, using the SOM Compiler and run-time support. 
  21143.                 The SOMOA class implements methods defined in the abstract BOA 
  21144.                 class (its base class). See also BOA class. 
  21145.  
  21146.  somSelf        Within method procedures  in the implementation file for a 
  21147.                 class, a parameter pointing to the target object that is an 
  21148.                 instance  of the class being implemented. It is local to the 
  21149.                 method procedure. 
  21150.  
  21151.  somThis        Within method procedures, a local variable that points to a 
  21152.                 data structure containing the instance variables introduced by 
  21153.                 the class. If no instance variables are specified in the SOM 
  21154.                 IDL source file, then the somThis assignment statement is 
  21155.                 commented out by the SOM Compiler. 
  21156.  
  21157.  state (of an object) The data (attributes, instance variables and their 
  21158.                 values) associated with an object. See also behavior. 
  21159.  
  21160.  static method  Any method that can be accessed through offset method 
  21161.                 resolution. Any method declared in the IDL specification of a 
  21162.                 class is a static method. See also method and dynamic method. 
  21163.  
  21164.  stub procedures Method procedures in the implementation template generated by 
  21165.                 the SOM Compiler. They are procedures whose bodies are largely 
  21166.                 vacuous, to be filled in by the implementor. 
  21167.  
  21168.  subclass       A class that inherits instance methods, attributes, and 
  21169.                 instance variables directly from another class, called the 
  21170.                 parent class, base class, superclass, or indirectly from an 
  21171.                 ancestor class. A subclass may also be called a child class or 
  21172.                 derived class. 
  21173.  
  21174.  subclassing    The process whereby a new class, as it is created (or derived), 
  21175.                 inherits instance methods, attributes, and instance variables 
  21176.                 from one or more previously defined ancestor classes. The 
  21177.                 immediate parent class(es) of a new class must be specified in 
  21178.                 the class's interface declaration. See also inheritance. 
  21179.  
  21180.  superclass     See parent class. 
  21181.  
  21182.  symbol         In the Emitter Framework, any of a (standard or user-defined) 
  21183.                 set of names (such as, className) that are used as placeholders 
  21184.                 when building a text template to pattern the desired emitter 
  21185.                 output. When a template is emitted, the symbols are replaced 
  21186.                 with their corresponding values from the emitter's symbol 
  21187.                 table. Other symbols (such as, classSN) have values that are 
  21188.                 used by section-emitting methods to identify major sections of 
  21189.                 the template (which are correspondingly labeled as "classS" or 
  21190.                 by a user-defined name). 
  21191.  
  21192.  target object  (Or receiver.) The object responding to a method call. The 
  21193.                 target object is always the first formal parameter of a method 
  21194.                 procedure. For SOM's C-language bindings, the target object is 
  21195.                 the first argument provided to the method invocation macro, 
  21196.                 _methodName. 
  21197.  
  21198.  usage bindings The language-specific binding files for a class that are 
  21199.                 generated by the SOM Compiler for inclusion in client programs 
  21200.                 using the class. 
  21201.  
  21202.  value logging  In the Replication Framework, a technique for maintaining 
  21203.                 consistency among replicas of a replicated object, whereby the 
  21204.                 new value of the object is distributed after the execution of a 
  21205.                 method that updates the object. 
  21206.  
  21207.  view-data paradigm A Replication Framework construct similar to the 
  21208.                 Model-View-Controller paradigm in SmallTalk. The "view" object 
  21209.                 contains only presentation-specific information, while the 
  21210.                 "data" object contains the state of the application. The "view" 
  21211.                 and "data" are connected by means of an "observation" protocol 
  21212.                 that lets the "view" be notified whenever the "data" changes. 
  21213.  
  21214.  writers        See readers and writers. 
  21215.