home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 14 Text / 14-Text.zip / somguide.zip / SOMGUIDE.INF (.txt)
OS/2 Help File  |  1998-04-20  |  655KB  |  20,066 lines

  1.  
  2. ΓòÉΓòÉΓòÉ 1. About This Book ΓòÉΓòÉΓòÉ
  3.  
  4. This book accompanies the SOMobjects Base Toolkit, which consists of the base 
  5. (or core) capabilities in the System Object Model (SOM) of the SOMobjects 
  6. Developer Toolkit.  The base system is a rich subset of the full-capability 
  7. SOMobjects Developer Toolkit. Because the current manual is a subset of 
  8. chapters from the full  SOMobjects Developer Toolkit Users Guide, references 
  9. herein to the "SOMobjects Developer Toolkit" should be interpreted as 
  10. capabilities of the SOMobjects Base Toolkit. 
  11.  
  12. This manual explains how programmers using C, C++, and other languages can: 
  13.  
  14.      Implement class libraries that exploit the SOM library-packaging 
  15.       technology, 
  16.  
  17.      Develop client programs that use class libraries that were built using 
  18.       SOM, and 
  19.  
  20.      Develop applications that use the frameworks supplied with the SOMobjects 
  21.       Toolkit, class libraries that facilitate development of object-oriented 
  22.       applications. 
  23.  
  24.  In addition to this book, refer to the System Object Model Programming 
  25.  Reference during application development for specific information about the 
  26.  classes, methods, functions, and macros supplied with the SOMobjects Toolkit. 
  27.  
  28.  For purchasers of the full-capability SOMobjects systems, the SOMobjects 
  29.  Developer Toolkit: Emitter Framework Guide and Reference contains 
  30.  documentation of the Emitter Framework of the SOMobjects Developer Toolkit. In 
  31.  addition, the SOMobjects Developer Toolkit: Collection Classes Reference 
  32.  Manual describes the collection classes and methods provided with the 
  33.  SOMobjects Developer Toolkit. 
  34.  
  35.  
  36. ΓòÉΓòÉΓòÉ 1.1. How This Book Is Organized ΓòÉΓòÉΓòÉ
  37.  
  38. This book is a subset of the SOMobjects Developer Toolkit Users Guide for the 
  39. full-capability SOMobjects Developer Toolkit.  The omitted chapters describe 
  40. capabilities not included with the SOMobjects Base Toolkit.  Chapters that are 
  41. included appear in their entirety, as written for the full-capability 
  42. SOMobjects systems, except for some references to capabilities not included in 
  43. the SOMobjects Base Toolkit. 
  44.  
  45.      Introducing the SOMobjects Developer Toolkit provides an overview of the 
  46.       major elements of SOM. 
  47.  
  48.      Tutorial for Implementing SOM Classes contains a Tutorial with five 
  49.       evolutionary examples that illustrate techniques for implementing classes 
  50.       in SOM. All readers should cover this tutorial. 
  51.  
  52.      Using SOM Classes in Client Programs describes how an application program 
  53.       creates instances of a SOM class, how it invokes methods, and so on. For 
  54.       readers interested only in using SOM classes, rather than building them, 
  55.       chapters 2 and 3 may provide all of the information they need to begin 
  56.       using SOM classes. 
  57.  
  58.      SOM IDL and the SOM Compiler contains explanations and examples for all 
  59.       valid SOM IDL syntax components, it then presents the SOM Compiler, 
  60.       including all compiler options and related environment variables.  All 
  61.       class implementors will need to reference this chapter. 
  62.  
  63.      Implementing Classes in SOM provides more comprehensive information about 
  64.       the SOM system itself, including operation of the SOM run-time 
  65.       environment, inheritance, and method resolution.  This chapter also 
  66.       describes how to create language-neutral class libraries using SOM.  In 
  67.       addition, it contains some advanced topics for customizing SOM to better 
  68.       suit the needs of a particular application. All class implementors will 
  69.       need to reference this chapter. 
  70.  
  71.      Distributed SOM (DSOM) describes Distributed SOM and how to use it to 
  72.       access objects across address spaces, even on different machines. This 
  73.       chapter also describes how to customize DSOM. Note that SOMobjects Base 
  74.       Toolkit supports only Workstation DSOM (distribution among processes on a 
  75.       single machine), whereas SOMobjects Developer Toolkit also supports 
  76.       Workgroup DSOM (distribution among a network of machines). 
  77.  
  78.      SOM Interface Repository Framework describes the Interface Repository 
  79.       Framework of classes supplied with the SOMobjects Toolkit. 
  80.  
  81.      Metaclass Framework describes the Metaclass Framework and some utility 
  82.       metaclasses that SOM provides to assist users in deriving new classes 
  83.       with special abilities to execute "before" and "after" operations when a 
  84.       method call occurs, as well as other capabilities for modifying the 
  85.       default semantics of method invocation and object creation. 
  86.  
  87.      Event Management Framework describes the Event Manager Framework, which 
  88.       allows grouping of all application events and waiting on multiple events 
  89.       in one place. The Event Manager is used by DSOM. 
  90.  
  91.      SOMobjects Error Codes contains lists of the error codes and messages 
  92.       that can be issued by the SOM kernel or by the various frameworks. 
  93.  
  94.      SOM IDL Language Grammar contains the SOM IDL language grammar. 
  95.  
  96.      Implementing Sockets Subclasses describes how to subclass a "Sockets" 
  97.       class that facilitates inter-process communications required by the DSOM, 
  98.       Replication, and Event Management Frameworks. 
  99.  
  100.      A glossary and an index conclude this programming guide. 
  101.  
  102.  
  103. ΓòÉΓòÉΓòÉ 1.2. Who Should Read This Book ΓòÉΓòÉΓòÉ
  104.  
  105. This book is for the professional programmer using C, C++, or another language 
  106. who wishes to 
  107.  
  108.      Use SOM to build object-oriented class libraries, or 
  109.  
  110.      Write application programs using class libraries that others have 
  111.       implemented using SOM, 
  112.  
  113.  even if the programming language does not directly support object-oriented 
  114.  programming. 
  115.  
  116.  The discussions in this book are expressed in the commonly used terminology of 
  117.  object-oriented programming. A number of important terms are everyday English 
  118.  words that take on specialized meanings. These terms appear in the Glossary at 
  119.  the back of this book. You may find it worth consulting the Glossary if the 
  120.  unusual significance attached to an otherwise ordinary word puzzles you. 
  121.  
  122.  This book assumes that you are an experienced programmer and that you have a 
  123.  general familiarity with the basic notions of object-oriented programming. 
  124.  Practical experience using an object-oriented programming language is helpful, 
  125.  but not essential. 
  126.  
  127.  If you would like a good introduction to object-oriented programming or a 
  128.  general survey of the many aspects of the topic, you might enjoy reading one 
  129.  of the following books: 
  130.  
  131.      Booch, G, Object-Oriented Design with Applications, Benjamin/Cummings 
  132.       1991, ISBN 0-8053-0091-0. 
  133.  
  134.      Budd, T, An Introduction to Object-Oriented Programming, Addison-Wesley 
  135.       1991, ISBN 0-201-54709-0. 
  136.  
  137.      Cox, B, and Novobilski, A, Object-Oriented Programming, An Evolutionary 
  138.       Approach 2nd Edition, Addison-Wesley 1991, ISBN 0-201-54834-8. 
  139.  
  140.  
  141. ΓòÉΓòÉΓòÉ 2. Introducing the SOMobjects Developer Toolkit ΓòÉΓòÉΓòÉ
  142.  
  143. This section contains: 
  144.  
  145.      Background information 
  146.      An overview of the SOMobjects Toolkit 
  147.      What's New in SOMobjects Version 2.1 
  148.  
  149.  
  150. ΓòÉΓòÉΓòÉ 2.1. Background ΓòÉΓòÉΓòÉ
  151.  
  152. Object-oriented programming (or OOP) is an important new programming technology 
  153. that offers expanded opportunities for software reuse and extensibility. 
  154. Object-oriented programming shifts the emphasis of software development away 
  155. from functional decomposition and toward the recognition of units (called 
  156. objects) that encapsulate both code and data.  As a result, programs become 
  157. easier to maintain and enhance. Object-oriented programs are typically more 
  158. impervious to the "ripple effects" of subsequent design changes than their 
  159. non-object-oriented counterparts. This, in turn, leads to improvements in 
  160. programmer productivity. 
  161.  
  162. Despite its promise, penetration of object-oriented technology to major 
  163. commercial software products has progressed slowly because of certain 
  164. obstacles.  This is particularly true of products that offer only a binary 
  165. programming interface to their internal object classes (Example: products that 
  166. do not allow access to source code). 
  167.  
  168. The first obstacle that developers must confront is the choice of an 
  169. object-oriented programming language. 
  170.  
  171. So-called"pure" object-oriented language (such as Smalltalk) presume a complete 
  172. run-time environment (sometimes known as a virtual machine), because their 
  173. semantics represent a major departure from traditional, procedure-oriented 
  174. system architectures.  So long as the developer works within the supplied 
  175. environment, everything works smoothly and consistently.  When the need arises 
  176. to interact with foreign environment, however (for example, to make an external 
  177. procedure call), the pure-object paradigm ends, and objects must be reduced to 
  178. data structures for external manipulation.  Unfortunately, data structures do 
  179. not retain the advantage that objects offer with regard to encapsulation and 
  180. code reuse. 
  181.  
  182. "Hybrid" languages such as C++(**) on the other hand, require less run-time 
  183. support, but sometimes result in tight bindings between programs that implement 
  184. objects (called "class libraries") and their clients (the programs that use 
  185. them). That is, implementation detail is often unavoidably compiled into the 
  186. client programs.  Tight binding between class libraries and their clients means 
  187. that client programs often must be recompiled whenever simple changes are made 
  188. in the library.  Furthermore, no binary standard exists for C++ objects, so the 
  189. C++ class libraries produced by one C++ compiler cannot (in general) be used 
  190. from C++ programs built with a different C++ compiler. 
  191.  
  192. The second obstacle developers of object-oriented software must confront is 
  193. that, because different object-oriented languages and toolkits embrace 
  194. incompatible models of what objects are and how they work, software developed 
  195. using a particular language or toolkit is naturally limited in scope.  Classes 
  196. implemented in one language cannot be readily used from another.  A C++ 
  197. programmer, for example, cannot easily use classes developed in Smalltalk, nor 
  198. can a Smalltalk programmer make effective use of C++ classes. Object-oriented 
  199. language and toolkit boundaries become, in effect, barriers to 
  200. interoperability. 
  201.  
  202. Ironically, no such barrier exists for ordinary procedure libraries. Software 
  203. developers routinely construct procedure libraries that can be shared across a 
  204. variety of languages, by adhering to standard linkage conventions. 
  205. Object-oriented class libraries are inherently different in that no binary 
  206. standards or conventions exist to derive a new class from an existing one,  or 
  207. even to invoke a method in a standard way.  Procedure libraries also have the 
  208. benefit that their implementations can be freely changed without requiring 
  209. client programs to be recompiled, unlike the situation for C++ class libraries. 
  210.  
  211. For developers who need to provide binary class libraries, these are serious 
  212. obstacles. In an era of open systems and heterogeneous networking, a 
  213. single-language solution is frequently not broad enough.  Certainly, mandating 
  214. a specific compiler from a specific vendor in order to use a class library 
  215. might be grounds not to include the class library with an operating system or 
  216. other general-purpose product. 
  217.  
  218. The System Object Model (SOM) is IBM's solution to these problems. 
  219.  
  220.  
  221. ΓòÉΓòÉΓòÉ 2.2. An Overview of SOM and the SOMobjects Toolkit ΓòÉΓòÉΓòÉ
  222.  
  223. The System Object Model (SOM) is a new object-oriented programming technology 
  224. for building, packaging, and manipulating binary class libraries. 
  225.  
  226.      With SOM, class implementers describe the interface for a class of 
  227.       objects (names of the methods it supports, the return types, parameter 
  228.       types, and so forth) in a standard language called the Interface 
  229.       Definition Language, or IDL. 
  230.  
  231.      They then implement methods in their preferred programming language 
  232.       (which may be either an object-oriented programming language or a 
  233.       procedural language such as C). 
  234.  
  235.  This means that programmers can begin using SOM quickly, and also extends the 
  236.  advantages of OOP to programmers who use non-object-oriented programming 
  237.  languages. 
  238.  
  239.  A principal benefit of using SOM is that SOM accommodates changes in 
  240.  implementation details and even in certain facets of a class ' interface, 
  241.  without breaking the binary interface to a class library and without requiring 
  242.  recompilation of client programs.  As a rule of thumb , if changes to a SOM 
  243.  class do not require source-code changes in client programs, then those client 
  244.  programs will not need to be recompiled. This is not true of many 
  245.  object-oriented languages, and it is one of the chief benefits of using SOM. 
  246.  For instance, SOM classes can undergo structural changes such as the 
  247.  following, yet retain full backward, binary compatibility: 
  248.  
  249.      Adding new methods, 
  250.  
  251.      Changing the size of an object by adding or deleting instance variables, 
  252.  
  253.      Inserting new parent (base) classes above a class in the inheritance 
  254.       hierarchy, and 
  255.  
  256.      Relocating methods upward in the class hierarchy. 
  257.  
  258.  In short, implementers can make the typical kinds of changes to an 
  259.  implementation and its interfaces that evolving software systems experience 
  260.  over time. 
  261.  
  262.  Unlike the object models found in formal object-oriented programming 
  263.  languages, SOM is language-neutral.  It preserves the key OOP characteristics 
  264.  of encapsulation, inheritance, and polymorphism, without requiring that the 
  265.  user of a SOM class and the implementer of a SOM class use the same 
  266.  programming language.  SOM is said to be language-neutral for four reasons: 
  267.  
  268.    1. All SOM interactions consist of standard procedure calls. On systems that 
  269.       have a standard linkage convention for system calls, SOM interactions 
  270.       conform to those conventions. Thus, most programming languages that can 
  271.       make external procedure calls can use SOM. 
  272.  
  273.    2. The form of the SOM Application Programming Interface, or API (the way 
  274.       that programmers invoke methods, create objects, and so on) can vary 
  275.       widely from language to language, as a benefit of the SOM bindings. 
  276.       Bindings are a set of macros and procedure calls that make implementing 
  277.       and using SOM classes more convenient by tailoring the interface to a 
  278.       particular programming language. 
  279.  
  280.    3. SOM supports several mechanisms for method resolution that can be readily 
  281.       mapped into the semantics of a wide range of object-oriented programming 
  282.       languages. Thus, SOM class libraries can be shared across object-oriented 
  283.       languages that have differing object models.  A SOM object can 
  284.       potentially be accessed with three different forms of method resolution: 
  285.  
  286.           Offset resolution: roughly equivalent to the C++ "virtual function" 
  287.            concept. Offset resolution implies a static scheme for typing 
  288.            objects, with polymorphism based strictly on class derivation.  It 
  289.            offers the best performance characteristics for SOM method 
  290.            resolution.  Methods accessible through offset resolution are called 
  291.            static methods, because they are considered a fixed aspect of an 
  292.            object's interface. 
  293.  
  294.           Name-lookup resolution: similar to that employed by Objective-C and 
  295.            Smalltalk.  Name resolution supports untyped (sometimes called 
  296.            "dynamically" typed) access to objects, with polymorphism based on 
  297.            the actual protocols that objects honor. Name resolution offers the 
  298.            opportunity to write code to manipulate objects with little or no 
  299.            awareness of the type or shape of the object when the code is 
  300.            compiled. 
  301.  
  302.           Dispatch-function resolution: a unique feature of SOM that permits 
  303.            method resolution based on arbitrary rules known only in the domain 
  304.            of the receiving object. Languages that require special entry or 
  305.            exit sequences or local objects that represent distributed object 
  306.            domains are good candidates for using dispatch-function resolution. 
  307.            This technique offers the highest degree of encapsulation for the 
  308.            implementation of an object, with some cost in performance. 
  309.  
  310.    4. SOM conforms fully with the Object Management Group's (OMG) [ OMG is an 
  311.       industry consortium founded to advance the use of object technology in 
  312.       distributed, heterogeneous environments] Common Object Request Broker 
  313.       Architecture (CORBA) standards. In particular, 
  314.  
  315.           Interface to SOM classes are described in CORBA's Interface 
  316.            Definition Language, IDL, and the entire SOMobjects Toolkit supports 
  317.            all CORBA-defined data types. 
  318.  
  319.           The SOM bindings for the C language are compatible with the C 
  320.            bindings prescribed by CORBA. 
  321.  
  322.           All information about the interface to a SOM class is available at 
  323.            run time through a CORBA-defined "Interface Repository." 
  324.  
  325.  SOM is not intended to replace existing object-oriented languages. Rather, it 
  326.  is intended to complement them so that application programs written in 
  327.  different programming languages can share common SOM class libraries. For 
  328.  example, SOM can be used with C++ to do the following: 
  329.  
  330.      Provide upwardly compatible class libraries, so that when a new version 
  331.       of a SOM class is released, client code needn't be recompiled, so long as 
  332.       no changes to the client's source code are required. 
  333.  
  334.      Allow other language users (and other C++ compiler users) to use SOM 
  335.       classes implemented in C++. 
  336.  
  337.      Allow C++ programs to use SOM classes implemented using other languages. 
  338.  
  339.      Allow other language users to implement SOM classes derived from SOM 
  340.       classes implemented in C++. 
  341.  
  342.      Allow C++ programmers to implement SOM classes derived from SOM classes 
  343.       implemented using other languages. 
  344.  
  345.      Allow encapsulation (implementation hiding) so that SOM class libraries 
  346.       can be shared without exposing private instance variables and methods. 
  347.  
  348.      Allow dynamic (run-time) method resolution in addition to static 
  349.       (compile-time) method resolution (on SOM objects). 
  350.  
  351.      Allow information about classes to be obtained and updated at run time. 
  352.       (C++ classes are compile-time structures that have no properties at run 
  353.       time.) 
  354.  
  355.  
  356. ΓòÉΓòÉΓòÉ 2.2.1. The SOM Compiler ΓòÉΓòÉΓòÉ
  357.  
  358. The SOMobjects Toolkit contains a tool, called the SOM Compiler, that helps 
  359. implementers build classes in which interface and implementation are decoupled. 
  360. The SOM Compiler reads the IDL definition of a class interface and generates: 
  361.  
  362.      an implementation skeleton for the class, 
  363.  
  364.      bindings for implementers, and 
  365.  
  366.      bindings for client programs. 
  367.  
  368.  Bindings are language-specific macros and procedures  that make implementing 
  369.  and using SOM classes more convenient. These bindings offer a convenient 
  370.  interface to SOM that is tailored to a particular programming language.  For 
  371.  instance, C programmers can invoke methods in the same way they make ordinary 
  372.  procedure calls. The C++ bindings "wrap" SOM objects as C++ objects, so that 
  373.  C++ programmers can invoke methods on SOM objects in the same way they invoke 
  374.  methods on C++ objects. In addition, SOM objects receive full C++ 
  375.  typechecking, just as C++ objects do.  Currently, the SOM Compiler can 
  376.  generate both C and C++ language bindings for a class. The C and C++ bindings 
  377.  will work with a variety of commercial products available from IBM and others. 
  378.  Vendors of other programming languages may also offer SOM bindings.  Check 
  379.  with your language vendor about possible SOM support. 
  380.  
  381.  
  382. ΓòÉΓòÉΓòÉ 2.2.2. The SOM run-time library ΓòÉΓòÉΓòÉ
  383.  
  384. In addition to the SOM Compiler, SOM includes a run-time library.  This library 
  385. provides, among other things, a set of classes, methods, and procedures used to 
  386. create object and invoke methods on them.  The library allows any programming 
  387. language to use SOM classes (classes developed using SOM) if that language can: 
  388.  
  389.      Call external procedures, 
  390.  
  391.      Store a pointer to a procedure and subsequently invoke that procedure, 
  392.       and 
  393.  
  394.      Map IDL types onto the programming language's native types. 
  395.  
  396.  Thus, the user of a SOM class and the implementer of a SOM class needn't use 
  397.  the same programming language, and neither is required to use an 
  398.  object-oriented language.  The independence of client language and 
  399.  implementation language also extends to subclassing: a SOM class can be 
  400.  derived from other SOM classes, and the subclass may or may not be implemented 
  401.  in the same language as the parent class(es). Moreover, SOM's run-time 
  402.  environment allows applications to access information about classes 
  403.  dynamically (at run time). 
  404.  
  405.  
  406. ΓòÉΓòÉΓòÉ 2.2.3. Frameworks provided in the SOMobjects Toolkit ΓòÉΓòÉΓòÉ
  407.  
  408. In addition to SOM itself (the SOM compiler and the SOM run-time library), the 
  409. SOMobjects Developer Toolkit also provides a set of frameworks (class 
  410. libraries) that can be used in developing object-oriented applications.  These 
  411. include Distributed SOM, the Interface Repository Framework, and the Emitter 
  412. Framework, and the Metaclass Framework, described below. 
  413.  
  414. Note:  SOMobjects Base Toolkit, the core version of SOMobject shipped with this 
  415.        documentation, contains only Distributed SOM, the Interface Repository, 
  416.        and the Metaclass frameworks. The complete SOMobjects Developer Toolkit 
  417.        can be ordered from IBM by calling 1-800-342-6672 in the U.S. or 
  418.        1-800-465-7999 in Canada. The part number is 10H9767 for the CD-ROM 
  419.        containing SOMobjects for the AIX, OS/2, and Windows platforms 
  420.        (including online documentation). SOMobjects manuals are available 
  421.        individually. 
  422.  
  423.  
  424. ΓòÉΓòÉΓòÉ 2.2.3.1. Distributed SOM ΓòÉΓòÉΓòÉ
  425.  
  426. Distributed SOM  (or DSOM) allows application programs to access SOM objects 
  427. across address spaces.. That is, application programs can access objects in 
  428. other processes, even on different machines.  DSOM provides this transparent 
  429. access to remote objects through its Object Request Broker (ORB): the location 
  430. and implementation of the object are hidden from the client, and the client 
  431. accesses the object as if local.  The current release of DSOM supports 
  432. distribution of objects among processes within a workstation, and across a 
  433. local area network consisting of OS/2 system, AIX systems, or a mix of both. 
  434. Future releases may support larger enterprise-wide networks. 
  435.  
  436.  
  437. ΓòÉΓòÉΓòÉ 2.2.3.2. Interface Repository Framework ΓòÉΓòÉΓòÉ
  438.  
  439. The Interface Repository is a database, optionally created and maintained by 
  440. the SOM Compiler, that holds all the information contained in the IDL 
  441. description of a class of objects. The Interface Repository Framework consists 
  442. of the 11 classes defined in the CORBA standard for accessing the Interface 
  443. Repository. Thus, the interface Repository Framework provides run-time access 
  444. to all information contained in the IDL description of a class of objects. 
  445. Type information is available as TypeCodes - a CORBA-defined way of encoding 
  446. the complete description of any data type that can be constructed in IDL. 
  447.  
  448.  
  449. ΓòÉΓòÉΓòÉ 2.2.4. Metaclass Framework ΓòÉΓòÉΓòÉ
  450.  
  451. Finally, the Metaclass Framework is a collection of SOM metaclasses that 
  452. provide functionality that may be useful to SOM class designers for modifying 
  453. the default semantics of method invocation and object creation.  These 
  454. metaclasses are described in Chapter 8, "The Metaclass Framework." 
  455.  
  456.  
  457. ΓòÉΓòÉΓòÉ 2.3. What's New in SOMobjects Version 2.1 ΓòÉΓòÉΓòÉ
  458.  
  459. Version 2.1 of the SOMobjects Developer Toolkit provides enhanced capabilities 
  460. and improved performance for both SOM and DSOM. In addition, the Toolkit now 
  461. includes support for DirectToSOM (DTS) C++ compilers. New metaclasses in the 
  462. Metaclass Framework allow class implementors to define classes that 
  463. automatically possess certain convenience facilities. Also, TCP/IP support is 
  464. available for Windows users, and OS/2 users can choose 32-bit TCP/IP. 
  465.  
  466. In particular, SOMobjects Version 2.1 offers the following additions over 
  467. Version 2.0: 
  468.  
  469.  
  470. ΓòÉΓòÉΓòÉ 2.3.1. General enhancements ΓòÉΓòÉΓòÉ
  471.  
  472.      C++ programmers can use DirectToSOM (DTS) C++ compilers (available from 
  473.       independent software vendors) as an alternative to the SOMobjects 
  474.       Toolkit's C++ bindings. (A DTS C++ compiler uses SOM classes to implement 
  475.       C++ objects.) The support provided by SOMobjects for DTS C++ consists of 
  476.       various enhancements to the SOM API (useful to SOM programmers in 
  477.       general), and a new emitter that produces DTS C++ header files 
  478.       corresponding to SOM IDL. DTS C++ programs include these ".hh" header 
  479.       files, which are emitted as described under "Generating binding files" in 
  480.       Chapter 4, "SOM IDL and the SOM Compiler." 
  481.  
  482.      With this release, TCP/IP support is now available for SOMobjects For 
  483.       Windows. Also, for OS/2 users only, SOMobjects now supports the 32-bit 
  484.       TCP/IP version 2.0, which offers greater performance over the 16-bit 
  485.       TCP/IP version 1.2.1. These are described in your SOMobjects 
  486.       Installation/Configuration Guide. 
  487.  
  488.       SOMobjects enhancements 
  489.  
  490.      A new default process whereby SOMobjects initializes and destroys objects 
  491.       more efficiently (using the somDefaultInit and somDestruct methods). See 
  492.       "Initializing and Uninitializing Objects" in Chapter 5, "Implementing 
  493.       Classes in SOM." 
  494.  
  495.      A new kind of method, nonstatic, that is similar to a C++ nonstatic 
  496.       member function. It is normally invoked using offset resolution but can 
  497.       use any form of SOMobjects method resolution. See "The four kinds of SOM 
  498.       methods" in Chapter 5, "Implementing Classes in SOM" and the nonstatic 
  499.       modifier under "Modifier statements" in Chapter 4, "SOM IDL and the SOM 
  500.       Compiler." 
  501.  
  502.      A new kind of data, staticdata, that is similar to C++ static data 
  503.       members. A staticdata variable is not stored in an object; rather, the 
  504.       ClassData structure of the implementing class contains a pointer to the 
  505.       variable. See the staticdatamodifier under "Modifier statements" in 
  506.       Chapter 4, "SOM IDL and the SOM Compiler." 
  507.  
  508.      Two new modifiers, somallocate and somdeallocate, used to indicate that a 
  509.       user-written procedure should be executed to allocate/deallocate memory 
  510.       for class instances when the somAllocate or somDeallocate method is 
  511.       invoked. See these modifiers under "Modifier statements" in Chapter 4, 
  512.       "SOM IDL and the SOM Compiler." 
  513.  
  514.      The ability to "cast" objects. See the methods somCastObj and 
  515.       somResetObj. 
  516.  
  517.      New support for loading/unloading class libraries. (This was introduced 
  518.       in SOMobjects For Windows and is now applicable on OS/2 as well.) See the 
  519.       SOM_ClassLibrary macro in the SOMobjects Base Toolkit Programmers 
  520.       Reference Manual. 
  521.  
  522.       DSOM enhancements 
  523.  
  524.      A new command-line tool, dsom, for managing DSOM servers (starting, 
  525.       restarting, stopping, querying, and so forth). See "The dsom server 
  526.       manager utility" in Chapter 6, "Distributed SOM." In addition, a 
  527.       corresponding programmatic interface is provided by methods of the new 
  528.       SOMDServerMgr class. See that class and its methods in the SOMobjects 
  529.       Base Toolkit Programmers Reference Manual. 
  530.  
  531.      A new command-line tool, somdchk, that performs environment validation. 
  532.       See "Verifying the DSOM environment with somdchk" in Chapter 6, 
  533.       "Distribute SOM." 
  534.  
  535.      New SOM IDL modifiers for memory management of parameters: 
  536.       memory_management= corba, caller_owns_parameters, caller_owns_result, 
  537.       object_owns_parameters, and object_owns_result. The individual modifiers 
  538.       are described under "Modifier statements" in Chapter 4, "SOM IDL and the 
  539.       SOM Compiler." See "Memory management" in Chapter 6, "Distributed SOM," 
  540.       for a complete discussion of the subject. This memory-management support 
  541.       also includes the new method somdReleaseResources and the functions 
  542.       somdExceptionFree and SOMD_NoORBfree, described in the SOMobject Base 
  543.       Toolkit Programmers Reference Manual. 
  544.  
  545.      A graphical user interface to the DSOM `regimpl' utility on OS/2, called 
  546.       pregimpl. See "Registration steps using `pregimpl' or `wregimpl', " in 
  547.       Chapter 6, "Distributed SOM." 
  548.  
  549.      Support for the CORBA constant OBJECT_NIL. In addition, the is_nil method 
  550.       of SOMDObject can now be used for local objects as well as NULL pointers. 
  551.  
  552.      Support for passing self-referential structs and unions (those valid in 
  553.       IDL) in remote method calls. 
  554.  
  555.      Support for local/remote transparency in DSOM's object-destruction 
  556.       methods. See "Destroying remote objects." 
  557.  
  558.      Ability for users to define customized base proxy classes. See 
  559.       "Customizing the default base proxy class." 
  560.  
  561.      Ability for users to specify an upper limit on the number of threads that 
  562.       a server can spawn, via the SOMDNUMTHREADS environment variable. See this 
  563.       variable under "Preparing the environment." 
  564.  
  565.      Improved error handling and performance improvements. 
  566.  
  567.      More sample programs distributed with the SOMobjects Toolkit. 
  568.  
  569.       Metaclass Framework 
  570.  
  571.      SOMMBeforeAfter - a metaclass that enables the programming of 
  572.       "before/after" metaclasses, whose instances execute a particular method 
  573.       before and after each method invocation. See Chapter 8, "The Metaclass 
  574.       Framework," for information about the new Metaclass Framework. Individual 
  575.       metaclasses, along with related classes and methods, are documented in 
  576.       the SOMobjects Base Toolkit Programmers Reference Manual. 
  577.  
  578.      SOMMTraced- a utility metaclass to do tracing. 
  579.  
  580.  
  581. ΓòÉΓòÉΓòÉ 2.3.2. New restrictions and deprecated methods ΓòÉΓòÉΓòÉ
  582.  
  583. While implementing the Metaclass Framework, IBM learned that metaclasses must 
  584. be programmed so that the capabilities they implement will be preserved when 
  585. various metaclasses are combined (using multiple inheritance) into a 
  586. SOM-derived metaclass. To assure this result, the Metaclass Framework 
  587. metaclasses have been programmed using a "Cooperative Metaclass." However, IBM 
  588. is not yet ready to include the Cooperative metaclass among the officially 
  589. supported features of SOMobjects. 
  590.  
  591. To prevent user-defined metaclasses from interfering with the operation of the 
  592. Cooperative Metaclass and consequently with the Metaclass Framework, SOMobjects 
  593. programmers are strongly urged to observe the following restriction when 
  594. programming new metaclasses: 
  595.  
  596.      User-defined metaclasses can introduce new class methods and class 
  597.       variables, but should not override any of the methods introduced by the 
  598.       SOMClass class. 
  599.  
  600.  SOMobjects users whose metaclass programming requirements cannot be met within 
  601.  the above restrictions will be given access to the Cooperative Metaclass and 
  602.  its documentation. Note, however, that metaclasses developed using the 
  603.  Cooperative Metaclass may require reprogramming when an officially supported 
  604.  Cooperative Metaclass is later introduced. 
  605.  
  606.  In addition, use of a number of (public) methods introduced by SOMClass is now 
  607.  deprecated because they are useful only from overridden SOMClass methods. 
  608.  These methods are listed under the heading "Deprecated methods" in the 
  609.  documentation for SOMClass within the SOMobjects Base Toolkit Programmers 
  610.  Reference Manual, until such time as SOMobjects is ready to officially provide 
  611.  a framework within which their use will not interfere with the internal 
  612.  operation of SOMobjects itself. 
  613.  
  614.  
  615. ΓòÉΓòÉΓòÉ 3. Tutorial for Implementing SOM Classes ΓòÉΓòÉΓòÉ
  616.  
  617. This tutorial contains five examples showing how SOM classes can be implemented 
  618. to achieve various functionality. Obviously, for any person who wishes to 
  619. become a class implementor, this tutorial is essential. However, even for those 
  620. programmers who expect only to use SOM classes that were implemented by others, 
  621. the tutorial is also necessary, as it presents several concepts that will help 
  622. clarify the process of using SOM classes. 
  623.  
  624.  
  625. ΓòÉΓòÉΓòÉ 3.1. Basic Concepts of the System Object Model (SOM) ΓòÉΓòÉΓòÉ
  626.  
  627. The System Object Model (SOM), provided by the SOMobjects Developer Toolkit, is 
  628. a set of libraries, utilities, and conventions used to create binary class 
  629. libraries that can be used by application programs written in various 
  630. object-oriented programming languages, such as C++ and Smalltalk, or in 
  631. traditional procedural languages, such as C and Cobol. The following paragraphs 
  632. introduce some of the basic terminology used when creating classes in SOM: 
  633.  
  634.      An object is an OOP entity that has behavior (its methods or operations) 
  635.       and state (its data values).  In SOM, an object is a run-time entity with 
  636.       a specific set of methods and instance variables.  The methods are used 
  637.       by a client programmer to make the object exhibit behavior (that is, to 
  638.       do something), and the instance variables are used by the object to store 
  639.       its state.  (The state of an object can change over time, which allows 
  640.       the object's behavior to change.)  When a method is invoked on an object, 
  641.       the object is said to be the receiver or target of the method call. 
  642.  
  643.      An object's implementation is determined by the procedures that execute 
  644.       its methods, and by the type and layout of its instance variables.  The 
  645.       procedures and instance variables that implement an object are normally 
  646.       encapsulated  (hidden from the caller), so a program can use the object's 
  647.       methods without knowing anything about how those methods are implemented. 
  648.       Instead, a user is given access to the object's methods through its 
  649.       interface (a description of the methods in terms of the data elements 
  650.       required as input and the type of value each method returns). 
  651.  
  652.      An interface through which an object may be manipulated is represented by 
  653.       an object type.  That is, by declaring a type for an object variable, a 
  654.       programmer specifies the interface that is intended to be used to access 
  655.       that object.  SOM IDL (the SOM Interface Definition Language) is used to 
  656.       define object interfaces.  The interface names used in these IDL 
  657.       definitions are also the type names used by programmers when typing SOM 
  658.       object variables. 
  659.  
  660.      In SOM, as in most approaches to object-oriented programming, a class 
  661.       defines the implementation of objects. That is, the implementation of any 
  662.       SOM object (as well as its interface) is defined by some specific SOM 
  663.       class. A class definition begins with an IDL specification of the 
  664.       interface to its objects, and the name of this interface is used as the 
  665.       class name as well. Each object of a given class may also be called an 
  666.       instance of the class, or an instantiation of the class. 
  667.  
  668.      Inheritance, or class derivation, is a technique for developing new 
  669.       classes from existing classes. The original class is called the base 
  670.       class, or the parent class, or sometimes the direct ancestor class. The 
  671.       derived class is called a child class or a subclass.  The primary 
  672.       advantage of inheritance is that a derived class inherits all of its 
  673.       parent's methods and instance variables.  Also through inheritance, a new 
  674.       class can override (or redefine) methods of its parent, in order to 
  675.       provide enhanced functionality as needed.  In addition, a derived class 
  676.       can introduce new methods of its own. If a class results from several 
  677.       generations of successive class derivation, that class "knows" all of its 
  678.       ancestors's methods (whether overridden or not), and an object (or 
  679.       instance) of that class can execute any of those methods. 
  680.  
  681.      SOM classes can also take advantage of multiple inheritance, which means 
  682.       that a new class is jointly derived from two or more parent classes.  In 
  683.       this case, the derived class inherits methods from all of its parents 
  684.       (and all of its ancestors), giving it greatly expanded capabilities.  In 
  685.       the event that different parents have methods of the same name that 
  686.       execute differently, SOM provides ways for avoiding conflicts. 
  687.  
  688.      In the SOM run time, classes are themselves objects.  That is, classes 
  689.       have their own methods and interfaces, and are themselves defined by 
  690.       other classes. For this reason, a class is often called a class object. 
  691.       Likewise, the terms class methods and class variables are used to 
  692.       distinguish between the methods/variables of a class object vs. those of 
  693.       its instances.  (Note that the type of an object is not the same as the 
  694.       type of its class, which as a "class object" has its own type.) 
  695.  
  696.      A class that defines the implementation of class objects is called a 
  697.       metaclass.  Just as an instance of a class is an object, so an instance 
  698.       of a metaclass is a class object.  Moreover, just as an ordinary class 
  699.       defines methods that its objects respond to, so a metaclass defines 
  700.       methods that a class object responds to.  For example, such methods might 
  701.       involve operations that execute when a class (that is, a class object) is 
  702.       creating an instance of itself (an object).  Just as classes are derived 
  703.       from parent classes, so metaclasses can be derived from parent 
  704.       metaclasses, in order to define new functionality for class objects. 
  705.  
  706.      The SOM system contains three primitive classes that are the basis for 
  707.       all subsequent classes: 
  708.  
  709.       SOMObject           the root ancestor class for all SOM classes, 
  710.  
  711.       SOMClass            the root ancestor class for all SOM metaclasses, and 
  712.  
  713.       SOMClassMgr         the class of the SOMClassMgrObject, an object created 
  714.                           automatically during SOM initialization, to maintain 
  715.                           a registry of existing classes and to assist in 
  716.                           dynamic class loading/unloading. 
  717.  
  718.       SOMClass is defined as a subclass (or child) of SOMObject and inherits 
  719.       all generic object methods; this is why instances of a metaclass are 
  720.       class objects  (rather than simply classes) in the SOM run time. 
  721.  
  722.  SOM classes are designed to be language neutral. That is, SOM classes can be 
  723.  implemented in one programming language and used in programs of another 
  724.  language. To achieve language neutrality, the interface for a class of objects 
  725.  must be defined separately from its implementation. That is, defining 
  726.  interface and implementation requires two completely separate steps (plus an 
  727.  intervening compile), as follows: 
  728.  
  729.      An interface is the information that a program must know in order to use 
  730.       an object of a particular class. This interface is described in an 
  731.       interface definition (which is also the class definition), using a formal 
  732.       language whose syntax is independent of the programming language used to 
  733.       implement the class's methods. For SOM classes, this is the SOM Interface 
  734.       Definition Language (SOM IDL). The interface is defined in a file known 
  735.       as the IDL source file (or, using its extension, this is often called the 
  736.       .idl file). 
  737.  
  738.       An interface definition is specified within the interface declaration (or 
  739.       interface statement) of the .idl file, which includes: 
  740.  
  741.       (a)        the interface name (or class name) and the name(s) of the 
  742.                  class's parent(s), and 
  743.  
  744.       (b)        the names of the class's attributes and the signatures of its 
  745.                  new methods. (Recall that the complete set of available 
  746.                  methods also includes all inherited methods.) 
  747.  
  748.       Each method signature includes the method name, and the type and order of 
  749.       its arguments, as well as the type of its return value (if any). 
  750.       Attributes are instance variables for which "set" and "get" methods will 
  751.       automatically be defined, for use by the application program.  (By 
  752.       contrast, instance variables that are not attributes are hidden from the 
  753.       user.) 
  754.  
  755.      Once the IDL source file is complete, the SOM Compiler is used to analyze 
  756.       the .idl file and create the implementation template file, within which 
  757.       the class implementation will be defined. Before issuing the SOM Compiler 
  758.       command, sc, the class implementor can set an environment variable that 
  759.       determines which emitters (output-generating programs) the SOM Compiler 
  760.       will call and, consequently, which programming language and operating 
  761.       system the resulting binding files will relate to. (Alternatively, this 
  762.       emitter information can be placed on the command line for sc.)  In 
  763.       addition to the implementation template file itself, the binding files 
  764.       include two language-specific header files that will be #included in the 
  765.       implementation template file and in application program files. The header 
  766.       files define many useful SOM macros, functions, and procedures that can 
  767.       be invoked from the files that include the header files. 
  768.  
  769.      The implementation of a class is done by the class implementor in the 
  770.       implementation template file (often called just the implementation file 
  771.       or the template file).  As produced by the SOM Compiler, the template 
  772.       file contains stub procedures  for each method of the class.  These are 
  773.       incomplete method procedures that the class implementor uses as a basis 
  774.       for implementing the class by writing the corresponding code in the 
  775.       programming language of choice. 
  776.  
  777.  In summary, the process of implementing a SOM class includes using the SOM IDL 
  778.  syntax to create an IDL source file that specifies the interface to a class of 
  779.  objects - that is, the methods and attributes that a program can use to 
  780.  manipulate an object of that class.  The SOM Compiler is then run to produce 
  781.  an implementation template file and two binding (header) files that are 
  782.  specific to the designated programming language and operating system. Finally, 
  783.  the class implementor writes language-specific code in the template file to 
  784.  implement the method procedures. 
  785.  
  786.  At this point, the next step is to write the application (or client) 
  787.  program(s) that use the objects and methods of the newly implemented class. 
  788.  (Observe, here, that a programmer could write an application program using a 
  789.  class implemented entirely by someone else.)  If not done previously, the SOM 
  790.  compiler is run to generate usage bindings for the new class, as appropriate 
  791.  for the language used by the client program (which may be different from the 
  792.  language in which the class was implemented). After the client program is 
  793.  finished, the programmer compiles and links it using a language-specific 
  794.  compiler, and then executes the program. (Notice again, the client program can 
  795.  invoke methods on objects of the SOM class without knowing how those methods 
  796.  are implemented.) 
  797.  
  798.  
  799. ΓòÉΓòÉΓòÉ 3.1.1. Development of the Tutorial examples ΓòÉΓòÉΓòÉ
  800.  
  801.      Example 1-Implementing a simple class with one method 
  802.       Prints a default message when the "sayHello" method is invoked on an 
  803.       object of the "Hello" class. 
  804.  
  805.      Example 2-Adding an attribute to the Hello class 
  806.       Defines a "msg" attribute for the "sayHello" method to use. The client 
  807.       program "sets" a message; then the "sayHello" method "gets" the message 
  808.       and prints it. (There is no defined message when an object of the "Hello" 
  809.       class is first created.) 
  810.  
  811.      Example 3- Overriding an inherited method 
  812.       Overrides the SOMobjects method somPrintSelf so that invoking this method 
  813.       on an object of the "Hello" class will not only display the class name 
  814.       and the object's location, but will also include the object's message 
  815.       attribute. 
  816.  
  817.      Example 4-Initializing a SOM object. 
  818.       Overrides the default initialization method,  somDefaultInit, to 
  819.       illustrate how an object's instance variables can be initialized when the 
  820.       object is created. 
  821.  
  822.      Example 5-Using multiple inheritance 
  823.       Extends the "Hello" class to provide it with multiple inheritance (from 
  824.       the "Disk;" and "Printer" classes.) The "Hello" interface defines an enum 
  825.       and an "output" attribute that takes its value from the enum (either 
  826.       "screen," "printer," or "disk"). The client program "sets" the form of 
  827.       "output" before invoking the "sayHello" method to send a "msg"(defined as 
  828.       in Example 4). 
  829.  
  830.  
  831. ΓòÉΓòÉΓòÉ 3.2. Basic Steps for Implementing SOM Classes ΓòÉΓòÉΓòÉ
  832.  
  833. Implementing and using SOM classes in C or C++ involves the following steps, 
  834. which are explicitly illustrated in the examples of this tutorial: 
  835.  
  836.    1. Define the interface to objects of the new class (that is, the interface 
  837.       declaration), by creating a .idl file. 
  838.  
  839.    2. Run the SOM Compiler on the .idl file (by issuing the sc command on AIX 
  840.       or OS/2, or by issuing the somc command on Windows) to produce the 
  841.       following binding files: 
  842.  
  843.           Template implementation file 
  844.  
  845.  
  846.            a .c file for C programmers, or 
  847.  
  848.  
  849.            a .C file (on AIX) or a .cpp file (on OS/2 or Windows) for C++ 
  850.            programmers; 
  851.  
  852.           Header file to be included in the implementation file 
  853.  
  854.  
  855.            a .ih file for C programmers, or 
  856.  
  857.  
  858.            a .xih file for C++ programmers; and 
  859.  
  860.           Header file to be included in client programs that use the class 
  861.  
  862.  
  863.            a .h file for C clients, or 
  864.  
  865.  
  866.            a .xh file for C++ clients. 
  867.  
  868.       To specify whether the SOM Compiler should produce C or C++ bindings, set 
  869.       the value of the SMEMIT environment variable or use the "-s" option of 
  870.       the sc or somc command, as described in Section 4.3, "The SOM Compiler." 
  871.       By default, the SOM Compiler produces C bindings. 
  872.  
  873.    3. Customize the implementation, by adding code to the template 
  874.       implementation file. 
  875.  
  876.    4. Create a client program that uses the class. 
  877.  
  878.    5. Compile and link the client code with the class implementation, using a C 
  879.       or C++ compiler. 
  880.  
  881.    6. Execute the client program. 
  882.  
  883.  The following examples illustrate appropriate syntax for defining interface 
  884.  declarations in a .idl file, including designating the methods that the 
  885.  class's instances will perform.  In addition, example template implementation 
  886.  files contain typical code that the SOM Compiler produces. Explanations 
  887.  accompanying each example discuss topics that are significant to the 
  888.  particular example; full explanations of the SOM IDL syntax are contained in 
  889.  Chapter 4, "SOM IDL and the SOM Compiler." Customization of each 
  890.  implementation file (step 3) is illustrated in C and C++. 
  891.  
  892.  Note: 
  893.  
  894.    1. The Tutorial assumes you will work through the examples in order. If you 
  895.       do not do so, the code that the SOM Compiler generates from your revised 
  896.       .idl file may vary slightly from what you see in the Tutorial. 
  897.  
  898.    2. When the SOMobjects Toolkit is installed, a choice is made between 
  899.       "somcorba" and "somstars" for the style of C bindings the SOM Compiler 
  900.       will generate.  The Tutorial examples use the "somcorba" style, where an 
  901.       interface name used as a type indicates a pointer to an object, as 
  902.       required by strict CORBA bindings.  Consequently, as the examples show, a 
  903.       "*" does not explicitly appear for types that are pointers to objects. 
  904.       If your system was installed for "somstars" C bindings, you can set the 
  905.       environment variable SMADDSTAR=1 or use the SOM Compiler option 
  906.       "-maddstar" to request bindings that use explicit pointer stars. For more 
  907.       information, see "Declaring object variables" in Chapter 3, "Using SOM 
  908.       Classes in Client Programs" and "Object types" in Chapter 4, "SOM IDL and 
  909.       the SOM Compiler." 
  910.  
  911.  
  912. ΓòÉΓòÉΓòÉ 3.2.1. Example 1-Implementing a Simple Class with One Method ΓòÉΓòÉΓòÉ
  913.  
  914. Example 1 defines a class "Hello" which introduces one new method, "sayHello". 
  915. When invoked from a client program, the "sayHello" method will print the fixed 
  916. string "Hello, World!"  The example follows the six steps described in the 
  917. preceding topic, "Basic Steps for Implementing SOM Classes." 
  918.  
  919.    1. Define the interface to class "Hello", which inherits methods from the 
  920.       root class SOMObject and introduces one new method, "sayHello". Define 
  921.       these IDL specifications in the file "hello.idl". 
  922.  
  923.       The "interface" statement introduces the name of a new class and any 
  924.       parents (base classes) it may have (here, the root class SOMObject).  The 
  925.       body of the interface declaration introduces the method "sayHello." 
  926.       Observe that method declarations in IDL have syntax similar to C and C++ 
  927.       function prototypes: 
  928.  
  929.             #include <somobj.idl>  //# Get the parent class definition.
  930.  
  931.             interface Hello : SOMObject
  932.             /*  This is a simple class that demonstrates how to define the
  933.              *  interface to a new class of objects in SOM IDL.
  934.              */
  935.             {
  936.                 void sayHello();
  937.                 // This method outputs the string "Hello, World!".
  938.                    /* On Windows, use: string sayHello();
  939.                     * This method returns the string "Hello, World!". */
  940.             };
  941.  
  942.       Note that the method "sayHello" has no (explicit) arguments and returns 
  943.       no value (except on Windows, which returns a string). The characters "//" 
  944.       start a line comment, which finishes at the end of the line.  The 
  945.       characters "/*" start a block comment which finishes with the "*/". Block 
  946.       comments do not nest. The two comment styles can be used interchangeably. 
  947.       Throw-away comments are also permitted in a .idl file; they are ignored 
  948.       by the SOM Compiler.  Throw-away comments start with the characters "//#" 
  949.       and terminate at the end of the line. 
  950.  
  951.       Note:  For simplicity, this IDL fragment does not include a releaseorder 
  952.              modifier; consequently, the SOM Compiler will issue a warning for 
  953.              the method "sayHello". For directions on using the releaseorder 
  954.              modifier to remove this warning, see the topic "Modifier 
  955.              statements" in Chapter 4, "Implementing Classes in SOM." 
  956.  
  957.    2. Run the SOM Compiler to produce binding files and an implementation 
  958.       template (that is, issue the sc command): 
  959.  
  960.             > sc -s"c;h;ih" hello.idl      (for C bindings on AIX or OS/2)
  961.             > sc -s"xc;xh;xih" hello.idl   (for C++ bindings on AIX or OS/2)
  962.  
  963.       When set to generate C binding files, the SOM Compiler generates the 
  964.       following implementation template file, named "hello.c". The template 
  965.       implementation file contains stub procedures for each new method.  These 
  966.       are procedures whose bodies are largely vacuous, to be filled in by the 
  967.       implementor. (Unimportant details have been removed for this tutorial.) 
  968.  
  969.             #include <hello.ih>
  970.             /*
  971.              *  This method outputs the string "Hello, World!".
  972.              */
  973.  
  974.             SOM_Scope  void   SOMLINK  sayHello(Hello somSelf, Environment *ev)
  975.             {
  976.                 /* HelloData *somThis = HelloGetData(somSelf); */
  977.                 HelloMethodDebug("Hello", "sayHello");
  978.             }
  979.  
  980.       The terms SOM_Scope and SOMLINK appear in the prototype for all stub 
  981.       procedures, but they are defined by SOM and are not of interest to the 
  982.       developer. In the method procedure for the "sayHello" method, "somSelf" 
  983.       is a pointer to the target object (here, an instance of the class 
  984.       "Hello") that will respond to the method. A "somSelf" parameter appears 
  985.       in the procedure prototype for every method, since SOM requires every 
  986.       method to act on some object. 
  987.  
  988.       The target object is always the first parameter of a method's procedure, 
  989.       although it should not be included in the method's IDL specification. The 
  990.       second parameter (which also is not included in the method's IDL 
  991.       specification) is the parameter (Environment *ev).  This parameter can be 
  992.       used by the method to return exception information if the method 
  993.       encounters an error.  (Contrast the prototype for the "sayHello" method 
  994.       in steps 1 and 2 above.) 
  995.  
  996.       The remaining lines of the template above are not pertinent at this 
  997.       point.  (For those interested, they are discussed in section 5.4 of 
  998.       Chapter 5, "Implementing SOM Classes.")  The file is now ready for 
  999.       customization with the C code needed to implement method "sayHello". 
  1000.  
  1001.       When set to generate C++ binding files, the SOM Compiler generates an 
  1002.       implementation template file, "hello.C" (on AIX) or "hello.cpp (on OS/2), 
  1003.       similar to the one above.  (Chapter 5 discusses the implementation 
  1004.       template in more detail.) 
  1005.  
  1006.       Recall that, in addition to generating a template implementation file, 
  1007.       the SOM Compiler also generates implementation bindings (in a header file 
  1008.       to be included in the implementation file) and usage bindings (in a 
  1009.       header file to be included in client programs).  These files are named 
  1010.       "hello.ih" and "hello.h" for C bindings, and are "hello.xih" and 
  1011.       "hello.xh" for C++ bindings. Notice that the "hello.c" file shown above 
  1012.       includes the "hello.ih" implementation binding file. 
  1013.  
  1014.    3. Customize the implementation, by adding code to the template 
  1015.       implementation file. 
  1016.  
  1017.       Modify the body of the "sayHello" method procedure in the "hello.c" (or, 
  1018.       for C++,"hello.C" on AIX, "hello.cpp" on OS/2) implementation file so 
  1019.       that the "sayHello" method prints "Hello, World!": 
  1020.  
  1021.             SOM_Scope void   SOMLINK sayHello(Hello somSelf, Environment *ev)
  1022.             {
  1023.                 /* HelloData *somThis = HelloGetData(somSelf); */
  1024.                 HelloMethodDebug("Hello","sayHello");
  1025.  
  1026.                 printf("Hello, World!\n");
  1027.             }
  1028.  
  1029.    4. Create a client program that uses the class. 
  1030.  
  1031.       Write a program "main" that creates an instance (object) of the "Hello" 
  1032.       class and invokes the method "sayHello" on that object. 
  1033.  
  1034.       A C programmer would write the following program in "main.c", using the 
  1035.       bindings defined in the "hello.h" header file: 
  1036.  
  1037.             #include <hello.h>
  1038.  
  1039.             int main(int argc, char *argv[])
  1040.             {
  1041.                 /* Declare a variable to point to an instance of Hello */
  1042.                 Hello obj;
  1043.  
  1044.                 /* Create an instance of the Hello class */
  1045.                 obj = HelloNew();
  1046.  
  1047.                 /* Execute the "sayHello" method */
  1048.                 _sayHello(obj, somGetGlobalEnvironment());
  1049.  
  1050.                 /* Free the instance: */
  1051.                 _somFree(obj);
  1052.                 return (0);
  1053.             }
  1054.  
  1055.       Notice the statement obj = HelloNew();  The "hello.h" header file 
  1056.       automatically contains the SOM-defined macro <className>New(), which is 
  1057.       used to create an instance of the <className> class (here, the "Hello" 
  1058.       class). 
  1059.  
  1060.       Also notice that, in C, a method is invoked on an object by using the 
  1061.       form: 
  1062.  
  1063.             _<methodName>(<objectName>, <environment_argument>, <other_method_arguments>)
  1064.  
  1065.       as used above in the statement _sayHello(obj, somGetGlobalEnvironment()). 
  1066.       As shown in this example, the SOM-provided somGetGlobalEnvironment 
  1067.       function can be used to supply the (Environment *) argument of the 
  1068.       method. 
  1069.  
  1070.       Finally, the code uses the method somFree, which SOM also provides, to 
  1071.       free the object created by HelloNew().  Notice that  somFree does not 
  1072.       require an (Environment *) argument. This is because the method 
  1073.       procedures for some of the classes in the SOMobjects Toolkit (including 
  1074.       SOMObject, SOMClass, and SOMClassMgr) do not have an Environment 
  1075.       parameter, to ensure compatibility with the previous release of SOM.  The 
  1076.       documentation for each SOM-kernel method in the SOMobjects Developer 
  1077.       Toolkit: Programmers Reference Manual indicates whether an Environment 
  1078.       parameter is used. 
  1079.  
  1080.       A C++ programmer would write the following program in "main.C" (on AIX) 
  1081.       or "main.cpp" (on OS/2), using the bindings defined in the "hello.xh" 
  1082.       header file: 
  1083.  
  1084.             #include <hello.xh>
  1085.  
  1086.             int main(int argc, char *argv[])
  1087.             {
  1088.                 /* Declare a variable to point to an instance of Hello */
  1089.                 Hello *obj;
  1090.  
  1091.                 /* Create an instance of the Hello class */
  1092.                 obj = new Hello;
  1093.  
  1094.                 /* Execute the "sayHello" method */
  1095.                 obj->sayHello(somGetGlobalEnvironment());
  1096.  
  1097.                 obj->somFree();
  1098.                 return (0);
  1099.             }
  1100.  
  1101.       Notice that the only argument passed to the "sayHello" method by a C++ 
  1102.       client program is the Environment pointer.  (Contrast this with the 
  1103.       invocation of "sayHello" in the C client program, above. 
  1104.  
  1105.    5. Compile and link the client code with the class implementation. 
  1106.  
  1107.       Note: On AIX or OS/2, the environment variable SOMBASE represents the 
  1108.       directory in which SOM has been installed. 
  1109.  
  1110.       Under AIX, for C programmers: 
  1111.  
  1112.             > xlc -I. -I$SOMBASE/include -o hello main.c hello.c  -L$SOMBASE/lib -l somtk
  1113.  
  1114.       Under AIX, for C++ programmers: 
  1115.  
  1116.             > xlc -I. -I$SOMBASE/include -o hello main.C hello.C  -L$SOMBASE/lib -lsomtk
  1117.  
  1118.       Under OS/2, for C programmers: 
  1119.  
  1120.             > set LIB=%SOMBASE%\lib;%LIB%
  1121.             > icc -I. -I%SOMBASE%\include -Fe hello main.c hello.c  somtk.lib
  1122.  
  1123.       Under OS/2, for C++ programmers: 
  1124.  
  1125.             > set LIB=%SOMBASE%\lib;%LIB%
  1126.             > icc -I. -I\%SOMBASE%\include -Fe hello main.cpp hello.cpp  somtk.lib
  1127.  
  1128.    6. Execute the client program. 
  1129.  
  1130.             > hello
  1131.             Hello, World!
  1132.  
  1133.       Example 2 will extend the "Hello" class to introduce an "attribute." 
  1134.  
  1135.       File Extensions for SOM Files 
  1136.  
  1137.             ΓöîΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÉ
  1138.             ΓöéIDL source file:                   Γöé.idl    Γöéfor all users              Γöé
  1139.             Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  1140.             ΓöéImplementation template file:      Γöé.c      Γöéfor C, all systems         Γöé
  1141.             Γöé                                   Γöé.C      Γöéfor C++, on AIX            Γöé
  1142.             Γöé                                   Γöé.cpp    Γöéfor C++, on OS/2 or WindowsΓöé
  1143.             Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  1144.             ΓöéHeader file for implementation     Γöé.ih     Γöéfor C                      Γöé
  1145.             Γöéfile:                              Γöé.xih    Γöéfor C++                    Γöé
  1146.             Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  1147.             ΓöéHeader file for program file:      Γöé.h      Γöéfor C                      Γöé
  1148.             Γöé                                   Γöé.xh     Γöéfor C++                    Γöé
  1149.             ΓööΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÿ
  1150.  
  1151.  
  1152. ΓòÉΓòÉΓòÉ 3.2.2. Example 2-Adding an Attribute to the Hello class ΓòÉΓòÉΓòÉ
  1153.  
  1154. Example 1 introduced a class "Hello" which has a method "sayHello" that prints 
  1155. the fixed string "Hello, World!"  Example 2 extends the "Hello" class so that 
  1156. clients can customize the output from the method "sayHello". 
  1157.  
  1158.    1. Modify the interface declaration for the class definition in "hello.idl." 
  1159.  
  1160.       Class "Hello" is extended by adding an attribute that we call "msg". 
  1161.       Declaring an attribute is equivalent to defining "get" and "set" methods. 
  1162.       For example, specifying: 
  1163.  
  1164.                attribute string msg;
  1165.  
  1166.       is equivalent to defining the two methods: 
  1167.  
  1168.                string _get_msg();
  1169.                void  _set_msg(in string msg);
  1170.  
  1171.       Thus, for convenience, an attribute can be used (rather than an instance 
  1172.       variable) in order to use the automatically defined "get" and "set" 
  1173.       methods without having to write their method procedures. The new 
  1174.       interface specification for "Hello" that results from adding attribute 
  1175.       "msg" to the "Hello" class is as follows (with some comment lines 
  1176.       omitted): 
  1177.  
  1178.                #include <somobj.idl>
  1179.  
  1180.                interface Hello : SOMObject
  1181.                {
  1182.                  void  sayHello();
  1183.  
  1184.                  attribute string msg;
  1185.                       //# This is equivalent to defining the methods:
  1186.                       //#     string _get_msg();
  1187.                       //#      void  _set_msg(string msg);
  1188.                };
  1189.  
  1190.    2. Re-run the SOM Compiler on the updated idl file, as in example 1.  This 
  1191.       produces new header files and updates the existing implementation file, 
  1192.       if needed, to reflect changes made to the .idl file.  In this example, 
  1193.       the implementation file is not modified by the SOM Compiler. 
  1194.  
  1195.    3. Customize the implementation. 
  1196.  
  1197.       Customize the implementation file by modifying the print statement in the 
  1198.       "sayHello" method procedure. This example prints the contents of the 
  1199.       "msg" attribute (which must be initialized in the client program) by 
  1200.       invoking the "_get_msg" method. Notice that, because the "_get_msg" 
  1201.       method name begins with an underscore, the method is invoked with two 
  1202.       leading underscores (for C only). 
  1203.  
  1204.                SOM_Scope void   SOMLINK sayHello(Hello somSelf, Environment  *ev)
  1205.                {
  1206.                    /* HelloData *somThis = HelloGetData(somSelf); */
  1207.                    HelloMethodDebug("Hello", "sayHello");
  1208.  
  1209.                    printf("%s\n", __get_msg(somSelf, ev));
  1210.  
  1211.                    /* for  C++, use   somSelf->_get_msg(ev);  */
  1212.                }
  1213.  
  1214.       This implementation assumes that "_set_msg" has been invoked to 
  1215.       initialize the "msg" attribute before the "_get_msg" method is invoked by 
  1216.       the "sayHello" method.  This initialization can be done within the client 
  1217.       program. 
  1218.  
  1219.    4. Update the client program. 
  1220.  
  1221.       Modify the client program so that the "_set_msg" method is invoked to 
  1222.       initialize the "msg" attribute before the "sayHello" method is invoked. 
  1223.       Notice that, because the "_set_msg" method name begins with an 
  1224.       underscore, the C client program invokes the method with two  leading 
  1225.       underscores. 
  1226.  
  1227.       For C programmers: 
  1228.  
  1229.                #include <hello.h>
  1230.  
  1231.                int main(int argc, char *argv[])
  1232.                {
  1233.                    Hello obj;
  1234.  
  1235.                    obj = HelloNew();
  1236.                    /* Set the msg text */
  1237.                    __set_msg(obj, somGetGlobalEnvironment(), "Hello World Again");
  1238.  
  1239.                    /* Execute the "sayHello" method */
  1240.                    _sayHello(obj, somGetGlobalEnvironment());
  1241.  
  1242.                    _somFree(obj);
  1243.                    return (0);
  1244.                }
  1245.  
  1246.       For C++ programmers: 
  1247.  
  1248.                #include <hello.xh>
  1249.  
  1250.                int main(int argc, char *argv[])
  1251.                {
  1252.                    Hello *obj;
  1253.                    obj = new Hello;
  1254.  
  1255.                    /* Set the msg text */
  1256.                    obj->_set_msg(somGetGlobalEnvironment(), "Hello World Again");
  1257.  
  1258.                    /* Execute the "sayHello" method */
  1259.                    obj->sayHello(somGetGlobalEnvironment());
  1260.  
  1261.                    obj->somFree();
  1262.                    return (0);
  1263.                }
  1264.  
  1265.    5. Compile and link the client program, as before. 
  1266.  
  1267.    6. Execute the client program: 
  1268.  
  1269.                > hello
  1270.                Hello World Again
  1271.  
  1272.       The next example extends the "Hello" class to override (redefine) one of 
  1273.       the methods it inherits from its parent class, SOMObject. 
  1274.  
  1275.  
  1276. ΓòÉΓòÉΓòÉ 3.2.3. Attributes vs instance variables ΓòÉΓòÉΓòÉ
  1277.  
  1278. As an alternative to defining "numberObjs" as an attribute, it could be defined 
  1279. as an instance variable, with a "get_numberObjs" method also defined for 
  1280. retrieving its value.  Instance variables are declared in an implementation 
  1281. statement, as shown below: 
  1282.  
  1283.    interface Hello
  1284.    {
  1285.    string get_msg() ;
  1286.    void set_msg(in string msg);
  1287.  
  1288.    #ifdef __SOMIDL__
  1289.    implementation
  1290.    {
  1291.        string message;
  1292.    };
  1293.    #endif
  1294.    };
  1295.  
  1296. As demonstrated in this example, one disadvantage to using an instance variable 
  1297. is that the "get_msg" and "set_msg" methods must be defined in the 
  1298. implementation file by the class implementor. For attributes, by contrast, 
  1299. default implementations of the "get" and "set" methods are generated 
  1300. automatically by the SOM Compiler in the .ih and .xih header files. 
  1301.  
  1302. Note: For some attributes (particularly those involving structures, strings, 
  1303. and pointers) the default implementation generated by the SOM Compiler for the 
  1304. "set" method may not be suitable. This happens because the SOM Compiler only 
  1305. performs a "shallow copy," which typically is not useful for distributed 
  1306. objects with these types of attributes.  In such cases, it is possible to write 
  1307. your own implementations, as you do for any other method, by specifying the 
  1308. "noset/noget" modifiers for the attribute. (See the subtopic "Modifier 
  1309. statements" in Chapter 4 "SOM IDL and the SOM Compiler.") 
  1310.  
  1311. Regardless of whether you let the SOM Compiler generate your implementations or 
  1312. not, if access to instance data is required, either from a subclass or a client 
  1313. program, then this access should be facilitated by using an attribute. 
  1314. Otherwise, instance data can be defined in the "implementation" statement as 
  1315. above (using the same syntax as used to declare variables in C or C++), with 
  1316. appropriate methods defined to access it. For more information about 
  1317. "implementation" statements, see the topic "Implementation statements" in 
  1318. Chapter 4. 
  1319.  
  1320. As an example where instance variables would be used (rather than attributes), 
  1321. consider a class "Date" that provides a method for returning the current date. 
  1322. Suppose the date is represented by three instance variables-"mm", "dd", and 
  1323. "yy". Rather than making "mm", "dd", and "yy" attributes (and allowing clients 
  1324. to access them directly), "Date" defines "mm", "dd", and "yy" as instance 
  1325. variables in the "implementation" statement, and defines a method "get_date" 
  1326. that converts "mm", "dd", and "yy" into a string of the form "mm/dd/yy": 
  1327.  
  1328.    interface Date
  1329.    {
  1330.            string get_date() ;
  1331.  
  1332.    #ifdef __SOMIDL__
  1333.    implementation
  1334.    {
  1335.        long mm,dd,yy;
  1336.    };
  1337.    #endif
  1338.    };
  1339.  
  1340. To access instance variables that a class introduces from within the class 
  1341. implementation file, two forms of notation are available: 
  1342.  
  1343. somThis->variableName 
  1344.  
  1345. or 
  1346.  
  1347. _variableName 
  1348.  
  1349. For example, the implementation for "get_date" would 
  1350.  
  1351.       access the "mm" instance variable as somThis->mm or _mm, 
  1352.       access "dd"  as somThis->dd or _dd, and 
  1353.       access "yy" as somThis->yy or _yy. 
  1354.  
  1355.  In C++ programs, the _variableName  form is available only if the programmer 
  1356.  first defines the macro VARIABLE_MACROS (that is, enter #define 
  1357.  VARIABLE_MACROS) in the implementation file prior to including the .xih file 
  1358.  for the class. 
  1359.  
  1360.  
  1361. ΓòÉΓòÉΓòÉ 3.2.4. Example 3-Overriding an Inherited Method ΓòÉΓòÉΓòÉ
  1362.  
  1363. An important aspect of OOP programming is the ability of a subclass to replace 
  1364. an inherited method implementation with a new implementation especially 
  1365. appropriate to its instances.  This is called overriding llo"q.  a method. 
  1366. Sometimes, a class may introduce methods that every descendant class is 
  1367. expected to override.  For example, SOMobject  ves  introduces the somPrintSelf 
  1368. method, and a good SOM programmer will generally override this method when 
  1369. implementing a new class. 
  1370.  
  1371. The purpose of somPrintSelf is to print a brief description of an object.  The 
  1372. method can be useful when debugging an application that deals with a number of 
  1373. objects of the same class -assuming the class designer has overridden 
  1374. somPrintSelf with a message that is useful in distinguishing different objects 
  1375. of the class.  For example, the implementation of somPrintSelf provided by 
  1376. SOMobjects simply prints the class of the object and its address in memory. 
  1377. SOMclass overrides this method so that, when somPrintSelf is invoked on a class 
  1378. object, the name of the class will print. 
  1379.  
  1380. This example illustrates how somPrintSelf might be overridden for the "Hello" 
  1381. class.  An important identifying characteristic of "Hello" objects is the 
  1382. message they hold; thus, the following steps illustrate how somPrintSelf could 
  1383. be overridden in "Hello" to provide this information. 
  1384.  
  1385.    1. Modify the interface declaration in "hello.idl." 
  1386.  
  1387.       To override the somPrintSelf method in "Hello", additionalinformation 
  1388.       must be provided in "hello.idl" in the form of an implementation 
  1389.       statement, which gives extra information about the class, its methods and 
  1390.       attributes, and any instance variables.  (The previous examples omitted 
  1391.       the optional "implementation" statement, because it was not needed.) 
  1392.  
  1393.       In the current example, the "implementation" statement introduces the 
  1394.       modifiers  for the "Hello" class, as follows. 
  1395.  
  1396.                #include <somobj.idl>
  1397.  
  1398.                interface Hello : SOMObject
  1399.                {
  1400.                  void sayHello();
  1401.  
  1402.                  attribute string msg;
  1403.  
  1404.                  #ifdef __SOMIDL__
  1405.                  implementation
  1406.                  {
  1407.                          //# Method Modifiers:
  1408.                          somPrintSelf: override;
  1409.                          // Override the inherited implementation of somPrintSelf.
  1410.                  };
  1411.                  #endif
  1412.  
  1413.                  };
  1414.  
  1415.       Here, "somPrintSelf:" introduces a list of modifiers  for the (inherited) 
  1416.       somPrintSelf method in the class "Hello".  Modifiers are like C/C ++ 
  1417.       #pragma commands and give specific implementation details to the 
  1418.       compiler. This example uses only one modifier, "override." Because of the 
  1419.       "override" modifier, when somPrintSelf is invoked on an instance of class 
  1420.       "Hello", Hello's implementation of somPrintSelf (in the implementation 
  1421.       file) will be called, instead of the implementation inherited from the 
  1422.       parent class, SOMObject. 
  1423.  
  1424.       The "#ifdef__SOMIDL__" and "#endif" are standard C and C++ preprocessor 
  1425.       commands that cause the "implementation" statement to be read only when 
  1426.       using the SOM IDL compiler (and not some other IDL compiler). 
  1427.  
  1428.    2. Re-run the SOM Compiler on the updated .idl file, as before.  The SOM 
  1429.       Compiler extends the existing implementation file from Example 2 to 
  1430.       include new stub procedures as needed (in this case, for somPrintSelf). 
  1431.       Below is a shortened version of the C language implementation file as 
  1432.       updated by the SOM Compiler; C++ implementation files are similarly 
  1433.       revised.  Notice that the code previously added to the "sayHello" method 
  1434.       is not disturbed when the SOM Compiler updates the implementation file. 
  1435.  
  1436.                #include <hello.ih>
  1437.  
  1438.                SOM_Scope void   SOMLINK sayHello(Hello somSelf, Environment  *ev)
  1439.                {
  1440.                    /* HelloData *somThis = HelloGetData(somSelf); */
  1441.                    HelloMethodDebug("Hello","sayHello");
  1442.  
  1443.                    printf("%s\n", __get_msg(somSelf, ev));
  1444.                }
  1445.  
  1446.                SOM_Scope void   SOMLINK  somPrintSelf(Hello somSelf)
  1447.                {
  1448.                    HelloData *somThis = HelloGetData(somSelf);
  1449.                    HelloMethodDebug("hello","somPrintSelf");
  1450.  
  1451.                      Hello_parent_SOMObject_somPrintSelf(somSelf);
  1452.                }
  1453.  
  1454.       Note that the SOM Compiler added code allowing the "Hello" class to 
  1455.       redefine somPrintSelf.  The SOM Compiler provides a default 
  1456.       implementation for overriding the somPrintSelf method.  This default 
  1457.       implementation simply calls the "parent method" [the procedure that the 
  1458.       parent class of "Hello" (SOMObject) uses to implement the somPrintSelf 
  1459.       method]. This parent method call is accomplished by the macro 
  1460.       Hello_parent_SOMObject_somPrintSelf defined in "hello.ih." 
  1461.  
  1462.       Notice that the stub procedure for overriding the somPrintSelf method 
  1463.       does not include an Environment parameter. This is because somPrintSelf 
  1464.       is introduced by SOMObject, which does not include the Environment 
  1465.       parameter in any of its methods (to ensure backward compatibility). The 
  1466.       signature for a method cannot change after it has been introduced. 
  1467.  
  1468.    3. Customize the implementation. 
  1469.  
  1470.       Within the new somPrintSelf method procedure, display a brief description 
  1471.       of the object, appropriate to "Hello" objects.  Note that the parent 
  1472.       method call is not needed, so it has been deleted.  Also, direct access 
  1473.       to instance data introduced by the "Hello" class is not required, so the 
  1474.       assignment to "somThis" has been commented out (see the first line of the 
  1475.       procedure). 
  1476.  
  1477.                SOM_Scope void   SOMLINK somPrintSelf(Hello somSelf)
  1478.                {
  1479.                    HelloData *somThis = HelloGetData(somSelf);
  1480.                    HelloMethodDebug("Hello","somPrintSelf");
  1481.  
  1482.                  somPrintf("--a %s object at location %x with msg:s\n",
  1483.                                _somGetClassName(somSelf),
  1484.                                somSelf,
  1485.                                __get_msg(somSelf,0));
  1486.                }
  1487.  
  1488.    4. Update the client program to illustrate the change (also notice the new 
  1489.       message text): 
  1490.  
  1491.       For C programmers: 
  1492.  
  1493.                #include <hello.h>
  1494.  
  1495.                int main(int argc, char *argv[])
  1496.                {
  1497.                    Hello obj;
  1498.                    Environment *ev = somGetGlobalEnvironment();
  1499.  
  1500.                    obj = HelloNew();
  1501.  
  1502.                    /* Set the msg text */
  1503.                    __set_msg(obj, ev, "Hi There");
  1504.  
  1505.                    /* Execute the "somPrintSelf" method */
  1506.                    _somPrintSelf(obj);
  1507.  
  1508.                         _somFree(obj);
  1509.                         return (0);
  1510.                }
  1511.  
  1512.       For C++ programmers: 
  1513.  
  1514.                #include <hello.xh>
  1515.  
  1516.                int main(int argc, char *argv[])
  1517.                {
  1518.                    Hello *obj;
  1519.                    Environment *ev = somGetGlobalEnvironment();
  1520.  
  1521.                    obj = new Hello;
  1522.  
  1523.                    /* Set the msg text */
  1524.                    __setmsg(obj, ev, "Hi There");
  1525.  
  1526.                   /* Execute the "somPrintSelf" method */
  1527.                      obj->somPrintSelf();
  1528.  
  1529.                    obj->somFree();
  1530.                    return (0);
  1531.                }
  1532.  
  1533.    5. Compile and link the client program, as before. 
  1534.  
  1535.    6. Execute the client program, which now outputs the message: 
  1536.  
  1537.                > hello
  1538.                 -- a Hello object at location 20062838 with msg: Hi There
  1539.  
  1540.  
  1541. ΓòÉΓòÉΓòÉ 3.2.5. Example 4 - Initializing a SOM Object ΓòÉΓòÉΓòÉ
  1542.  
  1543. The previous example showed how to override the method somPrintSelf, introduced 
  1544. by SOMObject. As mentioned in that example, somPrintSelf should generally be 
  1545. overridden when implementing a new class. Another method introduced by 
  1546. SOMObject  that should generally be overridden is somDefaultInit. The purpose 
  1547. of somDefaultInit is to provide a "default" initializer  for the instance 
  1548. variables introduced by a class. 
  1549.  
  1550. This example shows how to override somDefaultInit to give each "Hello" object's 
  1551. message an initial value when the object is first created. To learn more about 
  1552. initializers than shown in this example (including how to introduce new 
  1553. initializers that take arbitrary arguments, and how to explicitly invoke 
  1554. initializers) read Section 5.5, "Initializing and Uninitializing Objects," in 
  1555. Chapter 5, "Implementing Classes in SOM." 
  1556.  
  1557. The overall process of overriding somDefaultInit is similar to that of the 
  1558. previous example. First, the IDL for "Hello" is modified. In addition to an 
  1559. override  modifier, an init modifier is used to indicate that a stub procedure 
  1560. for an initialization method is desired (the stub procedures for initializers 
  1561. are different from those of normal methods). 
  1562.  
  1563.    1. Modify the interface declaration in "hello.idl." 
  1564.  
  1565.  
  1566.             #include <somobj.idl>
  1567.  
  1568.             interface Hello : SOMObject
  1569.             {
  1570.               void sayHello();
  1571.  
  1572.               attribute string msg;
  1573.  
  1574.             #ifdef __SOMIDL__
  1575.             implementation
  1576.             {
  1577.                 //# Method Modifiers:
  1578.                 somPrintSelf: override;
  1579.                 somDefaultInit: override, init;
  1580.             };
  1581.             #endif
  1582.  
  1583.             };
  1584.  
  1585.    2. Re-run the SOM Compiler on the updated hello.idl file, as before. SOM 
  1586.       Compiler extends the existing implementation file. Below is the 
  1587.       initializer stub procedure that the SOM Compiler adds to the C language 
  1588.       implementation file; C++ implementation files would be similarly revised: 
  1589.  
  1590.  
  1591.             SOM_Scope void SOMLINK
  1592.                       somDefaultInit(Hello somSelf, somInitCtrl *ctrl)
  1593.             {
  1594.               HelloData *somThis; /* set by BeginInitializer */
  1595.               somInitCtrl globalCtrl;
  1596.               somBooleanVector myMask;
  1597.               HelloMethodDebug("Hello", "somDefaultInit");
  1598.               Hello_BeginInitializer_somDefaultInit;
  1599.  
  1600.               Hello_Init_SOMObject_somDefaultInit(somSelf, ctrl);
  1601.               /*
  1602.                * local Hello initialization code added by programmer
  1603.                */
  1604.             }
  1605.  
  1606.    3. Customize the implementation. 
  1607.  
  1608.       Here, the "msg" instance variable is set in the implementation template 
  1609.       (rather than in the client program, as before). Thus, the "msg" is 
  1610.       defined as part of the "Hello" object's initialization. 
  1611.  
  1612.             SOM_Scope void SOMLINK
  1613.                            somDefaultInit(Hello somSelf, somInitCtrl *ctrl)
  1614.             {
  1615.               HelloData *somThis; /* set by BeginInitializer */
  1616.               somInitCtrl globalCtrl;
  1617.               somBooleanVector myMask;
  1618.               HelloMethodDebug("Hello", "somDefaultInit");
  1619.               Hello_BeginInitializer_somDefaultInit;
  1620.  
  1621.               Hello_Init_SOMObject_somDefaultInit(somSelf, ctrl);
  1622.               /*
  1623.                * local Hello initialization code added by programmer
  1624.                */
  1625.               __set_msg(somSelf, "Initial Message");
  1626.             }
  1627.  
  1628.    4. Update the client program to illustrate default initialization. 
  1629.  
  1630.  
  1631.             #include <hello.h>
  1632.             main()
  1633.             {
  1634.                 Hello h = HelloNew();
  1635.  
  1636.                 /* Execute the "somPrintSelf" method */
  1637.                 _somPrintSelf(h);
  1638.             }
  1639.  
  1640.    5. Compile and link the client program, as before. 
  1641.  
  1642.    6. Execute the client program. 
  1643.  
  1644.   > hello
  1645.   -- a Hello object at 200633A8 with msg: Initial Message
  1646.  
  1647.  
  1648. ΓòÉΓòÉΓòÉ 3.2.6. Example 5-Using Multiple Inheritance ΓòÉΓòÉΓòÉ
  1649.  
  1650. The "Hello" class is useful for writing messages to the screen.  So that 
  1651. clients can also write messages to printers and disk files, this example 
  1652. references two additional classes: "Printer" and "Disk."  The "Printer" class 
  1653. will manage messages to a printer, and the "Disk" class will manage messages 
  1654. sent to files. These classes can be defined as follows: 
  1655.  
  1656.    #include <somobj.idl>
  1657.  
  1658.    interface Printer : SOMObject
  1659.    {
  1660.        void stringToPrinter(in string s) ;
  1661.         // This method writes a string to a printer.
  1662.    };
  1663.  
  1664.    #include <somobj.idl>
  1665.  
  1666.    interface Disk : SOMObject
  1667.    {
  1668.         void stringToDisk(in string s) ;
  1669.         // This method writes a string to disk.
  1670.    };
  1671.  
  1672. This example assumes the "Printer" and "Disk" classes are defined separately 
  1673. (in "print.idl" and "disk.idl," for example), are implemented in separate 
  1674. files, and are linked with the other example code.  Given the implementations 
  1675. of the "Printer" and "Disk" interfaces, the "Hello" class can use them by 
  1676. inheriting from them, as illustrated next. 
  1677.  
  1678.    1. Modify the interface declaration in "hello.idl". 
  1679.  
  1680.                #include <disk.idl>
  1681.                #include <printer.idl>
  1682.  
  1683.                interface Hello : Disk, Printer
  1684.                {
  1685.                    void sayHello();
  1686.  
  1687.                    attribute string msg;
  1688.  
  1689.                    enum outputTypes {screen, printer, disk};
  1690.                    // Declare an enumeration for the different forms of output
  1691.  
  1692.                    attribute outputTypes output;
  1693.                    // The current form of output
  1694.  
  1695.                #ifdef __SOMIDL__
  1696.  
  1697.                  implementation {
  1698.                  somDefaultInit: override, init;
  1699.                  };
  1700.                #endif //#  __SOMIDL__
  1701.                };
  1702.  
  1703.       Notice that SOMObject is not listed as a parent of "Hello" above, because 
  1704.       SOMObject is a parent of "Disk" (and of "Printer"). 
  1705.  
  1706.       The IDL specification above declares an enumeration "outputTypes" for the 
  1707.       different forms of output, and an attribute "output" whose value will 
  1708.       depend on where the client wants the output of the "sayHello" method to 
  1709.       go. 
  1710.  
  1711.       Note: SOM IDL allows the use of structures, unions (though with a syntax 
  1712.       different from C or C++), enumerations, constants, and typedefs, both 
  1713.       inside and outside the body of an interface statement. Declarations that 
  1714.       appear inside an interface body will be emitted in the header file (that 
  1715.       is, in "hello.h" or "hello.xh").  Declarations that appear outside of an 
  1716.       interface body do not appear in the header file (unless required by a 
  1717.       special #pragma directive; see the SOM Compiler options in Chapter 4). 
  1718.  
  1719.       SOM IDL also supports all of the C and C++ preprocessor directives, 
  1720.       including conditional compilation, macro processing, and file inclusion. 
  1721.  
  1722.    2. Re-run the SOM Compiler on the updated idl file.. 
  1723.  
  1724.       Unfortunately, when this is done, the implementation for somDefaultInit 
  1725.       is not correctly updated to reflect the addition of two new parents to 
  1726.       "Hello."  This is because the implementation file emitter never changes 
  1727.       the bodies of existing method procedures.  As a result, method procedures 
  1728.       for initializer methods are not given new parent calls when the parents 
  1729.       of a class are changed.  One way to deal with this (when the parents of a 
  1730.       class are changed) is to temporarily rename the method procedure for 
  1731.       initializer methods, and then run the implementation emitter. Once this 
  1732.       is done, the code in the renamed methods can be merged into the new 
  1733.       templates, which will include all the appropriate parent method calls. 
  1734.       When this is done here, the new implementation for somDefaultInit would 
  1735.       appear as: 
  1736.  
  1737.                   SOM_Scope void SOMLINK
  1738.                                  somDefaultInit(Hello somSelf, somInitCtrl *ctrl)
  1739.              {
  1740.                HelloData *somThis; /* set by BeginInitializer */
  1741.                somInitCtrl globalCtrl;
  1742.                somBooleanVector myMask;
  1743.                HelloMethodDebug("Hello", "somDefaultInit");
  1744.                Hello_BeginInitializer_somDefaultINit;
  1745.  
  1746.                 Hello_Init_Disk_somDefaultInit(somSelf, ctrl);
  1747.                 Hello_Init_Printer_somDefaultInit(somSelf, ctrl);
  1748.                /*
  1749.                 * local Hello initialization code added by programmer
  1750.                /*
  1751.                __set_msg(somSelf, "Initial Message");
  1752.             }
  1753.  
  1754.    3. Continue to customize the implementation file, hello.c, as follows. 
  1755.       Notice that the "sayHello" method (last discussed in Example 2) is now 
  1756.       modified to allow alternate ways of outputing a "msg". 
  1757.  
  1758.             SOM_Scope void  SOMLINK sayHello(Hello somSelf, Environment *ev)
  1759.             {
  1760.                 /* HelloData *somThis = HelloGetData(somSelf) ; */
  1761.                 HelloMethodDebug("Hello","sayHello") ;
  1762.                 switch (__get_output(somSelf, ev) ) {
  1763.                         /*  for C++, use:  somSelf->_get_output(ev) */
  1764.                 case Hello_screen:
  1765.                     printf("%s\n", __get_msg(somSelf, ev) );
  1766.                         /*  for C++, use:  somSelf->_get_msg(ev) */
  1767.                     break;
  1768.                 case Hello_printer:
  1769.                     _stringToPrinter(somSelf, ev, __get_msg(somSelf, ev) );
  1770.                         /* for C++, use:
  1771.                          * somSelf->stringToPrinter(ev, somSelf->_get_msg(ev) );
  1772.                          */
  1773.                     break;
  1774.                 case Hello_disk:
  1775.                     _stringToDisk(somSelf, ev, __get_msg(somSelf, ev) );
  1776.                         /*  for C++, use:
  1777.                          *   somSelf->stringToDisk(ev, somSelf->_get_msg(ev) );
  1778.                          */
  1779.                break;
  1780.                 }
  1781.             }
  1782.  
  1783.       The "switch" statement invokes the appropriate method depending on the 
  1784.       value of the "output" attribute.  Notice how the "case" statements 
  1785.       utilize the enumeration values of "outputTypes" declared in "hello.idl" 
  1786.       by prefacing the enumeration names with the class name (Hello_screen, 
  1787.       Hello_printer, and Hello_disk). 
  1788.  
  1789.    4. Update the client program, as illustrated next: 
  1790.  
  1791.                #include <hello.h>
  1792.                        /* for C++, use "hello.xh" and <stdio.h> */
  1793.  
  1794.                int main(int argc, char *argv[])
  1795.                {
  1796.                    Hello a = HelloNew();
  1797.                    Environment *ev = somGetGlobalEnvironment();
  1798.  
  1799.                    /*Invoke "sayHello" on an object and use each output */
  1800.                    _sayHello(a, ev) ; /* for c++, use:a->sayHello(ev);*/
  1801.                     __set_output(a, ev, Hello_printer);
  1802.                                              /* C++: a->_set_output(ev,Hello_printer);*/
  1803.                    _sayHello(a, ev);
  1804.                    __set_output(a, ev, Hello_disk);
  1805.                               /* C++:a->_set_output(ev,Hello-disk);       */
  1806.                    _sayHello(a, ev) ;
  1807.  
  1808.                    _somFree(a0 ;  /* for C++, use: a->somFree(); */
  1809.                     return (0);
  1810.                }
  1811.  
  1812.    5. Compile and link the client program as before, except also include the 
  1813.       implementation files for the "Printer" and "Disk" classes in the 
  1814.       compilation. 
  1815.  
  1816.    6. Execute the client program.  Observe that the message that prints is the 
  1817.       "msg" defined in Example 4 as part of the somDefaultInit initialization 
  1818.       of the "Hello" object. 
  1819.  
  1820.        Initial Message
  1821.  
  1822.        Initial Message               - goes to a Printer
  1823.  
  1824.        Initial Message               - goes to Disk
  1825.  
  1826.  This tutorial has described features of SOM IDL that will be useful to C and 
  1827.  C++ programmers.  SOM IDL also provides features such as full type checking, 
  1828.  constructs for declaring private methods, and constructs for defining methods 
  1829.  that receive and return pointers to structures.  Chapter 4, "SOM IDL and the 
  1830.  SOM Compiler" gives complete description of the SOM IDL syntax and also 
  1831.  describes how to use the SOM Compiler.  In addition, Chapter 5, "Implementing 
  1832.  Classes in SOM," provides helpful information for completing the 
  1833.  implementation template, for using initializer (somDefaultInit or user-defined 
  1834.  initialization methods), for defining SOM class libraries, and for customizing 
  1835.  various aspects of SOMobjects execution. 
  1836.  
  1837.  
  1838. ΓòÉΓòÉΓòÉ 4. Using SOM Classes in Client Programs ΓòÉΓòÉΓòÉ
  1839.  
  1840. This chapter discusses how to use SOM classes that have already been fully 
  1841. implemented. That is, these topics describe the steps that a programmer uses to 
  1842. instantiate an object and invoke some method(s) on it from within an 
  1843. application program. 
  1844.  
  1845. Who should read this chapter? 
  1846.  
  1847.      Programmers who wish to use SOM classes that were originally developed by 
  1848.       someone else will need to know the information in this chapter. These 
  1849.       programmers often may not need the information from any subsequent 
  1850.       chapters. 
  1851.  
  1852.      By contrast, class implementers who are creating their own SOM classes 
  1853.       should continue with Chapter 4, "SOM IDL and the SOM Compiler," and 
  1854.       Chapter 5, "Implementing Classes in SOM "for complete information on the 
  1855.       SOM Interface Definition Language (SOM IDL) syntax and other details of 
  1856.       class implementation. 
  1857.  
  1858.  Programs that use a class are referred to as client programs. A client program 
  1859.  can be written in  C, in C++, or in another language. As noted, this chapter 
  1860.  describes how client programs can use SOM classes (classes defined using SOM, 
  1861.  as described in Chapter 2, "Tutorial for Implementing SOM Classes" and in 
  1862.  Chapter 4, "SOM IDL and the SOM Compiler"and Chapter 5 "Implementing Classes 
  1863.  in SOM"). Using a SOM class involves creating instances of a class, invoking 
  1864.  methods on objects, and so forth. All of the methods, functions, and macros 
  1865.  described here can also be used by class implementers within the 
  1866.  implementation file for a class. 
  1867.  
  1868.  Note: "Using a SOM class," as described in this chapter, does not include 
  1869.  subclassing the class in a client program. In particular, the C++ compatible 
  1870.  SOM classes made available in the .xh binding file can not be subclassed in 
  1871.  C++ to create new C++ or SOM classes. 
  1872.  
  1873.  Some of the macros and functions described here are supplied as part of SOM's 
  1874.  C and C++ usage bindings. These bindings are functions and macros defined in 
  1875.  header files to be included in client programs. The usage bindings make it 
  1876.  more convenient for C and C++ programmers to create and use instances of SOM 
  1877.  classes. SOM classes can be also used without the C or C++ bindings, however. 
  1878.  For example, users of other programming languages can use SOM classes, and C 
  1879.  and C++ programmers can use a SOM class without using its language bindings. 
  1880.  The language bindings simply offer a more convenient programmer's interface to 
  1881.  SOM. Vendors of other languages may also offer SOM bindings; check with your 
  1882.  language vendor for possible SOM support. 
  1883.  
  1884.  To use the C or C++ bindings for a class, a client program must include a 
  1885.  header file for the class (using the #include preprocessor directive). For a C 
  1886.  language client program, the file <classFileStem>.h must be included. For a 
  1887.  C++ language client program, the file <classFileStem>.xh must be included. The 
  1888.  SOM Compiler generates these header files from an IDL interface definition. 
  1889.  The header files contain definitions of the macros and functions that make up 
  1890.  the C or C++ bindings for the class. Whether the header files include bindings 
  1891.  for the class's private methods and attributes (in addition to the public 
  1892.  methods and attributes) depends on the IDL interface definition available to 
  1893.  the user, and on how the SOM Compiler was invoked when generating bindings. 
  1894.  
  1895.  Usage binding headers automatically include any other bindings upon which they 
  1896.  may rely. Client programs not using the C or C++ bindings for any particular 
  1897.  class of SOM object (for example, a client program that does not know at 
  1898.  compile time what classes it will be using) should simply include the 
  1899.  SOM-supplied bindings for  SOMObject, provided in the header file "somobj.h" 
  1900.  (for C programs) or"somobj.xh" (for C++ programs). 
  1901.  
  1902.  For each task that a user of a SOM class might want to perform, this chapter 
  1903.  shows how the task would be accomplished by: 
  1904.  
  1905.      a C programmer using the C bindings, 
  1906.      a C++ programmer using the C++ bindings, or 
  1907.      a programmer not using SOM's C or C++ language bindings. 
  1908.  
  1909.  If neither of the first two approaches is applicable, the third approach can 
  1910.  always be used. 
  1911.  
  1912.  
  1913. ΓòÉΓòÉΓòÉ 4.1. An Example Client Program ΓòÉΓòÉΓòÉ
  1914.  
  1915. Following is a C program that uses the class "Hello" (as defined in the 
  1916. Tutorial in Chapter 2). The "Hello" class provides one attribute, "msg", of 
  1917. type string, and one method, "sayHello". The "sayHello" method simply displays 
  1918. the value of the "msg" attribute of the object on which the method is invoked. 
  1919.  
  1920.    #include <hello.h>  /* include the header file for Hello */
  1921.  
  1922.    int main(int argc, char *argv[])
  1923.    {
  1924.        /* declare a variable (obj) that is a
  1925.         * pointer to an instance of the Hello class: */
  1926.        Hello obj;
  1927.  
  1928.        /* create an instance of the Hello class
  1929.         * and store a pointer to it in obj: */
  1930.        obj = HelloNew();
  1931.  
  1932.        /* invoke method _set_msg on obj with the argument
  1933.         * "Hello World Again". This method sets the value of
  1934.         * obj's 'msg' attribute to the specified string.
  1935.         */
  1936.         __set_msg(obj, somGetGlobalEnvironment(), "Hello World Again");
  1937.  
  1938.         /* invoke method sayHello on obj. This method prints
  1939.          * the value of obj's 'msg' attribute.  */
  1940.         _sayHello(obj, somGetGlobalEnvironment());
  1941.  
  1942.         _somFree(obj);
  1943.         return(0);
  1944.    }
  1945.  
  1946. The C++ version of the foregoing client program is shown below: 
  1947.  
  1948.    #include <hello.xh>  /* include the header file for Hello */
  1949.  
  1950.    int main(int argc, char *argv[])
  1951.    {
  1952.        /* declare a variable (obj) that is a
  1953.         * pointer to an instance of the Hello class: */
  1954.        Hello *obj;
  1955.  
  1956.        /* create an instance of the Hello class
  1957.         * and store a pointer to it in obj: */
  1958.        obj = new Hello;
  1959.  
  1960.       /* invoke method _set_msg on obj with the argument
  1961.        * "Hello World Again". This method sets the value of
  1962.        * obj's 'msg' attribute to the specified string.  */
  1963.       obj->_set_msg(somGetGlobalEnvironment(), "Hello World Again");
  1964.  
  1965.       /* invoke method sayHello on obj. This method prints
  1966.        * the value of obj's 'msg' attribute.  */
  1967.       obj->sayHello(somGetGlobalEnvironment());
  1968.  
  1969.       obj->somFree();
  1970.       return(0);
  1971.    }
  1972.  
  1973. These client programs both produce the output: 
  1974.  
  1975. Hello World Again
  1976.  
  1977.  
  1978. ΓòÉΓòÉΓòÉ 4.2. Using SOM Classes: the Basics ΓòÉΓòÉΓòÉ
  1979.  
  1980. This section covers the following subjects: 
  1981.  
  1982.      Declaring object variables 
  1983.      Creating instances of a class 
  1984.      Invoking methods on objects 
  1985.      Using class objects 
  1986.      Compiling and linking 
  1987.  
  1988.  
  1989. ΓòÉΓòÉΓòÉ 4.2.1. Declaring object variables ΓòÉΓòÉΓòÉ
  1990.  
  1991. When declaring an object variable, an object interface name defined in IDL is 
  1992. used as the type of the variable. The exact syntax is slightly different for C 
  1993. vs. C++ programmers. Specifically, 
  1994.  
  1995.  <interfaceName>  obj ;   in C programs or 
  1996.  <interfaceName> *obj ;   in C++ programs 
  1997.  
  1998.  declares "obj" to be a pointer to an object that has type <interfaceName>. In 
  1999.  SOM, objects of this type are instances of the SOM class named 
  2000.  <interfaceName>, or of any SOM class derived from this class. Thus, for 
  2001.  example, 
  2002.  
  2003.  Animal obj;              in C programs or 
  2004.  Animal *obj;             in C++ programs 
  2005.  
  2006.  declares "obj" as pointer to an object of type "Animal" that can be used to 
  2007.  reference an instance of the SOM class "Animal" or any SOM class derived from 
  2008.  "Animal". Note that the type of an object need not be the same as its class; 
  2009.  an object of type "Animal" might not be an instance of the "Animal" class 
  2010.  (rather, it might be an instance of some subclass of "Animal" - the "Cat" 
  2011.  class, perhaps). 
  2012.  
  2013.  All SOM objects are of type SOMObject, even though they may not be instances 
  2014.  of the SOMObject class. Thus, if it is not known at compile time what type of 
  2015.  object the variable will point to, the following declaration can be used: 
  2016.  
  2017.  SOMObject obj;           in C programs or 
  2018.  SOMObject *obj;          in C++ programs. 
  2019.  
  2020.  Because the sizes of SOM objects are not known at compile time, instances of 
  2021.  SOM classes must always be dynamically allocated. Thus, a variable declaration 
  2022.  must always define a pointer to an object. 
  2023.  
  2024.  Note: In the C usage bindings, as within an IDL specification, an interface 
  2025.  name used as a type implicitly indicates a pointer to an object that has that 
  2026.  interface (this is required by the CORBA specification). The C usage bindings 
  2027.  for SOM classes therefore hide the pointer with a C typedef for 
  2028.  <interfaceName>. But this is not appropriate in the C++  usage bindings, which 
  2029.  define a C++ class for <interfaceName>. Thus, it is not correct in C++ to use 
  2030.  a declaration of the form: 
  2031.  
  2032.  <interfaceName>  obj ;   not valid in C++ programs 
  2033.  
  2034.  Note: If a C programmer also prefers to use explicit pointers to 
  2035.  <interfaceName> types, then the SOM Compiler option -maddstar can be used when 
  2036.  the C binding files are generated, and the explicit " *" will then be required 
  2037.  in declarations of object variables. (This option is required for 
  2038.  compatibility with existing SOM OIDL code. For information on using the 
  2039.  -maddstar option, see "Running the SOM Compiler" in Chapter 4, "SOM IDL and 
  2040.  the SOM Compiler.") 
  2041.  
  2042.  Users of other programming languages must also define object variables to be 
  2043.  pointers to the data structure used to represent SOM objects. The way this is 
  2044.  done is programming-language dependent. The header file "somtypes.h" defines 
  2045.  the structure of SOM objects for the C language. 
  2046.  
  2047.  
  2048. ΓòÉΓòÉΓòÉ 4.2.2. Creating instances of a class ΓòÉΓòÉΓòÉ
  2049.  
  2050. For C programmers with usage bindings, SOM provides the <className>New and the 
  2051. <className>Renew macros for creating instances of a class. 
  2052.  
  2053. These macros are illustrated with the following two examples, each of which 
  2054. creates a single instance of class "Hello": 
  2055.  
  2056.    obj = HelloNew();
  2057.    obj = HelloRenew(buffer);
  2058.  
  2059.  
  2060. ΓòÉΓòÉΓòÉ 4.2.2.1. Using <className>New ΓòÉΓòÉΓòÉ
  2061.  
  2062. After verifying that the <className> class object exists, the <className>New 
  2063. macro invokes the somNew method on the class object.  This allocates enough 
  2064. space for a new instance of <className>, creates a new instance of the class, 
  2065. initializes this new object by invoking somDefaultIniton it, and then returns a 
  2066. pointer to it.  The <className>Newmacro automatically creates the the class 
  2067. object for <className>, as well as its ancestor classes and metaclass, if these 
  2068. objects have not already been created. 
  2069.  
  2070. After a client program has finished using an object created using the 
  2071. <className >New macro, the object should be freed by invoking the method 
  2072. somFree on it: 
  2073.  
  2074.    _somFree(obj);
  2075.  
  2076. After uninitializing the object by invoking somDestruct on it, somFree calls 
  2077. the class object for storage deallocation. This is important because storage 
  2078. for an object created using the <className>New macro is allocated by the class 
  2079. of the object. Thus, only the class of the object can know how to reclaim the 
  2080. object's storage. object for storage deallocation. 
  2081.  
  2082.  
  2083. ΓòÉΓòÉΓòÉ 4.2.2.2. Using <className>Renew ΓòÉΓòÉΓòÉ
  2084.  
  2085. After verifying that the <className> class object exists, the <className>Renew 
  2086. macro invokes the somRenew method on the class object.  <className>Renew is 
  2087. only used when the space for the object has been allocated previously. (Perhaps 
  2088. the space holds an old uninitialized object that is not needed anymore.) This 
  2089. macro converts the given space into a new, initialized instance of <className> 
  2090. and returns a pointer to it.  The programmer is responsible for ensuring that 
  2091. the argument of <className>Renew  points to a block of storage large enough to 
  2092. hold an instance of class <className>. The SOM method somGetInstanceSize can be 
  2093. invoked on the class to determine the amount of memory required. Like 
  2094. <className>New, the <className>Renew macro automatically creates any required 
  2095. class objects that have not already been created. 
  2096.  
  2097. Hint: When creating a large number of class instances, it may be more efficient 
  2098. to allocate at once enough memory to hold all the instances, and then invoke 
  2099. <className>Renew once for each object to be created, rather than performing 
  2100. separate memory allocations. 
  2101.  
  2102.  
  2103. ΓòÉΓòÉΓòÉ 4.2.2.3. Using <className>NewClass ΓòÉΓòÉΓòÉ
  2104.  
  2105. The C and C++ usage bindings for a SOM class also provide static linkage to a 
  2106. <className>NewClass function that can be used to create the class object.  This 
  2107. can be useful if the class object is needed before its instances are created. 
  2108.  
  2109. For example, the following C code uses the function HelloNewClass to create the 
  2110. "Hello" class object. The arguments to this function are defined by the usage 
  2111. bindings, and indicate the version of the class implementation that is assumed 
  2112. by the bindings. (For more detail on creation of classes, see the later 
  2113. section, "Creating a class object.") Once the class object has been created, 
  2114. the example invokes the method somGetInstanceSize  on this class to determine 
  2115. the size of a "Hello" object, uses SOMMalloc to allocate storage, and then uses 
  2116. the HelloRenew macro to create ten instances of the "Hello" class: 
  2117.  
  2118.    #include <hello.h>
  2119.    main()
  2120.    {
  2121.    SOMClass helloCls; /*  A pointer for the Hello class object */
  2122.    Hello objA[10];    /*  an array of Hello instances */
  2123.    unsigned char *buffer;
  2124.    int i;
  2125.    int size;
  2126.  
  2127.    /* create the Hello class object:  */
  2128.    helloCls =  HelloNewClass(Hello_MajorVersion, Hello_MinorVersion);
  2129.  
  2130.    /* get the amount of space needed for a Hello instance:
  2131.     * (somGetInstanceSize is a method provided by SOM.) */
  2132.    size =  _somGetInstanceSize(helloCls);
  2133.    size = ((size+3)/4)*4;  /* round up to doubleword multiple */
  2134.  
  2135.    /* allocate the total space needed for ten instances: */
  2136.    buffer =  SOMMalloc(10*size);
  2137.  
  2138.    /* convert the space into ten separate Hello instances: */
  2139.    for (i=0; i<10; i++)
  2140.        objA[i] = HelloRenew(buffer+i*size);
  2141.    ...
  2142.    ...
  2143.    /* Uninitialize the objects and free them */
  2144.    for (i=0; i<10; i++)
  2145.      _somDestruct(objA[i],0,0);
  2146.    SOMFree(buffer);
  2147.    }
  2148.  
  2149. When an object created with the <className>Renew macro is no longer needed, its 
  2150. storage must be freed using the dual to whatever method was originally used to 
  2151. allocate the storage. Two method pairs are typical: 
  2152.  
  2153.      For example, if an object was originally initialized using the 
  2154.       <className>New macro, then, as discussed previously, the client should 
  2155.       use the somFree  method on it. 
  2156.  
  2157.      On the other hand, if the program uses the SOMMalloc function to allocate 
  2158.       memory, as illustrated in the example above, then the SOMFree function 
  2159.       must be called to free the objects' storage (because SOMFree is the dual 
  2160.       to SOMMalloc). Before this is done, the objects in the region to be freed 
  2161.       should be deinitialized by invoking the somDestruct method on them. This 
  2162.       allows each object to free any memory that may have been allocated 
  2163.       without the programmer's knowledge. (The somFree method also calls the 
  2164.       somDestruct method.) 
  2165.  
  2166.  Note:  In the somDestruct method call above, the first zero indicates that 
  2167.         memory should not be freed by the class of the object (that is, the 
  2168.         programmer will do it explicitly).  The second zero indicates that the 
  2169.         class of the object is responsible for overall control of object 
  2170.         uninitialization.  For further discussion, see Section 5.5, 
  2171.         "Initializing and Uninitializing Objects," in Chapter 5, "Implementing 
  2172.         Classes in SOM." 
  2173.  
  2174.  For C++ programmers with usage bindings, instances of a class <className> can 
  2175.  be created with a new operator provided by the usage bindings of each SOM 
  2176.  class.  The new operator automatically creates the class object for 
  2177.  <className>, as well as its ancestor classes and metaclass,  if they do not 
  2178.  yet exist.  After verifying the existence of the desired class object, the new 
  2179.  operator then invokes the somNewNoInit  method on the class.  This allocates 
  2180.  memory and creates a new instance of the class,  but it does not initialize 
  2181.  the new object. Initialization of the new object is then performed using one 
  2182.  of the C++ constructors defined by the usage bindings.  (For further 
  2183.  discussion, see Section 5.5 "Initializing and Uninitializing Objects," in 
  2184.  Chapter 5, "Implementing Classes in SOM.") Two variations of the new operator 
  2185.  require no arguments. When either is used, the C++ usage bindings provide a 
  2186.  default constructor that invokes the somDefaultInit method on the new object. 
  2187.  Thus, a new object initialized by somDefaultInit would be created using either 
  2188.  of the forms: 
  2189.  
  2190.  new <className> 
  2191.  
  2192.  
  2193.  new <classname>() 
  2194.  
  2195.  For example: 
  2196.  
  2197.      obj = new Hello;
  2198.      obj1 = new Hello();
  2199.  
  2200.  For convenience, pointers to SOM objects created using the newoperator can be 
  2201.  freed using the delete operator, just as for normal C++ objects (or, the 
  2202.  somFree method could be used): 
  2203.  
  2204.     delete obj;
  2205.     obj1->somFree;
  2206.  
  2207.  When previously allocated space will be used to hold a new object, C++ 
  2208.  programmers should use the somRenew method, described below. C++ bindings do 
  2209.  not provide a macro for this purpose. 
  2210.  
  2211.  somNew and somRenew: C and C++ programmers, as well programmers using other 
  2212.  languages, can create instances of a class using the SOM methods somNew and 
  2213.  somRenew, invoked on the class object. As discussed and illustrated above for 
  2214.  the C bindings, the class object must first be created using the 
  2215.  <className>NewClass procedure (or, perhaps, using the somFindClass method-see 
  2216.  the section "Using class objects," to follow later in this chapter). 
  2217.  
  2218.  The somNew method invoked on the class object creates a new instance of the 
  2219.  class, initializes the object using somDefaultInit, and then returns a pointer 
  2220.  to the new object. For instance, the following C example creates a new object 
  2221.  of the "Hello" class. 
  2222.  
  2223.      #include <hello.h>
  2224.      main()
  2225.      {
  2226.        SOMClass helloCls;   /* a pointer to the Hello class */
  2227.        Hello obj;           /* a pointer to an Hello instance */
  2228.        /* create the Hello class  */
  2229.        helloCls = HelloNewClass(Hello_MajorVersion, Hello_MinorVersion);
  2230.        obj = _somNew(helloCls); /* create the Hello instance */
  2231.      }
  2232.  
  2233.  An object created using the somNew method should be freed by invoking the 
  2234.  somFree method on it after the client program is finished using the object. 
  2235.  
  2236.  The somRenew method invoked on the class object creates a new instance of a 
  2237.  class using the given space, rather than allocating new space for the object. 
  2238.  The method converts the given space into an instance of the class, initializes 
  2239.  the new object using somDefaultInit, and then returns a pointer to it. The 
  2240.  argument to somRenew must point to a block of storage large enough to hold the 
  2241.  new instance. The method somGetInstanceSize can be used to determine the 
  2242.  amount of memory required. For example, the following C++ code creates ten 
  2243.  instances of the "Hello" class: 
  2244.  
  2245.      #include <hello.xh>
  2246.      #include <somcls.xh>
  2247.      main()
  2248.      {
  2249.        SOMClass *helloCls; // a pointer to the Hello class
  2250.        Hello *objA[10]  //  an array of Hello instance pointers
  2251.        unsigned char *buffer;
  2252.        int i;
  2253.        int size;
  2254.  
  2255.       // create the Hello class object
  2256.       helloCls =  HelloNewClass(Hello_MajorVersion, Hello_MinorVersion);
  2257.  
  2258.       // get the amount of space needed for a Hello instance:
  2259.       size = helloCls-> somGetInstanceSize();
  2260.       size = ((size+3)/4)*4;  // round up to doubleword multiple
  2261.  
  2262.       // allocate the total space needed for ten instances
  2263.       buffer =  SOMMalloc(10*size);
  2264.  
  2265.       // convert the space into ten separate Hello objects
  2266.       for (i=0; i<10; i++)
  2267.          objA[i] = helloCls-> somRenew(buffer+i*size);
  2268.  
  2269.       // Uninitialize the objects and free them
  2270.       for (i=0; i<10; i++)
  2271.          objA[i]-> somDestruct(0,0);
  2272.       SOMFree(buffer);
  2273.      }
  2274.  
  2275.  The somNew  and somRenew methods are useful for creating instances of a class 
  2276.  when the header file for the class is not included in the client program at 
  2277.  compile time. (The name of the class might be specified by user input, for 
  2278.  example.) However, the <className>New macro (for C) and the new operator (for 
  2279.  C++) can only be used for classes whose header file is included in the client 
  2280.  program at compile time. 
  2281.  
  2282.  Objects created using the somRenew method should be freed by the client 
  2283.  program that allocated it, using the dual to whatever allocation approach was 
  2284.  initially used. If the somFree method is not appropriate (because the method 
  2285.  somNew was not initially used), then, before memory is freed, the object 
  2286.  should be explicitly deinitialized by invoking the somDestruct method on it. 
  2287.  (The somFree method calls the somDestruct method.  Refer to the previous C 
  2288.  example for Renew for an explanation of the arguments to somDestruct.) 
  2289.  
  2290.  
  2291. ΓòÉΓòÉΓòÉ 4.2.3. Invoking methods on objects ΓòÉΓòÉΓòÉ
  2292.  
  2293. This topic describes the general way to invoke methods in C/C+ + and in other 
  2294. languages, and then presents subtopics for more specialized situations. 
  2295.  
  2296.  
  2297. ΓòÉΓòÉΓòÉ 4.2.3.1. Making typical method calls ΓòÉΓòÉΓòÉ
  2298.  
  2299. For C programmers with usage bindings: To invoke a method in C, use the macro: 
  2300.  
  2301. _<methodName> (receiver, args) 
  2302.  
  2303. (that is, an underscore followed by the method name). Arguments to the macro 
  2304. are the receiver of the method followed by all of the arguments to the method. 
  2305. For example: 
  2306.  
  2307.    _foo(obj, somGetGlobalEnvironment(), x, y)
  2308.  
  2309. This invokes method "foo" on "obj" (the remaining arguments are arguments to 
  2310. the method "foo"). This expression can be used anywhere that a standard 
  2311. function call can be used in C. 
  2312.  
  2313. Required arguments 
  2314.  
  2315. In C, calls to methods defined using IDL require at least two arguments- a 
  2316. pointer to the receiving object (the object responding to the method) and a 
  2317. value of type (Environment *). The Environment data structure is specified by 
  2318. CORBA, and is used to pass environmental information between a caller and a 
  2319. called method. For example, it is used to return exceptions. (For more 
  2320. information on how to supply and use the Environment structure, see the later 
  2321. section entitled "Exceptions and error handling.") 
  2322.  
  2323. In the IDL definition of a method, by contrast, the receiver and the 
  2324. Environment pointer are not listed as parameters to the method. (Unlike the 
  2325. receiver, the Environment pointer is considered a method parameter, even though 
  2326. it is never explicitly specified in IDL. For this reason, it is called an 
  2327. implicit method parameter.) For example, if a method is defined in a .idl file 
  2328. with two parameters, as in: 
  2329.  
  2330.    int foo (in char c, in float f);
  2331.  
  2332. then, with the C usage bindings, the method would be invoked with four 
  2333. arguments, as in: 
  2334.  
  2335.    intvar = _foo(obj, somGetGlobalEnvironment(), x, y);
  2336.  
  2337. where "obj" is the object responding to the method and "x" and "y" are the 
  2338. arguments corresponding to "c" and "f", above. 
  2339.  
  2340. If the IDL specification of the method includes a context specification, then 
  2341. the method has an additional (implicit) context parameter. Thus, when invoking 
  2342. the method, this argument must follow immediately after the Environment pointer 
  2343. argument.  (None of the SOM-supplied methods require context arguments.)  The 
  2344. Environment  and context method parameters are prescribed by the CORBA 
  2345. standard. 
  2346.  
  2347. If the IDL specification of the class that introduces the method includes the 
  2348. callstyle=oidl modifier, then the (Environment*) and context arguments should 
  2349. not be supplied when invoking the method. That is, the receiver of the method 
  2350. call is followed immediately by the arguments to the method (if any). Some of 
  2351. the classes supplied in the SOMobjects Toolkit (including SOMObject, SOMClass, 
  2352. and SOMClassMgr) are defined in this way, to ensure compatibility with the 
  2353. previous release of SOM. The System Object Model Programming Reference 
  2354. specifies for each method whether these arguments are used. 
  2355.  
  2356. If you use a C expression to compute the first argument to a method call (the 
  2357. receiver), you must use an expression without side effects, because the first 
  2358. argument is evaluated twice by the _<methodName> macro expansion. In 
  2359. particular, a somNew method call or a macro call of <className>New can not be 
  2360. used as the first argument to a C method call, because doing so would create 
  2361. two new class instances rather than one. 
  2362.  
  2363. Following the initial, required arguments to a method (the receiving object, 
  2364. the Environment, if any, and the context, if any), you enter any additional 
  2365. arguments required by that method, as specified in IDL.  For a discussion of 
  2366. how IDL in/out/inout argument types may to C/C++ data types, see the topic 
  2367. "Parameter list" in Chapter 4, "SOM IDL and the SOM Compiler." 
  2368.  
  2369. Short form vs long form 
  2370.  
  2371. If a client program uses the bindings for two different classes that introduce 
  2372. or inherit two different methods of the same name, then the _<methodName> macro 
  2373. described above (called the short form) will not be provided by the bindings, 
  2374. because the macro would be ambiguous in that circumstance. The following long 
  2375. form macro, however, is always provided by the usage bindings for each class 
  2376. that supports the method: 
  2377.  
  2378. <className>_<methodName> (receiver, args) 
  2379.  
  2380. For example, method "foo" supported by class "Bar" can be invoked as: 
  2381.  
  2382.   Bar_foo(obj, somGetGlobalEnvironment(), x, y)   (in C)
  2383.  
  2384. where "obj"  has type "Bar" and "x" and "y" are the arguments to method "foo". 
  2385.  
  2386. In most cases (where there is no ambiguity, and where the method is not a 
  2387. va_list method, as described in the subsequent subtopic "Using 'va_list' 
  2388. methods"), a C programmer may use either the short or the long form of a method 
  2389. invocation macro interchangeably. However, only the long form complies with the 
  2390. CORBA standard for C usage bindings.  If you wish to write code that can be 
  2391. easily ported to other vendor platforms that support the CORBA standard, use 
  2392. the long form exclusively. The long form is always available for every method 
  2393. that a class supports. The short form is provided both as a programming 
  2394. convenience and for source code compatibility with release 1 of SOM. 
  2395.  
  2396. In order to use the long form, a programmer will usually know what type an 
  2397. object is expected to have.  If this is not known, but the different methods 
  2398. have the same signature, the method can be invoked using name-lookup 
  2399. resolution, as described in a following subtopic of this section. 
  2400.  
  2401. For C++  programmers with usage bindings:  To invoke a method, use the standard 
  2402. C++ form shown below: 
  2403.  
  2404. obj-><methodName> (args) 
  2405.  
  2406. where args are the arguments to the method. For instance, the following example 
  2407. invokes method "foo" on "obj": 
  2408.  
  2409.    obj->foo(somGetGlobalEnvironment(), x, y)
  2410. Required arguments 
  2411.  
  2412. All methods introduced by classes declared using IDL (except those having the 
  2413. SOM IDL callstyle=oidl modifier) have at least one parameter-a value of type 
  2414. (Environment *). The Environment data structure is used to pass environmental 
  2415. information between a caller and a called method. For example, it is used to 
  2416. return exceptions. For more information on how to supply and use the 
  2417. Environment structure, see the later section entitled "Exceptions and error 
  2418. handling." 
  2419.  
  2420. The Environment pointer is an implicit parameter; in the IDL definition of a 
  2421. method, the Environment pointer is not explicitly listed as a parameter to the 
  2422. method. For example, if a method is defined in IDL with two explicit 
  2423. parameters, as in: 
  2424.  
  2425.    int foo (in char c, in float f);
  2426.  
  2427. then the method would be invoked from C++ bindings with three arguments, as in: 
  2428.  
  2429.    intvar = obj->foo(somGetGlobalEnvironment(), x, y);
  2430.  
  2431. where "obj" is the object responding to the method and "x" and "y" are the 
  2432. arguments corresponding to "c" and "f", above. 
  2433.  
  2434. If the IDL specification of the method includes a context specification, then 
  2435. the method has a second implicit parameter, of type context, and the method 
  2436. must be invoked with an additional context argument.  This argument must follow 
  2437. immediately after the Environment pointer argument.  (No SOM-supplied methods 
  2438. require context arguments.)  The Environment and context method parameters are 
  2439. prescribed by the CORBA standard. 
  2440.  
  2441. If the IDL specification of the class that introduces the method includes the 
  2442. callstyle=oidl modifier, then the (Environment  *) and context arguments should 
  2443. not be supplied when the method is invoked. Some of the classes supplied in the 
  2444. SOMobjects Toolkit (including SOMObject, SOMClass, and SOMClassMgr) are defined 
  2445. in this way, to ensure compatibility with the previous release of SOM. The 
  2446. System Object Model Programming Reference specifies for each method whether 
  2447. these arguments are used. 
  2448.  
  2449. Following the initial, required arguments to a method (the receiving object, 
  2450. the Environment, if any, and the context, if any), you enter any additional 
  2451. arguments required by that method, as specified in IDL.  For a discussion of 
  2452. how IDL in/out/inout argument types map to C/C++ data types, see the topic 
  2453. "Parameter list" in Chapter 4, "SOM IDL and the SOM Compiler." 
  2454.  
  2455. For non-C/C++ programmers:  To invoke a static method  (that is, a method 
  2456. declared when defining an OIDL or IDL object interface) without using the C or 
  2457. C++ usage bindings, a programmer can use the somResolve procedure. The 
  2458. somResolve  procedure takes as arguments a pointer to the object on which the 
  2459. method is to be invoked and a method token for the desired method. It returns a 
  2460. pointer to the method's procedure (or raises a fatal error if the object does 
  2461. not support the method). Depending on the language and system, it may be 
  2462. necessary to cast this procedure pointer to the appropriate type; the way this 
  2463. is done is language-specific. 
  2464.  
  2465. The method is then invoked by calling the procedure returned by somResolve (the 
  2466. means for calling a procedure, given a pointer to it, is language-specific), 
  2467. passing the method's receiver, the Environment pointer (if necessary), the 
  2468. context argument (if necessary) and the remainder of the method's arguments, if 
  2469. any. (See the section above for C programmers; the arguments to a method 
  2470. procedure are the same as the arguments passed using the long form of the 
  2471. C-language method-invocation macro for that method.) 
  2472.  
  2473. Using somResolve requires the programmer to know where to find the method token 
  2474. for the desired method. Method tokens are available from class objects that 
  2475. support the method (via the method somGetMethodToken), or from a global data 
  2476. structure, called the ClassData structure,  corresponding to the class that 
  2477. introduces the method. In C and C++ programs with access to the definitions for 
  2478. ClassData structures provided by usage bindings, the method token for method 
  2479. methodName introduced by class className may be accessed by the following 
  2480. expression: 
  2481.  
  2482. <className>ClassData.<methodName > 
  2483.  
  2484. For example, the method token for method "sayHello"introduced by class "Hello" 
  2485. is stored at location HelloClassData.sayHello, for C and C++ programmers.  The 
  2486. way method tokens are accessed in other languages is language-specific. 
  2487.  
  2488. As an  example of using offset resolution to invoke methods from a programming 
  2489. language other than C/C++, one would do the following to create an instance of 
  2490. a SOM Class X in Smalltalk: 
  2491.  
  2492.    1. Initialize the SOM run-time environment, if it has not previously been 
  2493.       initialized, using the somEnvironmentNew function. 
  2494.  
  2495.    2. If the class object for class X has not yet been created, use somResolve 
  2496.       with arguments SOMClassMgrObject (returned by somEnvironmentNew in step 
  2497.       1) and the method token for the somFindClass method,  to obtain a method 
  2498.       procedure pointer for the somFindClass method. Use the method procedure 
  2499.       for somFindClass to create the class object for class X:  Call the 
  2500.       procedure with arguments SOMClassMgrObject, the result of calling the 
  2501.       somIdFromString function with argument "X", and the major and minor 
  2502.       version numbers for class X (or zero). The procedure returns the class 
  2503.       object for class X. 
  2504.  
  2505.    3. Use somResolve with arguments representing the class object for X 
  2506.       (returned by somFindClass in step 2) and the method token for the somNew 
  2507.       method, to obtain a method procedure pointer for method somNew. (The 
  2508.       somNew method is used to create instances of class X.) 
  2509.  
  2510.    4. Call the method procedure for somNew (using the method procedure pointer 
  2511.       obtained in step 3) with the class object for X (returned by somFindClass 
  2512.       in step 3) as the argument. The procedure returns a new instance of class 
  2513.       X. 
  2514.  
  2515.  In addition to somResolve, SOM also supplies the somClassResolve procedure. 
  2516.  Instead of an object, the somClassResolve procedure takes a class as its first 
  2517.  argument, and then selects a method procedure from the instance method table 
  2518.  of the passed class. (The somResolve procedure, by contrast, selects a method 
  2519.  procedure from the instance method table of the class of which the passed 
  2520.  object is an instance.) The somClassResolve procedure therefore supports 
  2521.  casted  method resolution. See the System Object Model Programming Reference 
  2522.  for more information on somResolve  and somClassResolve. 
  2523.  
  2524.  If the programmer does not know at compile time which class introduces the 
  2525.  method to be invoked, or if the programmer cannot directly access method 
  2526.  tokens, then the procedure somResolveByName can be used to obtain a method 
  2527.  procedure using name-lookup resolution, as described in the next section. 
  2528.  
  2529.  If the signature of the method to be invoked is not known at compile time, but 
  2530.  can be discovered at run time, use somResolve or somResolveByName  to get a 
  2531.  pointer to the somDispatch method procedure, then use it to invoke the 
  2532.  specific method, as described below under "Method name or signature not known 
  2533.  at compile time." 
  2534.  
  2535.  
  2536. ΓòÉΓòÉΓòÉ 4.2.3.2. Accessing Attributes ΓòÉΓòÉΓòÉ
  2537.  
  2538. In addition to methods, SOM objects can also have attributes. An attribute is 
  2539. an IDL shorthand for declaring methods, and does not necessarily indicate the 
  2540. presence of any particular instance data in an object of that type. Attribute 
  2541. methods are called "get" and "set" methods. For example, if a class "Hello" 
  2542. declares an attribute called "msg", then object variables of type "Hello" will 
  2543. support the methods _get_msg and _set_msg to access or set the value of the 
  2544. "msg" attribute. (Attributes that are declared as "readonly" have no "set" 
  2545. method, however.) 
  2546.  
  2547. The "get" and "set" methods are invoked in the same way as other methods. For 
  2548. example, given class "Hello" with attribute "msg" of type string, the following 
  2549. code segments set and get the value of the "msg" attribute: 
  2550.  
  2551. For C: 
  2552.  
  2553.    #include <hello.h>
  2554.    Hello obj;
  2555.    Environment *ev = somGetGlobalEnvironment();
  2556.  
  2557.    obj = HelloNew();
  2558.    __set_msg(obj, ev, "Good Morning");/*note: two leading underscores */
  2559.    printf("%s\n", __get_msg(obj, ev));
  2560.  
  2561. For C++: 
  2562.  
  2563.    #include <hello.xh>
  2564.    #include <stdio.h>
  2565.    Hello *obj;
  2566.    Environment *ev = somGetGlobalEnvironment();
  2567.  
  2568.    obj = new Hello;
  2569.    obj->_set_msg(ev, "Good Morning");
  2570.    printf("%s\n", obj->_get_msg(ev));
  2571.  
  2572. Attributes available with each class, if any, are described in the 
  2573. documentation of the class itself in the System Object Model Programming 
  2574. Reference. 
  2575.  
  2576.  
  2577. ΓòÉΓòÉΓòÉ 4.2.3.3. Using 'va_list' methods ΓòÉΓòÉΓòÉ
  2578.  
  2579. SOM supports methods whose final argument is a va_list. A va_list is a data 
  2580. type whose representation depends on the operating-system platform. To aid 
  2581. construction of portable code, SOM supports a platform-neutral API for building 
  2582. and manipulating va_lists. Use of this API is recommended on all platforms 
  2583. because it is compliant with the ANSI C standard and because of its 
  2584. portability. 
  2585.  
  2586. Note:  Initially support for va_list functions is available only for the 
  2587.        PowerPC platform. With the release of SOM 3.0 however, support is 
  2588.        extended to the PC platform. 
  2589.  
  2590.  A function to create a va_list is not provided. Instead, users declare local 
  2591.  variables of type somVaBuf and va_list. 
  2592.  
  2593.  The following sequence of calls is used to create and destroy a va_list: 
  2594.  
  2595.      somVaBuf_create 
  2596.  
  2597.       Creates a SOM buffer for variable arguments from which the va_list will 
  2598.       be built. 
  2599.  
  2600.      somVaBuf_add 
  2601.  
  2602.       Adds an argument to the SOM buffer for variable arguments. 
  2603.  
  2604.      somVaBuf_get_valist 
  2605.  
  2606.       Copies the va_list from the SOM buffer. 
  2607.  
  2608.      somVaBuf_destroy 
  2609.  
  2610.       Releases the SOM buffer and its associated va_list. 
  2611.  
  2612.      somvalistSetTarget 
  2613.  
  2614.       Modifies the first scalar value on the va_list without other side 
  2615.       effects. 
  2616.  
  2617.      somvalistGetTarget 
  2618.  
  2619.       Gets the first scalar value from the va_list without other side effects. 
  2620.  
  2621.  Detailed information on these functions is provided in the System Object Model 
  2622.  Programming Reference. 
  2623.  
  2624.  Examples of va_list usage 
  2625.  
  2626.  The following code segments pass a va_list to the somDispatch method by using 
  2627.  the SOMobjects functions that build the va_list. 
  2628.  
  2629.  The somDispatch method (introduced by SOMObject) is a particularly useful 
  2630.  method whose final argument is a va_list. As explained in the System Object 
  2631.  Model Programming Reference, somDispatch can be used to invoke some other 
  2632.  method (called the "dispatched" method) on an object when usage bindings for 
  2633.  the dispatched method are not available or when the method to be dispatched is 
  2634.  not known until run time. The va_list argument for somDispatch holds the 
  2635.  arguments that will be passed to the dispatched method, including the target 
  2636.  object for the dispatched method. 
  2637.  
  2638.  For C: 
  2639.  
  2640.   #include <somobj.h>
  2641.   void f1(SOMObject obj, Environment *ev)
  2642.   {
  2643.           char *msg;
  2644.           va_list start_val;
  2645.           somVaBuf vb;
  2646.           char *msg1 = "Good Morning";
  2647.  
  2648.           vb = (somVaBuf)somVaBuf_create(NULL, 0);
  2649.           somVaBuf_add(vb, (char *)&obj, tk_pointer);
  2650.                                                               /* target for _set_msg */
  2651.           somVaBuf_add(vb, (char *)&ev, tk_pointer);
  2652.                                                               /* next argument  */
  2653.           somVaBuf_add(vb, (char *)&msg1, tk_pointer);
  2654.                                                               /* final argument */
  2655.           somVaBuf_get_valist(vb, &start_val);
  2656.  
  2657.           /* dispatch _set_msg on object */
  2658.           SOMObject_somDispatch(
  2659.                   obj,    /* target for somDispatch */
  2660.                   0,      /* says ignore dispatched method result */
  2661.                   somIdFromString("_set_msg"),  /* the somId for _set_msg */
  2662.                   start_val);     /* target and args for _set_msg */
  2663.  
  2664.           /* dispatch _get_msg on obj:      */
  2665.           /* Get a fresh copy of the va_list      */
  2666.           somVaBuf_get_valist(vb, &start_val);
  2667.           SOMObject_somDispatch(
  2668.                   obj,
  2669.                   (somToken *)&msg,
  2670.                                  /* address to store dispatched result */
  2671.                   somIdFromString("_get_msg"),
  2672.                   start_val);     /* target and arguments for _get_msg */
  2673.           printf("%s\n",msg);
  2674.           somVaBuf_destroy(vb);
  2675.   }
  2676.  For C++: 
  2677.  
  2678.   #include <somobj.h>
  2679.   void f1(SOMObject obj, Environment *ev)
  2680.   {
  2681.           char *msg;
  2682.           va_list start_val;
  2683.           somVaBuf vb;
  2684.           char *msg1 = "Good Morning";
  2685.  
  2686.           vb = (somVaBuf)somVaBuf_create(NULL, 0);
  2687.           somVaBuf_add(vb, (char *)&obj, tk_pointer);
  2688.                                            /* target for _set_msg */
  2689.           somVaBuf_add(vb, (char *)&ev, tk_pointer);
  2690.                                                 /* next argument  */
  2691.           somVaBuf_add(vb, (char *)&msg1, tk_pointer);
  2692.                                                 /* final argument */
  2693.           somVaBuf_get_valist(vb, &start_val);
  2694.  
  2695.           /* dispatch _set_msg on object */
  2696.           obj->SOMObject_somDispatch(
  2697.                   0,      /* says ignore dispatched method result */
  2698.                   somIdFromString("_set_msg"),  /* the somId for _set_msg */
  2699.                   start_val);     /* target and args for _set_msg */
  2700.  
  2701.           /* dispatch _get_msg on obj:      */
  2702.           /* Get a fresh copy of the va_list      */
  2703.           somVaBuf_get_valist(vb, &start_val);
  2704.           obj->SOMObject_somDispatch(
  2705.                   (somToken *)&msg,
  2706.                                  /* address to store dispatched result */
  2707.                   somIdFromString("_get_msg"),
  2708.                   start_val);     /* target and arguments for _get_msg */
  2709.           printf("%s\n",msg);
  2710.           somVaBuf_destroy(vb);
  2711.   }
  2712.  
  2713.  As a convenience, methods whose final argument is a va_list can be invoked 
  2714.  from C and C++ by using the short form of method invocation and specifying a 
  2715.  variable number of arguments in place of the va_list. That is, beginning at 
  2716.  the syntax position where the va_list argument is expected, SOMobjects 
  2717.  interprets all subsequent arguments as being the components of the va_list. 
  2718.  This is illustrated below, using the somDispatch method. 
  2719.  
  2720.  As an example of using the variable-argument interface to somDispatch, the 
  2721.  following code segments illustrate how an example of attribute access (in the 
  2722.  topic "Accessing attributes") could be recoded to operate without usage 
  2723.  bindings for the "Hello" class. These code segments are expressed as functions 
  2724.  that accept an argument of type SOMObject under the assumption that bindings 
  2725.  for "Hello" are not available. (This requires usage bindings for SOMObject, 
  2726.  which are also required for calling somDispatch.) 
  2727.  
  2728.  For C: 
  2729.  
  2730.   #include <somobj.h>
  2731.   void f1(SOMObject obj, Environment *ev)
  2732.   {
  2733.           char *msg;
  2734.           /* dispatch _set_msg on obj:   */
  2735.           _somDispatch(
  2736.                   obj,    /* the target for somDispatch */
  2737.                   0,      /* says ignore the dispatched method result */
  2738.                   somIdFromString("_set_msg"),  /* the somId for _set_msg */
  2739.                   obj,    /* the target for _set_msg */
  2740.                   ev,     /* the other arguments for _set_msg */
  2741.                   "Good Morning");
  2742.           /* dispatch _get_msg on obj:     */
  2743.           _somDispatch(
  2744.                   obj,
  2745.                   (somToken *)&msg,
  2746.                               /* address to hold dispatched method result */
  2747.                   somIdFromString("_get_msg"),
  2748.                   obj,    /* the target for _get_msg */
  2749.                   ev);    /* the other argument for _get_msg */
  2750.           printf("%s\n", msg);
  2751.   }
  2752.  
  2753.  For C++: 
  2754.  
  2755.   #include <somobj.h>
  2756.   void f1(SOMObject obj, Environment *ev)
  2757.   {
  2758.           char *msg;
  2759.           /* dispatch _set_msg on obj:   */
  2760.           obj->somDispatch(
  2761.                   0,      /* says ignore the dispatched method result */
  2762.                   somIdFromString("_set_msg"),  /* dispatched method id */
  2763.                   obj,    /* the target for _set_msg */
  2764.                   ev,     /* the other arguments for _set_msg */
  2765.                   "Good Morning");
  2766.           /* dispatch _get_msg on obj:     */
  2767.           obj->somDispatch(
  2768.                   (somToken *)&msg,
  2769.                         /* address to store dispatched result */
  2770.                   somIdFromString("_get_msg"),
  2771.                   obj,
  2772.                   ev);
  2773.           printf("%s\n", msg);
  2774.   }
  2775.  
  2776.  C programmers must be aware that the "short form" of the invocation macro that 
  2777.  is used above to pass a variable number of arguments to a va_list method is 
  2778.  only available in the absence of ambiguity. The long-form macro (which is 
  2779.  always available) requires an explicit va_list argument. (See "Short form vs 
  2780.  long form" under "Making typical method calls" earlier in this chapter.) 
  2781.  
  2782.  
  2783. ΓòÉΓòÉΓòÉ 4.2.3.4. Using name-lookup method resolution ΓòÉΓòÉΓòÉ
  2784.  
  2785. For C/C++  programmers:  Offset resolution is the most efficient way to select 
  2786. the method procedure appropriate to a given method call. Client programs can, 
  2787. however, invoke a method using "name-lookup" resolution instead of offset 
  2788. resolution. The C and C++ bindings for method invocation use offset resolution 
  2789. by default, but methods defined with the namelookup SOM IDL modifier result in 
  2790. C bindings in which the short form invocation macro uses name-lookup resolution 
  2791. instead.  Also, for both C and C++ bindings, a special lookup_<methodName> 
  2792. macro is defined. 
  2793.  
  2794. Name-lookup resolution is appropriate in the case where a programmer knows at 
  2795. compile time which arguments will be expected by a method (that is, its 
  2796. signature), but does not know the type of the object on which the method will 
  2797. be invoked. For example, name-lookup resolution can be used when two different 
  2798. classes introduce different methods of the same name and signature, and it is 
  2799. not known which method should be invoked (because the type of the object is not 
  2800. known at compile time). 
  2801.  
  2802. Name-lookup resolution is also used to invoke dynamic methods (that is, methods 
  2803. that have been added to a class's interface at run time rather than being 
  2804. specified in the class's IDL specification). For more information on 
  2805. name-lookup method resolution, see the topic "Method Resolution" in Chapter 4, 
  2806. "SOM IDL and the SOM Compiler." 
  2807.  
  2808. For C: To invoke a method using name-lookup resolution, when using the C 
  2809. bindings for a method that has been implemented with the namelookup modifier, 
  2810. use either of the following macros: 
  2811.  
  2812.  _<methodName> (receiver, args)
  2813.  
  2814. lookup_<methodName> (receiver, args) 
  2815.  
  2816. Thus, the short-form method invocation macro results in name-lookup resolution 
  2817. (rather than offset resolution), when the method has been defined as a 
  2818. namelookup method. (The long form of the macro for offset resolution is still 
  2819. available in the C usage bindings.) If the method takes a variable number of 
  2820. arguments, then the first form shown above is used when supplying a variable 
  2821. number of arguments, and the second form is used when supplying a va_list 
  2822. argument in place of the variable number of arguments. 
  2823.  
  2824. For C++: To invoke a method using name-lookup resolution, when using the C++ 
  2825. bindings for a method that has been defined with the namelookup modifier, use 
  2826. either of the following macros: 
  2827.  
  2828.  lookup_<methodName> (receiver, args) 
  2829.  
  2830.  <className>_lookup_<methodName> (receiver, args)
  2831.  
  2832. If the method takes a variable number of arguments, then the first form shown 
  2833. above is used when supplying a variable number of arguments, and the second 
  2834. form is used when supplying a va_list argument in place of the variable number 
  2835. of arguments. Note that the offset-resolution forms for invoking methods using 
  2836. the C++ bindings are also still available, even if the method has been defined 
  2837. as a namelookup method. 
  2838.  
  2839. For C/C++  To invoke a method using name-lookup resolution, when the method has 
  2840. not been defined as a namelookup method: 
  2841.  
  2842.      Use the somResolveByName procedure (described in the following section), 
  2843.       or any of the methods somLookupMethod, somFindMethod or somFindMethodOk 
  2844.       to obtain a pointer to the procedure that implements the desired method. 
  2845.  
  2846.      Then, invoke the desired method by calling that procedure, passing the 
  2847.       method's intended receiver, the Environment pointer (if needed), the 
  2848.       context argument (if needed), and the remainder of the method's 
  2849.       arguments, if any. 
  2850.  
  2851.  The somLookupMethod, somFindMethod and somFindMethodOK methods are invoked on 
  2852.  a class object  (the class of the method receiver should be used), and take as 
  2853.  an argument the somId for the desired method (which can be obtained from the 
  2854.  method's name using the somIdFromString function). For more information on 
  2855.  these methods, see the System Object Model Programming Reference. 
  2856.  
  2857.  Important Note: SOM provides many ways for a SOM user to acquire a pointer to 
  2858.  a method procedure. Once this is done, it becomes the user's responsibility to 
  2859.  make appropriate use of this procedure. 
  2860.  
  2861.      First, the procedure should only be used on objects for which this is 
  2862.       appropriate-otherwise, run-time errors are likely to result. 
  2863.  
  2864.      Second, when the procedure is used, it is essential that the compiler be 
  2865.       given correct information concerning the signature of the method and the 
  2866.       linkage required by the method.  (On many systems, there are different 
  2867.       ways to pass method arguments, and linkage information tells a compiler 
  2868.       how to pass the arguments indicated by a method's signature). 
  2869.  
  2870.  SOM method procedures on OS/2 must be called with "system" linkage.  On AIX, 
  2871.  there is only one linkage convention for procedure calls. While C and C++ 
  2872.  provide standard ways to indicate a method signature, the way to indicate 
  2873.  linkage information depends on the specific compiler and system.  For each 
  2874.  method declared using OIDL or IDL,  the C and C++ usage bindings therefore use 
  2875.  conditional macros and a typedef to name a type that has the correct linkage 
  2876.  convention. This type name can then be used by programmers with access to the 
  2877.  usage bindings for the class that introduces the method whose procedure 
  2878.  pointer is used. The type is named somTD_<className>_<methodName>. This is 
  2879.  illustrated in the following example, and further details are provided in the 
  2880.  section below, titled "Obtaining a method's procedure pointer." 
  2881.  
  2882.  
  2883. ΓòÉΓòÉΓòÉ 4.2.3.5. A name-lookup example ΓòÉΓòÉΓòÉ
  2884.  
  2885. The following example shows the use of name-lookup by a SOM client programmer. 
  2886. Name-lookup resolution is appropriate when a programmer knows that an object 
  2887. will respond to a method of some given name, but does not know enough about the 
  2888. type of the object to use offset method resolution. How can this happen? It 
  2889. normally happens when a programmer wants to write generic code, using methods 
  2890. of the same name and signature that are applicable to different classes of 
  2891. objects, and yet these classes have no common ancestor that introduces the 
  2892. method. This can easily occur in single-inheritance systems (such as Smalltalk 
  2893. and SOM release 1) and can also happen in multiple-inheritance systems such as 
  2894. SOM release 2-when class hierarchies designed by different people are brought 
  2895. together for clients' use. 
  2896.  
  2897. If multiple inheritance is available, it is always possible to create a common 
  2898. class ancestor into which methods of this kind can be migrated. A refactoring 
  2899. of this kind often implements a semantically pleasing generalization that 
  2900. unifies common features of two previously unrelated class hierarchies. This 
  2901. step is most practical, however, when it does not require the redefinition or 
  2902. recompilation of current applications that use offset resolution. SOM is unique 
  2903. in that it allows this. 
  2904.  
  2905. However, such refactoring must redefine the classes that originally introduced 
  2906. the common methods (so the methods can be inherited from the new "unifying" 
  2907. class instead). A client programmer who simply wants to create an application 
  2908. may not control the implementations of the classes. Thus, the use of 
  2909. name-lookup method resolution seems the best alternative for programmers who do 
  2910. not want to define new classes, but simply to make use of available ones. 
  2911.  
  2912. For example, assume the existence of two different SOM classes, "classX" and 
  2913. "classY", whose only common ancestor is SOMObject, and who both introduce a 
  2914. method named "reduce" that accepts a string as an argument and returns a long. 
  2915. We assume that the classes were not designed in conjunction with each other. As 
  2916. a result, it is unlikely that the "reduce" method was defined with a namelookup 
  2917. modifier. The following figure illustrates the class hierarchy for this 
  2918. example. 
  2919.  
  2920. Following is a C++ generic procedure that uses name-lookup method resolution to 
  2921. invoke the "reduce" method on its argument, which may be either of type 
  2922. "classX" or "classY". Note that there is no reason to include classY's usage 
  2923. bindings, since the typedef provided for the "reduce" method procedure in 
  2924. "classX" is sufficient for invoking the method procedure, independently of 
  2925. whether the target object is of type "classX" or "classY". 
  2926.  
  2927.    #include <classX.xh> // use classX's method proc typedef
  2928.  
  2929.    // this procedure can be invoked on a target of type
  2930.    // classX or classY.
  2931.  
  2932.    long generic_reduce1(SOMObject *target, string arg)
  2933.    {
  2934.       somTD_classX_reduce reduceProc = (somTD_classX_reduce)
  2935.       somResolveByName(target, "reduce");
  2936.       return reduceProc(target, arg);
  2937.    }
  2938.  
  2939. On the other hand, If the classes were designed in conjunction with each other, 
  2940. and the class designer felt that programmers might want to write generic code 
  2941. appropriate to either class of object, the namelookup modifier might have been 
  2942. used. This is a possibility in SOM release 2, even with multiple inheritance, 
  2943. but it is much more likely that the class designer would use multiple 
  2944. inheritance to introduce the reduce method in a separate class, and then use 
  2945. this other class as a parent for both classX and classY (thereby allowing the 
  2946. use of offset resolution). 
  2947.  
  2948. In any case, if the "reduce" method in "classX" were defined as a namelookup 
  2949. method, the following code would be appropriate.  Note that the name-lookup 
  2950. support provided by "classX" usage bindings is still appropriate for use on 
  2951. targets that do not have type "classX".  As a result, the "reduce" method 
  2952. introduced by "classY" need not have been defined as a namelookup method. 
  2953.  
  2954.    #include <classX.xh> // use classX's name-lookup support
  2955.  
  2956.    // this procedure can be invoked on a target of type
  2957.    // classX or classY.
  2958.  
  2959.    long generic_reduce2(SOMObject *target, string arg)
  2960.    {
  2961.        return lookup_reduce(target, arg);
  2962.    }
  2963.  
  2964. For non-C/C++  programmers:  Name-lookup  resolution is useful for non-C/C++ 
  2965. programmers when the type of an object on which a method must be invoked is not 
  2966. known at compile time or when method tokens cannot be directly accessed by the 
  2967. programmer. To invoke a method using name-lookup resolution when not using the 
  2968. C or C++ usage bindings, use the somResolveByName procedure to acquire a 
  2969. procedure pointer. How the programmer indicates the method arguments and the 
  2970. linkage convention in this case is compiler specific. 
  2971.  
  2972. The somResolveByName  procedure takes as arguments a pointer to the object on 
  2973. which the method is to be invoked and the name of the method, as a string. It 
  2974. returns a pointer to the method's procedure (or NULL if the method is not 
  2975. supported by the object). The method can then be invoked by calling the method 
  2976. procedure, passing the method's receiver, the Environment pointer (if 
  2977. necessary), the context argument (if necessary), and the rest of the method's 
  2978. arguments, if any. (See the section above for C programmers; the arguments to a 
  2979. method procedure are the same as the arguments passed to the long-form 
  2980. C-language method-invocation macro for that method.) 
  2981.  
  2982. As an example of invoking methods using name-lookup resolution using the 
  2983. procedure somResolveByName, the following steps are used to create an instance 
  2984. of a SOM Class X in Smalltalk: 
  2985.  
  2986.    1. Initialize the SOM run-time environment (if it is not already 
  2987.       initialized) using the somEnvironmentNew function. 
  2988.  
  2989.    2. If the class object for class X has not yet been created, use 
  2990.       somResolveByName with the arguments SOMClassMgrObject (returned by 
  2991.       somEnvironmentNew in step 1) and the string "somFindClass", to obtain a 
  2992.       method procedure pointer for the somFindClass method. Use the method 
  2993.       procedure for somFindClass to create the class object for class X: Call 
  2994.       the method procedure with these four arguments: SOMClassMgrObject; the 
  2995.       variable holding class X 's somId (the result of calling the 
  2996.       somIdFromString function with argument "X"); and the major and minor 
  2997.       version numbers for class X (or zero). The result is the class object for 
  2998.       class X. 
  2999.  
  3000.    3. Use somResolveByName with arguments the class object for X (returned by 
  3001.       somFindClass in step 2) and the string "somNew", to obtain a method 
  3002.       procedure pointer for method somNew. (This somNew method is used to 
  3003.       create instances of a class.) 
  3004.  
  3005.    4. Call the method procedure for somNew (using the method procedure pointer 
  3006.       obtained in step 3) with the class object for X (returned by somFindClass 
  3007.       in step 3) as the argument. The result is a new instance of class X. How 
  3008.       the programmer indicates the method arguments and the linkage convention 
  3009.       is compiler-specific. 
  3010.  
  3011.  
  3012. ΓòÉΓòÉΓòÉ 4.2.3.6. Obtaining a method's procedure pointer ΓòÉΓòÉΓòÉ
  3013.  
  3014. Method resolution is the process of obtaining a pointer to the procedure that 
  3015. implements a particular method for a particular object at run time.  The method 
  3016. is then invoked subsequently by calling that procedure, passing the method's 
  3017. intended receiver, the Environment pointer (if needed), the context argument 
  3018. (if needed), and the method's other arguments, if any. C and C++ programmers 
  3019. may wish to obtain a pointer to a method's procedure for efficient repeated 
  3020. invocations. 
  3021.  
  3022. Obtaining a pointer to a method's procedure is achieved in one of two ways, 
  3023. depending on whether the method is to be resolved using offset resolution or 
  3024. name-lookup resolution. Obtaining a method's procedure pointer via offset 
  3025. resolution is faster, but it requires that the name of the class that 
  3026. introduces the method and the name of the method be known at compile time.  It 
  3027. also requires that the method be defined as part of that class's interface in 
  3028. the IDL specification of the class. (See the topic "Method Resolution" in 
  3029. Chapter 4, "SOM IDL and the SOM Compiler" for more information on offset and 
  3030. name-lookup method resolution.) 
  3031.  
  3032.  
  3033. ΓòÉΓòÉΓòÉ 4.2.3.6.1. Offset resolution ΓòÉΓòÉΓòÉ
  3034.  
  3035. To obtain a pointer to a procedure using offset resolution, the C/C++ usage 
  3036. bindings provide the SOM_Resolve and SOM_ResolveNoCheck macros. The usage 
  3037. bindings themselves use the first of these, SOM_Resolve, for offset-resolution 
  3038. method calls. The difference in the two macros is that the SOM_Resolve macro 
  3039. performs consistency checking on its arguments, but the macro 
  3040. SOM_ResolveNoCheck, which is faster, does not. Both macros require the same 
  3041. arguments: 
  3042.  
  3043. SOM_Resolve(<receiver>, <className>, <methodName>) 
  3044. SOM_ResolveNoCheck(<receiver>, <className>, <methodName>) 
  3045.  
  3046. where the arguments are as follows: 
  3047.  
  3048.  receiver          The object to which the method will apply. It should be 
  3049.                    specified as an expression without side effects. 
  3050.  
  3051.  className         The name of the class that introduces the method. 
  3052.  
  3053.  methodName        The name of the desired method. 
  3054.  
  3055.  These two names (className and methodName) must be given as tokens, rather 
  3056.  than strings or expressions. (For example, as Animal rather than "Animal".) If 
  3057.  the symbol SOM_TestOn is defined and the symbol SOM_NoTest is not defined in 
  3058.  the current compilation unit, then SOM_Resolve verifies that receiver is an 
  3059.  instance of className or some class derived from className. If this test 
  3060.  fails, an error message is output and execution is terminated. 
  3061.  
  3062.  The SOM_Resolve and SOM_ResolveNoCheck  macros use the procedure somResolve to 
  3063.  obtain the entry-point address of the desired method procedure (or raise a 
  3064.  fatal error if methodName is not introduced by className). This result can be 
  3065.  directly applied to the method arguments, or stored in a variable of generic 
  3066.  procedure type (for example, somMethodPtr) and retained for later method use. 
  3067.  This second possibility would result in a loss of information, however, for 
  3068.  the reasons now given. 
  3069.  
  3070.  The SOM_Resolve or SOM_ResolveNoCheck macros are especially useful because 
  3071.  they cast the method procedure they obtain to the right type to allow the C or 
  3072.  C++ compiler to call  this procedure with system linkage and with the 
  3073.  appropriate arguments. This is why the result of SOM_Resolve is immediately 
  3074.  useful for calling the method procedure, and why storing the result of 
  3075.  SOM_Resolve in a variable of some "generic" procedure type results in a loss 
  3076.  of information. The correct type information can be regained, however, because 
  3077.  the type used by SOM_Resolve for casting the result of somResolve  is 
  3078.  available from C/C++ usage bindings using the typedef name 
  3079.  somTD_<className>_<methodName>. This type name describes a pointer to a method 
  3080.  procedure for methodName introduced by class className. If the final argument 
  3081.  of the method is a va_list, then the method procedure returned by SOM_Resolve 
  3082.  or SOM_ResolveNoCheck must be called with a va_list  argument, and not a 
  3083.  variable number of arguments. 
  3084.  
  3085.  Below is a C example of using SOM_Resolve to obtain a method procedure pointer 
  3086.  for method "sayHello", introduced by class "Hello", and using it to invoke the 
  3087.  method on "obj." (Assume that the only argument required by the "sayHello" 
  3088.  method is the Environment pointer.) 
  3089.  
  3090.      somMethodProc *p;
  3091.      SOMObject obj = HelloNew();
  3092.      p = SOM_Resolve(obj, Hello, sayHello);
  3093.      ((somTD_Hello_sayHello)p) (obj, somGetGlobalEnvironment());
  3094.  
  3095.  SOM_Resolve and SOM_ResolveNoCheck can only be used to obtain method 
  3096.  procedures for static methods  (methods that have been declared in an IDL 
  3097.  specification for a class) and not methods that are added to a class at run 
  3098.  time. See the System Object Model Programming Reference for more information 
  3099.  and examples on SOM_Resolve and SOM_ResolveNoCheck. 
  3100.  
  3101.  
  3102. ΓòÉΓòÉΓòÉ 4.2.3.6.2. Name-lookup method resolution ΓòÉΓòÉΓòÉ
  3103.  
  3104. To obtain a pointer to a method's procedure using name-lookup  resolution, use 
  3105. the somResolveByName procedure (described in the following section), or any of 
  3106. the somLookupMethod, somFindMethod and somFindMethodOK methods. These methods 
  3107. are invoked on a class object that supports the desired method, and they take 
  3108. an argument specifying the a somId for the desired method (which can be 
  3109. obtained from the method's name using the somIdFromString function). For more 
  3110. information on these methods and for examples of their use, see the System 
  3111. Object Model Programming Reference. 
  3112.  
  3113.  
  3114. ΓòÉΓòÉΓòÉ 4.2.3.7. Method name or signature not known at compile time ΓòÉΓòÉΓòÉ
  3115.  
  3116. If the programmer does not know a method's name at compile time (for example, 
  3117. it might be specified by user input), then the method can be invoked in one of 
  3118. two ways, depending upon whether its signature is known: 
  3119.  
  3120.      Suppose the signature of the method is known at compile time (even though 
  3121.       the method name is not). In that case, when the name of the method 
  3122.       becomes available at run time, the somLookupMethod, somFindMethod or 
  3123.       somFindMethodOk methods or the somResolveByName procedure can be used to 
  3124.       obtain a pointer to the method's procedure using name-lookup method 
  3125.       resolution, as described in the preceding topics. That method procedure 
  3126.       can then be invoked, passing the method's intended receiver, the 
  3127.       Environment pointer (if needed), the context argument (if needed), and 
  3128.       the remainder of the method's arguments. 
  3129.  
  3130.      If the method's signature is unknown until run time, then 
  3131.       dispatch-function resolution is indicated, as described in the next 
  3132.       topic. 
  3133.  
  3134.  
  3135. ΓòÉΓòÉΓòÉ 4.2.3.7.1. Dispatch-function method resolution ΓòÉΓòÉΓòÉ
  3136.  
  3137. If the signature of the method is not known at compile time (and hence the 
  3138. method's argument list cannot be constructed until run time), then the method 
  3139. can be invoked at run time by (a) placing the arguments in a variable of type 
  3140. va_list at run time and (b) either using the somGetMethodData method followed 
  3141. by use of the somApply function, or by invoking the somDispatch or 
  3142. somClassDispatch method. Using somApply is more efficient, since this is what 
  3143. the somDispatch method does, but it requires two steps instead of one. In 
  3144. either case, the result invokes a "stub" procedure called an apply stub, whose 
  3145. purpose is to remove the method arguments from the va_list, and then pass them 
  3146. to the appropriate method procedure in the way expected by that procedure. For 
  3147. more information on these methods and for examples of their use, see the 
  3148. somApply function, and the somGetMethodData, somDispatch, and somClassDispatch 
  3149. methods in the System Object Model Programming Reference. 
  3150.  
  3151.  
  3152. ΓòÉΓòÉΓòÉ 4.2.4. Using class objects ΓòÉΓòÉΓòÉ
  3153.  
  3154. Using a class object encompasses three aspects: getting the class of an object, 
  3155. creating a new class object, or simply referring to a class object through the 
  3156. use of a pointer. 
  3157.  
  3158.  
  3159. ΓòÉΓòÉΓòÉ 4.2.4.1. Getting the class of an object ΓòÉΓòÉΓòÉ
  3160.  
  3161. To get the class that an object is an instance of, SOM provides a method called 
  3162. somGetClass. The somGetClass method takes an object as its only argument and 
  3163. returns a pointer to the class object of which it is an instance. For example, 
  3164. the following statements store in "myClass" the class object of which "obj" is 
  3165. an instance. 
  3166.  
  3167. myClass = _somGetClass(obj);  (for C)
  3168. myClass = obj->somGetClass();  (for C++)
  3169.  
  3170. Getting the class of an object is useful for obtaining information about the 
  3171. object; in some cases, such information cannot be obtained directly from the 
  3172. object, but only from its class. The section below entitled "Getting 
  3173. information about a class" describes the methods that can be invoked on a class 
  3174. object after it is obtained using somGetClass. 
  3175.  
  3176. The somGetClass method can be overridden by a class to provide enhanced or 
  3177. alternative semantics for its objects. Because it is usually important to 
  3178. respect the intended semantics of a class of objects, the somGetClass method 
  3179. should normally be used to access the class of an object. 
  3180.  
  3181. In a few special cases, it is not possible to make a method call on an object 
  3182. in order to determine its class. For such situations, SOM provides the 
  3183. SOM_GetClass  macro. In general, the somGetClass method and the SOM_GetClass 
  3184. macro may have different behavior (if somGetClass has been overridden). This 
  3185. difference may be limited to side effects, but it is possible for their results 
  3186. to differ as well. The SOM_GetClass macro should only be used when absolutely 
  3187. necessary. 
  3188.  
  3189.  
  3190. ΓòÉΓòÉΓòÉ 4.2.4.2. Creating a class object ΓòÉΓòÉΓòÉ
  3191.  
  3192. A class object is created automatically the first time the <className>New 
  3193. macro (for C) or the new operator (C++) is invoked to create an instance of 
  3194. that class. In other situations, however, it may be necessary to create a class 
  3195. object explicitly, as this section describes. 
  3196.  
  3197.  
  3198. ΓòÉΓòÉΓòÉ 4.2.4.2.1. Using <className>Renew or somRenew ΓòÉΓòÉΓòÉ
  3199.  
  3200. It is sometimes necessary to create a class object before creating any 
  3201. instances of the class. For example, creating instances using the <className> 
  3202. Renew macro or the somRenew method requires knowing how large the created 
  3203. instance will be, so that memory can be allocated for it. Getting this 
  3204. information requires creating the class object (see the example under "Creating 
  3205. instances of a class" early in this chapter). As another example, a class 
  3206. object must be explicitly created when a program does not use the SOM bindings 
  3207. for a class. Without SOM bindings for a class, its instances must be created 
  3208. using somNew or somRenew, and these methods require that the class object be 
  3209. created in advance. 
  3210.  
  3211. Use the <className>NewClass procedure to create a class object: 
  3212.  
  3213.      When using the C/C++ language bindings for the class, and 
  3214.  
  3215.      When the name of the class is known at compile time. 
  3216.  
  3217.  
  3218. ΓòÉΓòÉΓòÉ 4.2.4.2.2. Using <className>NewClass ΓòÉΓòÉΓòÉ
  3219.  
  3220. The <className>NewClass procedure initializes the SOM run-time environment, if 
  3221. necessary, creates the class object (unless it already exists), creates class 
  3222. objects for the ancestor classes and metaclass of the class, if necessary, and 
  3223. returns a pointer to the newly created class object. After its creation, the 
  3224. class object can be referenced in client code using the macro 
  3225.  
  3226.  _<className>                            (for C and C++ programs) 
  3227.  
  3228.  or the expression 
  3229.  
  3230.  <className>ClassData.classObject        (for C and C++ programs). 
  3231.  
  3232.  The <className>NewClass procedure takes two arguments, the major version 
  3233.  number and minor version number of the class. These numbers are checked 
  3234.  against the version numbers built into the class library to determine if the 
  3235.  class is compatible with the client's expectations. The class is compatible if 
  3236.  it has the same major version number and the same or a higher minor version 
  3237.  number. If the class is not compatible, an error is raised. Major version 
  3238.  numbers usually only change when a significant enhancement or incompatible 
  3239.  change is made to a class. Minor version numbers change when minor 
  3240.  enhancements or fixes are made. Downward compatibility is usually maintained 
  3241.  across changes in the minor version number. Zero can be used in place of 
  3242.  version numbers to bypass version number checking. 
  3243.  
  3244.  When using SOM bindings for a class, these bindings define constants 
  3245.  representing the major and minor version numbers of the class at the time the 
  3246.  bindings were generated. These constants are named <className>_MajorVersion 
  3247.  and <className>_MinorVersion. For example, the following procedure call: 
  3248.  
  3249.      AnimalNewClass(Animal_MajorVersion, Animal_MinorVersion);
  3250.  
  3251.  creates the class object for class "Animal". Thereafter, _Animal can be used 
  3252.  to reference the "Animal" class object. 
  3253.  
  3254.  The preceding technique for checking version numbers is not failsafe. For 
  3255.  performance reasons, the version numbers for a class are only checked when the 
  3256.  class object is created, and not when the class object or its instances are 
  3257.  used. Thus, run-time errors may result when usage bindings for a particular 
  3258.  version of a class are used to invoke methods on objects created by an earlier 
  3259.  version of the class. 
  3260.  
  3261.  
  3262. ΓòÉΓòÉΓòÉ 4.2.4.2.3. Using somFindClass or somFindClsInFile ΓòÉΓòÉΓòÉ
  3263.  
  3264. To create a class object when  not using the C/C++  language bindings for the 
  3265. class, or when the class name is not known at compile time: 
  3266.  
  3267.      First, initialize the SOM run-time environment by calling the 
  3268.       somEnvironmentNew function (unless it is known that the SOM run-time 
  3269.       environment has already been initialized). 
  3270.  
  3271.      Then, use the somFindClass or somFindClsInFile method to create the class 
  3272.       object. (The class must already be defined in a dynamically linked 
  3273.       library, or DLL.) 
  3274.  
  3275.  The somEnvironmentNew function initializes the SOM run-time environment. That 
  3276.  is, it creates the four primitive SOM objects (SOMClass, SOMObject, 
  3277.  SOMClassMgr, and the SOMClassMgrObject), and it initializes SOM global 
  3278.  variables. The function takes no arguments and returns a pointer to the 
  3279.  SOMClassMgrObject. 
  3280.  
  3281.  Note:  Although somEnvironmentNew must be called before using other SOM 
  3282.         functions and methods, explicitly calling somEnvironmentNew is usually 
  3283.         not necessary when using the C/C++ bindings,  because the macros for 
  3284.         <className>NewClass,  <className>New , and <className>Renew call it 
  3285.         automatically, as does the new operator for C++. Calling 
  3286.         somEnvironmentNew repeatedly does no harm. 
  3287.  
  3288.  After the SOM run-time environment has been initialized, the methods 
  3289.  somFindClass and somFindClsInFile can be used to create a class object. These 
  3290.  methods must be invoked on the class manager, which is pointed to by the 
  3291.  global variable SOMClassMgrObject.  (It is also returned as the result of 
  3292.  somEnvironmentNew.) 
  3293.  
  3294.  The somFindClass method takes the following arguments: 
  3295.  
  3296.  classId                  A somId identifying the name of the class to be 
  3297.                           created. The somIdFromString function returns a 
  3298.                           classId  given the name of the class. 
  3299.  
  3300.  major version number     The expected major version number of the class. 
  3301.  
  3302.  minor version number     The expected minor version number of the class. 
  3303.  
  3304.  The version numbers are checked against the version numbers built into the 
  3305.  class library to determine if the class is compatible with the client's 
  3306.  expectations. 
  3307.  
  3308.  The somFindClass  method dynamically loads the DLL containing the class's 
  3309.  implementation, if needed, creates the class object (unless it already exists) 
  3310.  by invoking its <className>NewClass procedure, and returns a pointer to it. If 
  3311.  the class could not be created, somFindClass returns NULL. For example, the 
  3312.  following C code fragment creates the class "Hello" and stores a pointer to it 
  3313.  in "myClass": 
  3314.  
  3315.      SOMClassMgr cm = somEnvironmentNew();
  3316.      somId classId = somIdFromString("Hello");
  3317.      SOMClass myClass = _somFindClass(SOMClassMgrObject, classId
  3318.                             Hello_MajorVersion, Hello_MinorVersion);
  3319.      ...
  3320.      SOMFree(classId);
  3321.  
  3322.  The somFindClass method uses somLocateClassFile to get the name of the library 
  3323.  file containing the class. If the class was defined with a "dllname" class 
  3324.  modifier, then somLocateClassFile returns that file name; otherwise, it 
  3325.  assumes that the class name is the name of the library file. The 
  3326.  somFindClsInFile method is similar to somFindClass, except that it takes an 
  3327.  additional (final) argument-the name of the library file containing the class. 
  3328.  The somFindClsInFile method is useful when a class is packaged in a DLL along 
  3329.  with other classes and the "dllname" class modifier has not been given in the 
  3330.  class's IDL specification. 
  3331.  
  3332.  Warning:  On AIX, the somFindClass and somFindClsInFile methods should not  be 
  3333.  used to create a class whose implementation is statically linked with the 
  3334.  client program. Instead, the class object should be created using the 
  3335.  <className>NewClass procedure provided by the class's .h/.xh header file. 
  3336.  Static linkage is not created by including usage bindings in a program, but by 
  3337.  use of the offset-resolution method-invocation macros. 
  3338.  
  3339.  Invoking methods without corresponding class usage bindings 
  3340.  
  3341.  This topic builds on the preceding discussion, and illustrates how a client 
  3342.  program can apply dynamic SOM mechanisms to utilize classes and objects for 
  3343.  which specific usage bindings are not available. This process can be applied 
  3344.  when a class implementor did not ship the C/C++ language bindings. 
  3345.  Furthermore, the process allows more programming flexibility, because it is 
  3346.  not necessary to know the class and method names at compile time in order to 
  3347.  access them at run time. (At run time, however, you must be able to provide 
  3348.  the method arguments, either explicitly or via a va_list, and provide a 
  3349.  generalized way to handle return values.) As an example application, a 
  3350.  programmer might create an online class viewer that can access many classes 
  3351.  without requiring usage bindings for all those classes, and the person using 
  3352.  the viewer can select class names at run time. 
  3353.  
  3354.  As another aspect of flexibility, a code sequence similar to the following C++ 
  3355.  example could be re-used to access any class or method. After getting the 
  3356.  somId for a class name, the example uses the somFindClass method to create the 
  3357.  class object. The somNew method is then invoked to create an instance of the 
  3358.  specified class, and the somDispatch method is used to invoke a method on the 
  3359.  object. 
  3360.  
  3361.   #include <stdio.h>
  3362.   #include <somcls.xh>
  3363.  
  3364.   int main()
  3365.   {
  3366.           SOMClass *classobj;
  3367.           somId tempId;
  3368.           somId methId;
  3369.           SOMObject *s2;
  3370.           Environment * main_ev = somGetGlobalEnvironment();
  3371.  
  3372.           tempId = SOM_IdFromString("myClassName");
  3373.           classobj = SOMClassMgrObject->somFindClass(tempId,0,0);
  3374.           SOMFree(tempId);
  3375.  
  3376.           if (NULL==classobj)
  3377.           {
  3378.                   printf("somFindClass could not find the selected class\n");
  3379.           }
  3380.           else
  3381.           {
  3382.                   s2 = (SOMObject *) (classobj->somNew());
  3383.                   methId = somIdFromString("sayHello");
  3384.                   if (s2->somDispatch((somToken *) 0, methId, s2, ev))
  3385.  
  3386.                           printf("Method successfully called.\n");
  3387.           }
  3388.  
  3389.           return 0;
  3390.   }
  3391.  
  3392.  
  3393. ΓòÉΓòÉΓòÉ 4.2.4.3. Referring to class objects ΓòÉΓòÉΓòÉ
  3394.  
  3395. Saving a pointer as the class object is created: The <className>NewClass macro 
  3396. and the somFindClass method, used to create class objects, both return a 
  3397. pointer to the newly created class object. Hence, one way to obtain a pointer 
  3398. to a class object is to save the value returned by <className>NewClass or 
  3399. somFindClass  when the class object is created. 
  3400.  
  3401. Getting a pointer after the class object is created: After a class object has 
  3402. been created, client programs can also get a pointer to the class object from 
  3403. the class name. When the class name is known at compile time and the client 
  3404. program is using the C or C++ language bindings, the macro 
  3405.  
  3406. _<className> 
  3407.  
  3408. can be used to refer to the class object for <className>. Also, when the class 
  3409. name is known at compile time and the client program is using the C or C++ 
  3410. language bindings, the expression 
  3411.  
  3412. <className>ClassData.classObject 
  3413.  
  3414. refers to the class object for <className>. For example, _Hello refers to the 
  3415. class object for class "Hello" in C or C++ programs, and 
  3416. HelloClassData.classObject refers to the class object for class "Hello." in C 
  3417. or C++ programs. 
  3418.  
  3419. Getting a pointer to the class object from an instance:  If any instances of 
  3420. the class are known to exist, a pointer to the class object can also be 
  3421. obtained by invoking the somGetClass method on such an instance. (See "Getting 
  3422. the class of an object," above.) 
  3423.  
  3424. Getting a pointer in other situations: If the class name is not known until run 
  3425. time, or if the client program is not using the C or C++ language bindings, and 
  3426. no instances of the class are known to exist, then the somClassFromId method 
  3427. can be used to obtain a pointer to a class object after the class object has 
  3428. been created. The somClassFromId method should be invoked on the class manager, 
  3429. which is pointed to by the global variable SOMClassMgrObject. The only argument 
  3430. to the method is a somId for the class name, which can be obtained using the 
  3431. somIdFromString function. The method somClassFromId returns a pointer to the 
  3432. class object of the specified class. For example, the following C code stores 
  3433. in "myClass" a pointer to the class object for class "Hello" (or NULL, if the 
  3434. class cannot be located): 
  3435.  
  3436.    SOMClassMgr cm = somEnvironmentNew();
  3437.    somId classId = somIdFromString("Hello");
  3438.    SOMClass myClass =_somClassFromId(SOMClassMgrObject,classId
  3439.                           Hello_MajorVersion, Hello_MinorVersion);
  3440.    SOMFree(classId);
  3441.  
  3442.  
  3443. ΓòÉΓòÉΓòÉ 4.2.5. Compiling and linking ΓòÉΓòÉΓòÉ
  3444.  
  3445. This section describes how to compile and link C and C++ client programs. 
  3446. Compiling and linking a client program with a SOM class is done in one of two 
  3447. ways, depending on how the class is packaged. 
  3448.  
  3449. Note: If you are building an application that uses a combination of C and C++ 
  3450. compiled object modules, then the C++ linker must be used to link them. 
  3451.  
  3452. If the class is not packaged as a library (that is, the client program has the 
  3453. implementation source code for the class, as in the examples given in the SOM 
  3454. IDL tutorial), then the client program can be compiled together with the class 
  3455. implementation file as follows. (This assumes that the client program and the 
  3456. class are both implemented in the same language, C or C++. If this is not the 
  3457. case, then each module must be compiled separately to produce an object file 
  3458. and the resulting object files linked together to form an executable.) 
  3459.  
  3460. In the following examples, the environment variable SOMBASE refers to the 
  3461. directory in which SOM has been installed. The examples also assume that the 
  3462. header files and the import library for the "Hello" class reside in the 
  3463. "include" and "lib" directories where SOM has been installed.  If this is not 
  3464. the case, additional path information should be supplied for these files. For 
  3465. client program "main" and class "Hello": 
  3466.  
  3467. Under AIX, for C programmers: 
  3468.  
  3469.    > xlc -I. -I$SOMBASE/include main.c hello.c -L$SOMBASE/lib -lsomtk \
  3470.          -o main
  3471.  
  3472. Under AIX, for C++ programmers: 
  3473.  
  3474.    > xlC -I. -I$SOMBASE/include main.C hello.C -L$SOMBASE/lib -lsomtk \
  3475.          -o main
  3476.  
  3477. Under OS/2, for C programmers: 
  3478.  
  3479.    > set LIB=%SOMBASE%\lib;%LIB%
  3480.    > icc -I. -I%SOMBASE%\include main.c hello.c somtk.lib
  3481.  
  3482. Under OS/2, for C++ programmers: 
  3483.  
  3484.    > set LIB=%SOMBASE%\lib;%LIB%
  3485.    > icc -I. -I%SOMBASE%\include main.cpp hello.cpp somtk.lib
  3486.  
  3487. If the class is packaged as a class library, then the client program, "main", 
  3488. is compiled as above, except that the class implementation file is not part of 
  3489. the compilation. Instead, the "import library" provided with the class library 
  3490. is used to resolve the symbolic references that appear in "main". For example, 
  3491. to compile the C client program "main.c" that uses class "Hello": 
  3492.  
  3493. Under AIX: 
  3494.  
  3495.    > xlc -I. -I$SOMBASE/include main.c -lc -L$SOMBASE/lib -lsomtk \
  3496.          -lhello -o main
  3497.  
  3498. Under OS/2: 
  3499.  
  3500.    > set LIB=%SOMBASE%\lib;%LIB%
  3501.    > icc -I. -I%SOMBASE%\include main.c somtk.lib hello.lib
  3502.  
  3503.  
  3504. ΓòÉΓòÉΓòÉ 4.3. Language-neutral Methods and Functions ΓòÉΓòÉΓòÉ
  3505.  
  3506. This section describes methods, functions, and macros that client programs can 
  3507. use regardless of the programming language in which they are written. In other 
  3508. words, these functions and methods are not part of the C or C++ bindings. 
  3509.  
  3510.  
  3511. ΓòÉΓòÉΓòÉ 4.3.1. Generating output ΓòÉΓòÉΓòÉ
  3512.  
  3513. The following functions and methods are used to generate output, including 
  3514. descriptions of SOM objects. They all produce their output using the 
  3515. character-output procedure held by the global variable SOMOutCharRoutine. The 
  3516. default procedure for character output simply writes the character to stdout, 
  3517. but it can be replaced to change the output destination of the methods and 
  3518. functions below. (See Chapter 5 for more information on customizing SOM.) 
  3519.  
  3520.  somDumpSelf              (method) writes a detailed description of an object, 
  3521.                           including its class, its location, and its instance 
  3522.                           data. The receiver of the method is the object to be 
  3523.                           dumped. An additional argument is the "nesting level" 
  3524.                           for the description. [All lines in the description 
  3525.                           will be indented by (2 * level) spaces.] 
  3526.  
  3527.  somPrintSelf             (method) Writes a brief description of an object, 
  3528.                           including its class and location in memory. The 
  3529.                           receiver of the method is the object to be printed. 
  3530.  
  3531.  somPrintf                (function) SOM's version of the C "printf" function. 
  3532.                           It generates character stream output via 
  3533.                           SOMOutCharRoutine. It has the same interface as the C 
  3534.                           "printf" function. 
  3535.  
  3536.  somVprintf               (function) Represents the "vprint" form of somPrintf. 
  3537.                           Its arguments are a formatting string and a va_list 
  3538.                           holding the remaining arguments. 
  3539.  
  3540.  somPrefixLevel           (function) Generates (via somPrintf) spaces to prefix 
  3541.                           a line at the indicated level. The return type is 
  3542.                           void. The argument is an integer specifying the 
  3543.                           level. The number of spaces generated is (2 * level). 
  3544.  
  3545.  somLPrintf               (function) Combines somPrefixLevel and somPrintf. The 
  3546.                           first argument is the level of the description (as 
  3547.                           for somPrefixLevel) and the remaining arguments are 
  3548.                           as for somPrintf (or for the C "printf" function). 
  3549.  
  3550.  See the System Object Model Programming Reference for more information on a 
  3551.  specific function or method. 
  3552.  
  3553.  
  3554. ΓòÉΓòÉΓòÉ 4.3.2. Getting information about a class ΓòÉΓòÉΓòÉ
  3555.  
  3556. The following methods are used to obtain information about a class or to locate 
  3557. a particular class object: 
  3558.  
  3559.  somCheckVersion          Checks a class for compatibility with the specified 
  3560.                           major and minor version numbers. The receiver of the 
  3561.                           method is the SOM class about which information is 
  3562.                           needed. Additional arguments are values of the major 
  3563.                           and minor version numbers. The method returns TRUE if 
  3564.                           the class is compatible, or FALSE otherwise. 
  3565.  
  3566.  somClassFromId           Finds the class object of an existing class when 
  3567.                           given its somId, but without loading the class. The 
  3568.                           receiver of the method is the class manager (pointed 
  3569.                           to by the global variable SOMClassMgrObject). The 
  3570.                           additional argument is the class's somId. The method 
  3571.                           returns a pointer to the class (or NULL if the class 
  3572.                           does not exist). 
  3573.  
  3574.  somDescendedFrom         Tests whether one class is derived from another. The 
  3575.                           receiver of the method is the class to be tested, and 
  3576.                           the potential ancestor class is the argument. The 
  3577.                           method returns TRUE if the relationships exists, or 
  3578.                           FALSE otherwise. 
  3579.  
  3580.  somFindClass             Finds or creates the class object for a class, given 
  3581.                           the class's somId and its major and minor version 
  3582.                           numbers. The receiver of the method is the class 
  3583.                           manager (pointed to by the global variable 
  3584.                           SOMClassMgrObject). Additional arguments are the 
  3585.                           class's somId and the major and minor version 
  3586.                           numbers. The method returns a pointer to the class 
  3587.                           object, or NULL if the class could not be created. 
  3588.  
  3589.  somFindClsInFile         Finds or creates the class object for a class. This 
  3590.                           method is similar to somFindClass, except the user 
  3591.                           also provides the name of a file to be used for 
  3592.                           dynamic loading, if needed. The receiver of the 
  3593.                           method is the class manager (pointed to by the global 
  3594.                           variable SOMClassMgrObject). Additional arguments are 
  3595.                           the class's somId, the major and minor version 
  3596.                           numbers, and the file name. The method returns a 
  3597.                           pointer to the class object, or NULL if the class 
  3598.                           could not be created. 
  3599.  
  3600.  somGetInstancePartSize   Obtains the size of the instance variables introduced 
  3601.                           by a class. The receiver of the method is the class 
  3602.                           object. The method returns the amount of space, in 
  3603.                           bytes, needed for the instance variables. 
  3604.  
  3605.  somGetInstanceSize       Obtains the total size requirements for an instance 
  3606.                           of a class. The receiver of the method is the class 
  3607.                           object. The method returns the amount of space, in 
  3608.                           bytes, required for the instance variables introduced 
  3609.                           by the class itself and by all of its ancestor 
  3610.                           classes. 
  3611.  
  3612.  somGetName               Obtains the name of a class. The receiver of the 
  3613.                           method is the class object. The method returns the 
  3614.                           class name. 
  3615.  
  3616.  somGetNumMethods         Obtains the number of methods available for a class. 
  3617.                           The receiver of the method is the class object. The 
  3618.                           method returns the total number of currently 
  3619.                           available methods (static or otherwise, including 
  3620.                           inherited methods). 
  3621.  
  3622.  somGetNumStaticMethods   Obtains the number of static methods available for a 
  3623.                           class. (A static method is one declared in the 
  3624.                           class's interface specification [.idl] file.) The 
  3625.                           receiver of the method is the class object. The 
  3626.                           method returns the total number of available static 
  3627.                           methods, including inherited ones. 
  3628.  
  3629.  somGetParents            Obtains a sequence of the parent (base) classes of a 
  3630.                           specified class. The receiver of the method is the 
  3631.                           class object. The method returns a pointer to a 
  3632.                           linked list of the parent (base) classes (unless the 
  3633.                           receiver is SOMObject, for which it returns NULL). 
  3634.  
  3635.  somGetVersionNumbers     Obtains the major and minor version numbers of a 
  3636.                           class. The return type is void, and the two arguments 
  3637.                           are pointers to locations in memory where the method 
  3638.                           can store the major and minor version numbers (of 
  3639.                           type long). 
  3640.  
  3641.  somSupportsMethod        Indicates whether instances of a given class support 
  3642.                           a given method. The receiver of the somSupportsMethod 
  3643.                           method is the class object. The argument is the somId 
  3644.                           for the method in question. The somSupportsMethod 
  3645.                           method returns TRUE if the method is supported, or 
  3646.                           FALSE otherwise. 
  3647.  
  3648.  See the System Object Model Programming Reference for more information on a 
  3649.  specific method. 
  3650.  
  3651.  
  3652. ΓòÉΓòÉΓòÉ 4.3.3. Getting information about an object ΓòÉΓòÉΓòÉ
  3653.  
  3654. The following methods and functions are used to obtain information about an 
  3655. object (instance) or to determine whether a variable holds a valid SOM object. 
  3656.  
  3657.  
  3658. ΓòÉΓòÉΓòÉ 4.3.3.1. Methods ΓòÉΓòÉΓòÉ
  3659.  
  3660.  somGetClass              Gets the class object of a specified object. The 
  3661.                           receiver of the method is the object whose class is 
  3662.                           desired. The method returns a pointer to the object's 
  3663.                           corresponding class object. 
  3664.  
  3665.  somGetClassName          Obtains the class name of an object. The receiver of 
  3666.                           the method is the object whose class name is desired. 
  3667.                           The method returns a pointer to the name of the class 
  3668.                           of which the specified object is an instance. 
  3669.  
  3670.  somGetSize               Obtains the size of an object. The receiver of the 
  3671.                           method is the object. The method returns the amount 
  3672.                           of contiguous space, in bytes, that is needed to hold 
  3673.                           the object itself (not including any additional space 
  3674.                           that the object may be using or managing outside of 
  3675.                           this area). 
  3676.  
  3677.  somIsA                   Determines whether an object is an instance of a 
  3678.                           given class or of one of its descendant classes. The 
  3679.                           receiver of the method is the object to be tested. An 
  3680.                           additional argument is the name of the class to which 
  3681.                           the object will be compared. This method returns TRUE 
  3682.                           if the object is an instance of the specified class 
  3683.                           or if (unlike somIsInstanceOf) it is an instance of 
  3684.                           any descendant class of the given class; otherwise, 
  3685.                           the method returns FALSE. 
  3686.  
  3687.  somIsInstanceOf          Determines whether an object is an instance of a 
  3688.                           specific class (but not of any descendant class).The 
  3689.                           receiver of the method is the object. The argument is 
  3690.                           the name of the class to which the object will be 
  3691.                           compared. The method returns TRUE if the object is an 
  3692.                           instance of the specified class, or FALSE otherwise. 
  3693.  
  3694.  somRespondsTo            Determines whether an object supports a given method. 
  3695.                           The receiver of the method is the object. The 
  3696.                           argument is the somId for the method in question. (A 
  3697.                           somId can be obtained from a string by using the 
  3698.                           somIdFromString function.) The somRespondsTo method 
  3699.                           returns TRUE if the object supports the method, or 
  3700.                           FALSE otherwise. 
  3701.  
  3702.  
  3703. ΓòÉΓòÉΓòÉ 4.3.3.2. Functions ΓòÉΓòÉΓòÉ
  3704.  
  3705.  somIsObj                 Takes as its only argument an address (which may not 
  3706.                           be valid). The function returns TRUE (1) if the 
  3707.                           address contains a valid SOM object, or FALSE (0) 
  3708.                           otherwise. This function is designed to be failsafe. 
  3709.  
  3710.  See the System Object Model Programming Reference for more information on a 
  3711.  specific method or function. 
  3712.  
  3713.  
  3714. ΓòÉΓòÉΓòÉ 4.3.4. Debugging ΓòÉΓòÉΓòÉ
  3715.  
  3716. The following macros are used to conditionally generate output for debugging. 
  3717. All output generated by these macros is written using the replaceable 
  3718. character-output procedure pointed to by the global variable SOMOutCharRoutine. 
  3719. The default procedure simply writes the character to stdout, but it can be 
  3720. replaced to change the output destination of the methods and functions below. 
  3721. (See Chapter 5 for more information on customizing SOM.) 
  3722.  
  3723. Debugging output is produced or suppressed based on the settings of three 
  3724. global variables, SOM_TraceLevel, SOM_WarnLevel, and SOM_AssertLevel: 
  3725.  
  3726.      SOM_TraceLevel controls the behavior of the <className>MethodDebug macro; 
  3727.  
  3728.      SOM_WarnLevel controls the behavior of the macros SOM_WarnMsg, SOM_TestC, 
  3729.       and SOM_Expect; and 
  3730.  
  3731.      SOM_AssertLevel controls the behavior of the SOM_Assert macro. 
  3732.  
  3733.  Available macros for generating debugging output are as follows: 
  3734.  
  3735.  <className>MethodDebug   (macro for C and C++ programmers using the SOM 
  3736.                           language bindings for <className>) 
  3737.                           The arguments to this macro are a class name and a 
  3738.                           method name. If the SOM_TraceLevel global variable 
  3739.                           has a nonzero value, the <className>MethodDebug macro 
  3740.                           produces a message each time the specified method (as 
  3741.                           defined by the specified class) is executed. This 
  3742.                           macro is typically used within the procedure that 
  3743.                           implements the specified method. (The SOM Compiler 
  3744.                           automatically generates calls to the 
  3745.                           <className>MethodDebug macro within the 
  3746.                           implementation template files it produces.) u To 
  3747.                           suppress method tracing for all methods of a class, 
  3748.                           put the following statement in the implementation 
  3749.                           file after including the header file for the class: 
  3750.  
  3751.                                                     #define <className>MethodDebug(c,m) \
  3752.                                                                        SOM_NoTrace(c,m)
  3753.  
  3754.                           This can yield a slight performance improvement. The 
  3755.                           SOMMTraced metaclass, discussed below, provides a 
  3756.                           more extensive tracing facility that includes method 
  3757.                           parameters and returned values. 
  3758.  
  3759.  SOM_TestC                The SOM_TestC macro takes as an argument a boolean 
  3760.                           expression. If the boolean expression is TRUE 
  3761.                           (nonzero) and SOM_AssertLevel is greater than zero, 
  3762.                           then an informational message is output. If the 
  3763.                           expression is FALSE (zero) and SOM_WarnLevel is 
  3764.                           greater than zero, a warning message is produced. 
  3765.  
  3766.  SOM_WarnMsg              The SOM_WarnMsg macro takes as an argument a 
  3767.                           character string. If the value of SOM_WarnLevel is 
  3768.                           greater than zero, the specified message is output. 
  3769.  
  3770.  SOM_Assert               The SOM_Assert macro takes as arguments a boolean 
  3771.                           expression and an error code (an integer). If the 
  3772.                           boolean expression is TRUE (nonzero) and 
  3773.                           SOM_AssertLevel  is greater than zero, then an 
  3774.                           informational message is output. If the expression is 
  3775.                           FALSE (zero), and the error code indicates a 
  3776.                           warning-level error and SOM_WarnLevel is greater than 
  3777.                           zero, then a warning message is output. If the 
  3778.                           expression is FALSE and the error code indicates a 
  3779.                           fatal error, then an error message is produced and 
  3780.                           the process is terminated. 
  3781.  
  3782.  SOM_Expect               The SOM_Expect macro takes as an argument a boolean 
  3783.                           expression. If the boolean expression is FALSE (zero) 
  3784.                           and SOM_WarnLevel is set to be greater than zero, 
  3785.                           then a warning message is output. If condition is 
  3786.                           TRUE and SOM_AssertLevel is set to be greater than 
  3787.                           zero, then an informational message is output. 
  3788.  
  3789.  See the System Object Model Programming Reference for more information on a 
  3790.  specific macro. 
  3791.  
  3792.  The somDumpSelf and somPrintSelf methods can be useful in testing and 
  3793.  debugging. The somPrintSelf method produces a brief description of an object, 
  3794.  and the somDumpSelf method produces a more detailed description. See the 
  3795.  System Object Model Programming Reference for more information. 
  3796.  
  3797.  
  3798. ΓòÉΓòÉΓòÉ 4.3.5. Checking the validity of method calls ΓòÉΓòÉΓòÉ
  3799.  
  3800. The C and C++ language bindings include code to check the validity of method 
  3801. calls at run time. If a validity check fails, the SOM_Error macro ends the 
  3802. process. (SOM_Error is described below.) To enable method-call validity 
  3803. checking, place the following directive in the client program prior to any 
  3804. #include directives for SOM header files: 
  3805.  
  3806. #define SOM_TestOn
  3807.  
  3808. Alternatively, the -DSOM_TestOn option can be used when compiling the client 
  3809. program to enable method-call validity checking. 
  3810.  
  3811.  
  3812. ΓòÉΓòÉΓòÉ 4.3.6. Exceptions and error handling ΓòÉΓòÉΓòÉ
  3813.  
  3814. In the classes provided in the SOM run-time library (that is, SOMClass, 
  3815. SOMObject, and SOMClassMgr), error handling is performed by a user-replaceable 
  3816. procedure, pointed to by the global variable SOMError, that produces an error 
  3817. message and an error code and, if appropriate ate, ends the process where the 
  3818. error occurred. (Chapter 5 describes how to customize the error handling 
  3819. procedure.) 
  3820.  
  3821. Each error is assigned a unique integer error code. Errors are grouped into 
  3822. three categories, based on the last digit of the error code: 
  3823.  
  3824.  SOM_Ignore               This category of error represents an informational 
  3825.                           event. The event is considered normal and can be 
  3826.                           ignored or logged at the user's discretion. Error 
  3827.                           codes having a last digit of 2 belong to this 
  3828.                           category. 
  3829.  
  3830.  SOM_Warn                 This category of error represents an unusual 
  3831.                           condition that is not a normal event, but is not 
  3832.                           severe enough to require program termination. Error 
  3833.                           codes having a last digit of 1 belong to this 
  3834.                           category. 
  3835.  
  3836.  SOM_Fatal                This category of error represents a condition that 
  3837.                           should not occur or that would result in loss of 
  3838.                           system integrity if processing were allowed to 
  3839.                           continue. In the default error handling procedure, 
  3840.                           these errors cause the termination of the process in 
  3841.                           which they occur. Error codes having a last digit of 
  3842.                           9 belong to this category. 
  3843.  
  3844.  The various codes for all errors detected by SOM are listed in Appendix A, 
  3845.  "Customer Support and Error Codes." 
  3846.  
  3847.  When errors are encountered in client programs or user defined-classes, the 
  3848.  following two macros can be used to invoke the error-handling procedure: 
  3849.  
  3850.  SOM_Error                The SOM_Error macro takes an error code as its only 
  3851.                           argument and invokes the SOM error handling procedure 
  3852.                           (pointed to by the global variable SOMError) to 
  3853.                           handle the error. The default error handling 
  3854.                           procedure prints a message that includes the error 
  3855.                           code, the name of the source file, and the line 
  3856.                           number where the macro was invoked. If the last digit 
  3857.                           of the error code indicates a serious error (of 
  3858.                           category SOM_Fatal), the process causing the error is 
  3859.                           terminated. (Chapter 5 describes how to customize the 
  3860.                           error handling procedure.) 
  3861.  
  3862.  SOM_Test                 The SOM_Test macro takes a boolean expression as an 
  3863.                           argument. If the expression is TRUE (nonzero) and the 
  3864.                           SOM_AssertLevel is greater than zero, then an 
  3865.                           informational message is output. If the expression is 
  3866.                           FALSE (zero), an error message is produced and the 
  3867.                           program is terminated. 
  3868.  
  3869.  See the System Object Model Programming Reference for more information on a 
  3870.  specific macro. 
  3871.  
  3872.  Other classes provided by the SOMobjects Toolkit (including those in the 
  3873.  Persistence, Replication, DSOM, and Interface Repository frameworks, and the 
  3874.  utility classes and metaclasses) handle errors differently. Rather than 
  3875.  invoking SOMError with an error code, their methods return exceptions via the 
  3876.  (Environment *) inout parameter required by these methods. The following 
  3877.  sections describe the exception declarations, the standard exceptions, and how 
  3878.  to set and get exception information in an Environment structure. 
  3879.  
  3880.  
  3881. ΓòÉΓòÉΓòÉ 4.3.6.1. Exception declarations ΓòÉΓòÉΓòÉ
  3882.  
  3883. As discussed in Chapter 4 in the section entitled "SOM Interface Definition 
  3884. Language," a method may be declared to return zero or more exceptions. IDL 
  3885. exceptions are implemented by simply passing back error information after a 
  3886. method call, as opposed to the "catch/throw" model where an exception is 
  3887. implemented by a long jump or signal. Associated with each type of exception is 
  3888. a name, and optionally, a struct-like data structure for holding error 
  3889. information. A method declares the types of exceptions it may return in a 
  3890. raises expression. 
  3891.  
  3892. Below is an example IDL declaration of a "BAD_FLAG" exception, which may be 
  3893. "raised" by a"checkFlag" method, as part of a "MyObject" interface: 
  3894.  
  3895.    interface MyObject {
  3896.       exception BAD_FLAG { long ErrCode; char Reason[80];}
  3897.  
  3898.       void checkFlag(in unsigned long flag) raises(BAD_FLAG);
  3899.    };
  3900.  
  3901. An exception structure contains whatever information is necessary to help the 
  3902. caller understand the nature of the error. The exception declaration can be 
  3903. treated like a struct definition:  i.e., whatever you can access in an IDL 
  3904. struct, you can access in an exception declaration. Alternatively, the 
  3905. structure can be empty, whereby the exception is just identified by its name. 
  3906.  
  3907. The SOM Compiler will map the exception declaration in the above example to the 
  3908. following C language constructs: 
  3909.  
  3910.    typedef struct BAD_FLAG {
  3911.       long ErrCode;
  3912.       char Reason[80];
  3913.    } BAD_FLAG;
  3914.  
  3915.    #define ex_BAD_FLAG "MyObject::BAD_FLAG"
  3916.  
  3917. When an exception is detected, the "checkFlag" method must call SOMMalloc to 
  3918. allocate a "BAD_FLAG" structure, initialize it with the appropriate error 
  3919. information, and make a call to somSetException (see "Setting an exception 
  3920. value," below) to record the exception value in the Environment structure 
  3921. passed in the method call. The caller, after invoking "checkFlag", can check 
  3922. the Environment structure that was passed to the method to see if there was an 
  3923. exception, and if so, extract the exception value from the Environment (see 
  3924. "Getting an exception value," below.) 
  3925.  
  3926.  
  3927. ΓòÉΓòÉΓòÉ 4.3.6.2. Standard exceptions ΓòÉΓòÉΓòÉ
  3928.  
  3929. In addition to user-defined exceptions (those defined explicitly in an IDL 
  3930. file), there are several predefined exceptions for system run-time errors. A 
  3931. system exception  can be returned on any method call. (That is, they are 
  3932. implicitly declared for every method whose class uses IDL call style, and they 
  3933. do not appear in any raises expressions.) The standard exceptions are listed in 
  3934. Table 2 of Section 4.2, "SOM Interface Definition Language". Most of the 
  3935. predefined system exceptions pertain to Object Request Broker errors. 
  3936. Consequently, these types of exceptions are most likely to occur in DSOM 
  3937. applications (Chapter 6). 
  3938.  
  3939. Each of the standard exceptions has the same structure: an error code (to 
  3940. designate the subcategory of the exception) and a completion status code. For 
  3941. example, the NO_MEMORY standard exception has the following definition: 
  3942.  
  3943.    enum completion_status {YES, NO, MAYBE};
  3944.    exception NO_MEMORY { unsigned long minor;
  3945.                          completion_status completed; };
  3946.  
  3947. The completion status value indicates whether the method was never initiated 
  3948. (NO), completed execution prior to the exception (YES), or the completion 
  3949. status is indeterminate (MAYBE). 
  3950.  
  3951. Since all the standard exceptions have the same structure, file "somcorba.h" 
  3952. (included by "som.h") defines a generic StExcep typedef which can be used 
  3953. instead of the specific typedefs: 
  3954.  
  3955.    typedef struct StExcep {
  3956.         unsigned long minor;
  3957.         completion_status completed;
  3958.    } StExcep;
  3959.  
  3960. The standard exceptions are defined in an IDL module called StExcep, in the 
  3961. file named "stexcep.idl", and the C definitions can be found in "stexcep.h". 
  3962.  
  3963.  
  3964. ΓòÉΓòÉΓòÉ 4.3.6.3. The Environment ΓòÉΓòÉΓòÉ
  3965.  
  3966. The Environment is a data structure that contains environmental information 
  3967. that can be passed between a caller and a called object when a method is 
  3968. executed. For example, it is used to pass information about the user id of a 
  3969. client, to return exception data to the client following a method call, and so 
  3970. on. 
  3971.  
  3972. A pointer to an Environment variable is passed as an argument to method calls 
  3973. (unless the method's class has the callstyle=oidl SOM IDL modifier). The 
  3974. Environment typedef is defined in "som.h", and an instance of the structure is 
  3975. allocated by the caller in any reasonable way: on  the stack (by declaring a 
  3976. local variable and initializing it using the macro SOM_InitEnvironment), 
  3977. dynamically (using the SOM_CreateLocalEnvironment macro), or by calling the 
  3978. somGetGlobalEnvironment function to allocate an Environment structure to be 
  3979. shared by objects running in the same thread. 
  3980.  
  3981. For class libraries that use callstyle=oidl, there is no explicit Environment 
  3982. parameter. For these libraries, exception information may be passed using the 
  3983. per-thread Environment structure returned by the somGetGlobalEnvironment 
  3984. procedure. 
  3985.  
  3986.  
  3987. ΓòÉΓòÉΓòÉ 4.3.6.4. Setting an exception value ΓòÉΓòÉΓòÉ
  3988.  
  3989. To set an exception value in the caller's Environment structure, a method 
  3990. implementation makes a call to the somSetException procedure: 
  3991.  
  3992.    void  somSetException ( Environment *ev,
  3993.                                exception_type major,
  3994.                                string exception_name,
  3995.                                void *params);
  3996.  
  3997. where "ev" is a pointer to the Environment structure passed to the method, 
  3998. "major" is an exception_type, "exception_name" is the string name of the 
  3999. exception (usually the constant defined by the IDL compiler, for example, 
  4000. ex_BAD_FLAG), and "params"  is a pointer to an (initialized) exception 
  4001. structure which must be allocated by SOMMalloc: 
  4002.  
  4003.    typedef enum exception_type {
  4004.       NO_EXCEPTION, USER_EXCEPTION, SYSTEM_EXCEPTION
  4005.    } exception_type;
  4006.  
  4007. It is important to reiterate that somSetException expects the params argument 
  4008. to be a pointer to a structure that was allocated using SOMMalloc. When 
  4009. somSetException is called, the client passes ownership of the exception 
  4010. structure to the SOM run-time environment. The SOM run-time  environment will 
  4011. free the structure when the exception is reset (that is, upon the next call to 
  4012. somSetException), or when the somExceptionFree procedure is called. 
  4013.  
  4014. Note that somSetException simply sets the exception value; it performs no exit 
  4015. processing. If there are multiple calls to somSetException before the method 
  4016. returns, the caller will only see the last exception value. 
  4017.  
  4018.  
  4019. ΓòÉΓòÉΓòÉ 4.3.6.5. Getting an exception value ΓòÉΓòÉΓòÉ
  4020.  
  4021. After a method returns, the calling client program can look at the Environment 
  4022. structure to see if there was an exception. The Environment struct is mostly 
  4023. opaque, except for an exception type field named _major: 
  4024.  
  4025.    typedef struct Environment {
  4026.       exception_type   _major;
  4027.       ...
  4028.    } Environment;
  4029.  
  4030. If ev._major != NO_EXCEPTION, there was an exception returned by the call. The 
  4031. caller can retrieve the exception name and value (passed as parameters in the 
  4032. somSetException call) from an Environment struct via the following functions: 
  4033.  
  4034. string somExceptionId (Environment *ev); 
  4035. somToken somExceptionValue (Environment *ev); 
  4036.  
  4037. The somExceptionId function returns the exception name, if any, as a string. 
  4038. The function somExceptionValue returns a pointer to the value of the exception, 
  4039. if any, contained in the exception structure. If NULL is passed as the 
  4040. Environment pointer in either of the above calls, an implicit call is made to 
  4041. somGetGlobalEnvironment. 
  4042.  
  4043. The somExceptionFree procedure will free any memory in the Environment 
  4044. associated with the last exception: 
  4045.  
  4046. void  somExceptionFree (Environment *ev); 
  4047.  
  4048. If preferred, developers can alternatively use the CORBA "exception_free" API 
  4049. to free the memory in an Environment structure. 
  4050.  
  4051. Note: File "somcorba.h" (included by "som.h") provides the following aliases 
  4052. for strict compliance with CORBA programming interfaces: 
  4053.  
  4054.    #ifdef CORBA_FUNCTION_NAMES
  4055.    #define exception_id    somExceptionId
  4056.    #define exception_value somExceptionValue
  4057.    #define exception_free  somExceptionFree
  4058.    #endif /* CORBA_FUNCTION_NAMES */
  4059.  
  4060.  
  4061. ΓòÉΓòÉΓòÉ 4.3.6.6. Example ΓòÉΓòÉΓòÉ
  4062.  
  4063. Let us define an IDL interface for a "MyObject" object, which declares a 
  4064. "BAD_FLAG" exception, which can be raised by the "checkFlag"method, in a file 
  4065. called "myobject.idl": 
  4066.  
  4067.    interface MyObject {
  4068.      exception BAD_FLAG { long ErrCode;   char Reason[80]; }
  4069.  
  4070.      void checkFlag(in unsigned long flag) raises(BAD_FLAG);
  4071.    };
  4072.  
  4073. The SOM IDL compiler will map the exception to the following C language 
  4074. constructs, in myobject.h: 
  4075.  
  4076.    typedef struct BAD_FLAG {
  4077.       long ErrCode;
  4078.       char Reason[80];
  4079.    } BAD_FLAG;
  4080.  
  4081.    #define ex_BAD_FLAG "MyObject::BAD_FLAG"
  4082.  
  4083. A client program that invokes the "checkFlag" method might contain the 
  4084. following error handling code.  (Note: The error checking code below lies in 
  4085. the user-written procedure, "ErrorCheck," so the code need not be replicated 
  4086. through the program.) 
  4087.  
  4088.    #include "som.h"
  4089.    #include "myobject.h"
  4090.    boolean ErrorCheck(Environment *ev);   /* prototype */
  4091.  
  4092.    main()
  4093.    {
  4094.        unsigned long flag;
  4095.        Environment ev;
  4096.        MyObject myobj;
  4097.        char     *exId;
  4098.        BAD_FLAG *badFlag;
  4099.        StExcep  *stExValue;
  4100.  
  4101.        myobj = MyObjectNew();
  4102.        flag  = 0x01L;
  4103.        SOM_InitEnvironment(&ev);
  4104.  
  4105.         /* invoke the checkFlag method, passing the Environment param */
  4106.        _checkFlag(myobj, &ev, flag);
  4107.  
  4108.        /* check for exception */
  4109.        if (ErrorCheck(&ev))
  4110.        {
  4111.           /* ... */
  4112.           somExceptionFree(&ev);   /* free the exception memory */
  4113.        }
  4114.  
  4115.        /* ... */
  4116.    }
  4117.  
  4118.    /* error checking procedure */
  4119.    boolean ErrorCheck(Environment *ev)
  4120.    {
  4121.      switch (ev._major)
  4122.      {
  4123.      case SYSTEM_EXCEPTION:
  4124.        /* get system exception id and value */
  4125.        exId      =  somExceptionId(ev);
  4126.        stExValue =  somExceptionValue(ev);
  4127.        /* ... */
  4128.        return( TRUE);
  4129.  
  4130.      case USER_EXCEPTION:
  4131.        /* get user-defined exception id and value */
  4132.        exId =  somExceptionId(ev);
  4133.        if (strcmp(exId, ex_BAD_FLAG) == 0)
  4134.        {
  4135.           badFlag = (BAD_FLAG *)  somExceptionValue(ev);
  4136.           /* ... */
  4137.        }
  4138.        /* ... */
  4139.        return( TRUE);
  4140.  
  4141.      case NO_EXCEPTION:
  4142.        return( FALSE);
  4143.      }
  4144.    }
  4145.  
  4146. The implementation of the "checkFlag" method might contain the following 
  4147. error-handling code: 
  4148.  
  4149.    #include "som.h"
  4150.    #include "myobject.h"
  4151.  
  4152.    void  checkFlag(MyObject somSelf, Environment *ev,
  4153.                    unsigned long flag)
  4154.    {
  4155.       BAD_FLAG *badFlag;
  4156.       /* ... */
  4157.  
  4158.       if ( /* flag is invalid */ )
  4159.       {
  4160.          badFlag = (BAD_FLAG *) SOMMalloc(sizeof(BAD_FLAG));
  4161.          badFlag->ErrCode = /* bad flag code */;
  4162.          strcpy(badFlag->Reason, "bad flag was passed");
  4163.          somSetException(ev, USER_EXCEPTION,
  4164.                          ex_BAD_FLAG, (void *)badFlag);
  4165.  
  4166.          return;
  4167.       }
  4168.       /* ... */
  4169.    }
  4170.  
  4171.  
  4172. ΓòÉΓòÉΓòÉ 4.3.7. Memory management ΓòÉΓòÉΓòÉ
  4173.  
  4174. The memory management functions used by SOM are a subset of those supplied in 
  4175. the ANSI C standard library. They have the same calling interface and the same 
  4176. return types as their ANSI C equivalents, but include supplemental error 
  4177. checking. Errors detected by these functions are passed to SOMError (described 
  4178. in the previous section). The correspondence between SOM memory management 
  4179. functions and their ANSI C standard library equivalents is shown below: 
  4180.  
  4181. ΓöîΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÉ
  4182. ΓöéSOM FUNCTION                       ΓöéEQUIVALENT ANSI C LIBRARY ROUTINE  Γöé
  4183. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  4184. ΓöéSOMMalloc                          Γöémalloc                             Γöé
  4185. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  4186. ΓöéSOMCalloc                          Γöécalloc                             Γöé
  4187. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  4188. ΓöéSOMRealloc                         Γöérealloc                            Γöé
  4189. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  4190. ΓöéSOMFree                            Γöéfree                               Γöé
  4191. ΓööΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÿ
  4192.  
  4193. SOMMalloc, SOMCalloc, SOMRealloc, and SOMFree are actually global variables 
  4194. that point to the SOM memory management functions (rather than being the names 
  4195. of the functions themselves), so that users can replace them with their own 
  4196. memory management functions if desired. (See chapter 5 for a discussion of 
  4197. replacing the SOM memory management functions.) 
  4198.  
  4199. Clearing memory for objects 
  4200.  
  4201. The memory associated with objects initialized by a client program must also be 
  4202. freed by the client.  The SOM-provided method somFree  is used to release the 
  4203. storage containing the receiver object: 
  4204.  
  4205.  #include "origcls.h"
  4206.  
  4207. main ()
  4208. {
  4209.    OrigCls myObject;
  4210.    myObject = OrigClsNew ();
  4211.  
  4212.     /*  Code to use myObject  */
  4213.     _somFree (myObject);
  4214. {
  4215.  
  4216. Clearing memory for the Environment 
  4217.  
  4218. Any memory associated with an exception in an Environment structure is 
  4219. typically freed using the somExceptionFree function. (Or, the CORBA 
  4220. "exception_free" API can be used.) The somExceptionFree function takes the 
  4221. following form (also see "Example" in the previous topic for an application 
  4222. example): 
  4223.  
  4224.   void somExceptionFree(Environment *ev);
  4225.  
  4226. Note: For information on managing the memory, objects, and exceptions used by 
  4227. DSOM applications, see "Memory management" in Chapter 6, "Distributed SOM 
  4228. (DSOM)." 
  4229.  
  4230.  
  4231. ΓòÉΓòÉΓòÉ 4.3.8. SOM manipulations using somId's ΓòÉΓòÉΓòÉ
  4232.  
  4233. A somId is similar to a number that represents a zero-terminated string. A 
  4234. somId is used in SOM to identify method names, class names, and so forth. For 
  4235. example, many of the SOM methods that take a method or class name as a 
  4236. parameter require a value of type somId rather than string. All SOM 
  4237. manipulations using somIds are case insensitive, although the original case of 
  4238. the string is preserved. 
  4239.  
  4240. During its first use with any of the following functions, a somId is 
  4241. automatically converted to an internal representation (registered). Because the 
  4242. representation of a somId changes, a special SOM type (somId) is provided for 
  4243. this purpose. Names and the corresponding somId can be declared at compile 
  4244. time, as follows: 
  4245.  
  4246.    string example = "exampleMethodName";
  4247.    somId exampleId = &example;
  4248.  
  4249. or a somId can be generated at run time, as follows: 
  4250.  
  4251.    somId myMethodId;
  4252.    myMethodId = somIdFromString("exampleMethodName");
  4253.  
  4254. SOM provides the following functions that generate or use a somId: 
  4255.  
  4256.  somIdFromString          Finds the somId that corresponds to a string. The 
  4257.                           method takes a string as its argument, and returns a 
  4258.                           value of type somId that represents the string. The 
  4259.                           returned somId must later be freed using SOMFree. 
  4260.  
  4261.  somStringFromId          Obtains the string that corresponds to a somId. The 
  4262.                           function takes a somId as its argument and returns 
  4263.                           the string that the somId represents. 
  4264.  
  4265.  somCompareIds            Determines whether two somId values are the same 
  4266.                           (that is, represent the same string). This function 
  4267.                           takes two somId values as arguments. It returns TRUE 
  4268.                           (1) if the somIds represent the same string, or FALSE 
  4269.                           (0) otherwise. 
  4270.  
  4271.  somCheckId               Determines whether SOM already knows a somId. The 
  4272.                           function takes a somId as its argument. It verifies 
  4273.                           whether the somId is registered and in normal form, 
  4274.                           registers it if necessary, and returns the input 
  4275.                           somId. 
  4276.  
  4277.  somRegisterId            The same as somCheckId, except it returns TRUE (1) if 
  4278.                           this is the first time the somId has been registered, 
  4279.                           or FALSE (0) otherwise. 
  4280.  
  4281.  somUniqueKey             Finds the unique key for a somId. The function takes 
  4282.                           a somId identifier as its argument, and returns the 
  4283.                           unique key for the somId-a number that uniquely 
  4284.                           represents the string that the somId represents. This 
  4285.                           key is the same as the key for another somId if and 
  4286.                           only if the other somId refers to the same string as 
  4287.                           the input somId. 
  4288.  
  4289.  somTotalRegIds           Finds the total number of somIds that have been 
  4290.                           registered, as an unsigned long. This function is 
  4291.                           used to determine an appropriate argument to 
  4292.                           somSetExpectedIds, below, in later executions of the 
  4293.                           program. The function takes no input arguments. 
  4294.  
  4295.  somSetExpectedIds        Indicates how many unique somIds SOM can expect to 
  4296.                           use during program execution, which, if accurate, can 
  4297.                           improve the space and time utilization of the program 
  4298.                           slightly. This routine must be called before the SOM 
  4299.                           run-time environment is initialized (that is, before 
  4300.                           the function somEnvironmentNew is invoked and before 
  4301.                           any objects are created). This is the only SOM 
  4302.                           function that can be invoked before the SOM run-time 
  4303.                           environment is initialized. The input argument is an 
  4304.                           unsigned long. The function has no return value. 
  4305.  
  4306.  somBeginPersistentIds and somEndPersistentIds Delimit a time interval for the 
  4307.                           current thread during which it is guaranteed that (a) 
  4308.                           any new somIds that are created will refer only to 
  4309.                           static strings and (b) these strings will not be 
  4310.                           subsequently modified or freed. These functions are 
  4311.                           useful because somIds that are registered within a 
  4312.                           "persistent ID interval" can be handled more 
  4313.                           efficiently. 
  4314.  
  4315.  See the System Object Model Programming Reference for more information on a 
  4316.  specific function. 
  4317.  
  4318.  
  4319. ΓòÉΓòÉΓòÉ 5. SOM IDL and the SOM Compiler ΓòÉΓòÉΓòÉ
  4320.  
  4321. This chapter first discusses how to define SOM classes and then describes the 
  4322. SOM Compiler. To allow a class of objects to be implemented in one programming 
  4323. language and used in another (that is, to allow a SOM class to be language 
  4324. neutral), the interface to objects of this class must be specified separately 
  4325. from the objects' implementation. 
  4326.  
  4327. To summarize:  As a first step, a file known as the .idl file is used to 
  4328. declare classes and their methods, using SOM's language#neutral Interface 
  4329. Definition Language (IDL). Next, the SOM Compiler is run on the .idl file to 
  4330. produce a template implementation file that contains stub method procedures for 
  4331. the new and overridden methods; this preliminary code corresponds to the 
  4332. computer language that will implement the class. Then, the class implementer 
  4333. fills in the stub procedures with code that implements the methods (or 
  4334. redefines overridden methods) and sets instance data. (This implementation 
  4335. process is the subject of Chapter 5, "Implementing Classes in SOM.") At this 
  4336. point, the implementation file can be compiled and linked with a client program 
  4337. that uses it (as described in Chapter 3, "Using SOM Classes in Client 
  4338. Programs"). 
  4339.  
  4340. Syntax for SOM IDL and the SOM Compiler are presented in this chapter, along 
  4341. with helpful information for using them correctly. 
  4342.  
  4343.  
  4344. ΓòÉΓòÉΓòÉ 5.1. Interface vs Implementation ΓòÉΓòÉΓòÉ
  4345.  
  4346. The interface to a class of objects contains the information that a client must 
  4347. know to use an object-namely, the names of its attributes and the signatures of 
  4348. its methods.  The interface is described in a formal language independent of 
  4349. the programming language used to implement the object's methods. In SOM, the 
  4350. formal language used to define object interfaces is the Interface Definition 
  4351. Language (IDL), standardized by CORBA. 
  4352.  
  4353. The implementation of a class of objects (that is, the procedures that 
  4354. implement methods) is written in the implementer's preferred programming 
  4355. language. This language can be object-oriented (for instance, C++) or 
  4356. procedural (for instance, C). 
  4357.  
  4358. A completely implemented class definition, then, consists of two main files: 
  4359.  
  4360.      An IDL specification of the interface to instances of the class (the 
  4361.       interface definition file (or .idl file) and 
  4362.  
  4363.      Method procedures written in the implementer's language of choice (the 
  4364.       implementation file). 
  4365.  
  4366.  The interface definition file has an .idl extension, as noted. The 
  4367.  implementation file, however, has an extension specific to the language in 
  4368.  which it is written. For example, implementations written in C have a .c 
  4369.  extension, and implementations written in C++ have a .C (for AIX) or .cpp (for 
  4370.  OS/2) extension. 
  4371.  
  4372.  To assist users in implementing SOM classes, the SOMobjects Toolkit provides a 
  4373.  SOM Compiler. The SOM Compiler takes as input an object interface definition 
  4374.  file  (the .idl file) and produces a set of binding files that make it 
  4375.  convenient to implement and use a SOM class whose instances are objects that 
  4376.  support the defined interface. The binding files and their purposes are as 
  4377.  follows: 
  4378.  
  4379.      An implementation template that serves as a guide for how the 
  4380.       implementation file for the class should look. The class implementer 
  4381.       fills in this template file with language-specific code to implement the 
  4382.       methods that are available on the class' instances. 
  4383.  
  4384.      Header files to be included (a) in the class's implementation file and 
  4385.       (b) in client programs that use the class. 
  4386.  
  4387.  These binding files produced by the SOM Compiler bridge the gap between  SOM 
  4388.  and the object model used in object-oriented languages (such as C++), and they 
  4389.  allow SOM to be used with non-object-oriented languages (such as C). The SOM 
  4390.  Compiler currently produces binding files for the C and C++ programming 
  4391.  languages. SOM can also be used with other programming languages; the bindings 
  4392.  simply offer a more convenient programmer's interface to SOM. Vendors of other 
  4393.  languages may also offer SOM bindings; check with your language vendor for 
  4394.  possible SOM support. 
  4395.  
  4396.  The subsequent sections of this chapter provide full syntax for SOM IDL and 
  4397.  the SOM Compiler. 
  4398.  
  4399.  
  4400. ΓòÉΓòÉΓòÉ 5.2. SOM Interface Definition Language ΓòÉΓòÉΓòÉ
  4401.  
  4402. This section describes the syntax of SOM's Interface Definition Language (SOM 
  4403. IDL). SOM IDL complies with CORBA's standard for IDL; it also adds constructs 
  4404. specific to SOM. (For more information on the CORBA standard for IDL, see The 
  4405. Common Object Request Broker: Architecture and Specification, published by 
  4406. Object Management Group and x/Open.) The full grammar for SOM IDL is given in 
  4407. Appendix C. Instructions for converting existing OIDL-syntax files to IDL are 
  4408. given in Appendix B. The current section describes the syntax and semantics of 
  4409. SOM IDL using the following conventions: 
  4410.  
  4411.       Constants (words to be used literally, such as keywords) appear in bold. 
  4412.       User-supplied elements appear in italics. 
  4413.       { }       Groups related items together as a single item. 
  4414.  
  4415.       [ ]       Encloses an optional item. 
  4416.  
  4417.       *         Indicates zero or more repetitions of the preceding item. 
  4418.  
  4419.       +         Indicates one or more repetitions of the preceding item. 
  4420.  
  4421.       |         Separates alternatives. 
  4422.  
  4423.       _         Within a set of alternatives, an underscore indicates the 
  4424.                 default, if defined. 
  4425.  
  4426.  IDL is a formal language used to describe object interfaces. Because, in SOM, 
  4427.  objects are implemented as instances of classes, an IDL object interface 
  4428.  definition specifies for a class of objects what methods (operations) are 
  4429.  available, their return types, and their parameter types. For this reason, we 
  4430.  often speak of an IDL specification for a class (as opposed to simply an 
  4431.  object interface). Constructs specific to SOM discussed below further 
  4432.  strengthen this connection between SOM classes and the IDL language. 
  4433.  
  4434.  IDL generally follows the same lexical rules as C and C++, with some 
  4435.  exceptions. In particular: 
  4436.  
  4437.      IDL uses the ISO Latin-1 (8859.1) character set (as per the CORBA 
  4438.       standard). 
  4439.  
  4440.      White space is ignored except as token delimiters. 
  4441.  
  4442.      C and C++ comment styles are supported. 
  4443.  
  4444.      IDL supports standard C/C++ preprocessing, including macro substitution, 
  4445.       conditional compilation, and source file inclusion. 
  4446.  
  4447.      Identifiers (user-defined names for methods, attributes, instance 
  4448.       variables, and so on) are composed of alphanumeric and underscore 
  4449.       characters, (with the first character alphabetic) and can be of arbitrary 
  4450.       length, up to an operating-system limit of about 250 characters. 
  4451.  
  4452.      Identifiers must be spelled consistently with respect to case throughout 
  4453.       a specification. 
  4454.  
  4455.      Identifiers that differ only in case yield a compilation error. 
  4456.  
  4457.      There is a single name space for identifiers (thus, using the same 
  4458.       identifier for a constant and a class name within the same naming scope, 
  4459.       for example, yields a compilation error). 
  4460.  
  4461.      Integer, floating point, character, and string literals are defined just 
  4462.       as in C and C++. 
  4463.  
  4464.  The terms listed in the Keywords table are reserved keywords and may not be 
  4465.  used otherwise. Keywords must be spelled using upper- and lower-case 
  4466.  characters exactly as shown in the table. For example, "void" is correct, but 
  4467.  "Void" yields a compilation error. 
  4468.  
  4469.  A typical IDL specification for a single class, residing in a single .idl 
  4470.  file, has the following form. (Also see the later section, "Module 
  4471.  declarations to define multiple interfaces in an .idl file.") The order is 
  4472.  unimportant, except that names must be declared (or forward referenced) before 
  4473.  they are referenced. The subsequent topics of this section describe the 
  4474.  requirements for these specifications: 
  4475.  
  4476.  Include directives       (optional) 
  4477.  
  4478.  Type declarations        (optional) 
  4479.  
  4480.  Constant declarations    (optional) 
  4481.  
  4482.  Exception declarations   (optional) 
  4483.  
  4484.  Interface declaration    (optional) 
  4485.  
  4486.  Module declaration       (optional) 
  4487.  
  4488.                           Keywords for SOM IDL 
  4489.  
  4490.                                                     ΓöîΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÉ
  4491.                                                     Γöéany                      ΓöéFALSE                    Γöéreadonly                 Γöé
  4492.                                                     Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  4493.                                                     Γöéattribute                Γöéfloat                    Γöésequence                 Γöé
  4494.                                                     Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  4495.                                                     Γöéboolean                  Γöéimplementation           Γöéshort                    Γöé
  4496.                                                     Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  4497.                                                     Γöécase                     Γöéin                       Γöéstring                   Γöé
  4498.                                                     Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  4499.                                                     Γöéchar                     Γöéinout                    Γöéstruct                   Γöé
  4500.                                                     Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  4501.                                                     Γöéclass                    Γöéinterface                Γöéswitch                   Γöé
  4502.                                                     Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  4503.                                                     Γöéconst                    Γöélong                     ΓöéTRUE                     Γöé
  4504.                                                     Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  4505.                                                     Γöécontext                  Γöémodule                   ΓöéTypeCode                 Γöé
  4506.                                                     Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  4507.                                                     Γöédefault                  Γöéoctet                    Γöétypedef                  Γöé
  4508.                                                     Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  4509.                                                     Γöédouble                   Γöéoneway                   Γöéunsigned                 Γöé
  4510.                                                     Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  4511.                                                     Γöéenum                     Γöéout                      Γöéunion                    Γöé
  4512.                                                     Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  4513.                                                     Γöéexception                Γöéraises                   Γöévoid                     Γöé
  4514.                                                     ΓööΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÿ
  4515.  
  4516.  
  4517. ΓòÉΓòÉΓòÉ 5.2.1. Include directives ΓòÉΓòÉΓòÉ
  4518.  
  4519. The IDL specification for a class normally contains #include statements that 
  4520. tell the SOM Compiler where to find the interface definitions (the .idl files) 
  4521. for: 
  4522.  
  4523.      Each of the class's parent (direct base) classes, and 
  4524.      The class's metaclass (if specified). 
  4525.  
  4526.  The #include statements must appear in the above order. For example, if class 
  4527.  "C" has parents "foo" and "bar" and metaclass "meta", then file "C.idl" must 
  4528.  begin with the following #include statements: 
  4529.  
  4530.      #include <foo.idl>
  4531.      #include <bar.idl>
  4532.      #include <meta.idl>
  4533.  
  4534.  As in C and C++, if a filename is enclosed in angle brackets (< >), the search 
  4535.  for the file will begin in system-specific locations. If the filename appears 
  4536.  in double quotation marks (" "), the search for the file will begin in the 
  4537.  current working directory, then move to the system-specific locations. 
  4538.  
  4539.  
  4540. ΓòÉΓòÉΓòÉ 5.2.2. Type and constant declarations ΓòÉΓòÉΓòÉ
  4541.  
  4542. IDL specifications may include type declarations and constant declarations as 
  4543. in C and C++, with the restrictions/extensions described below.  [Note: For any 
  4544. reader not familiar with C, a recommended reference is The C Programming 
  4545. Language (2nd edition, 1988, Prentice Hall) by Brian W. Kernighan and Dennis M. 
  4546. Ritchie. See pages 36-40 for a discussion of type and constant declarations.] 
  4547.  
  4548. IDL supports the following basic types (these basic types are also defined for 
  4549. C and C++ client and implementation programs, using the SOM bindings): 
  4550.  
  4551.  
  4552. ΓòÉΓòÉΓòÉ 5.2.2.1. Integral types ΓòÉΓòÉΓòÉ
  4553.  
  4554. IDL supports only the integral types short,  long, unsigned short, and unsigned 
  4555. long, which represent the following value ranges: 
  4556.  
  4557.  short                    -2[15] .. 2[15]-1 
  4558.  long                     -2[31] .. 2[31]-1 
  4559.  unsigned short           0 .. 2[16]-1 
  4560.  unsigned long            0 .. 2[32]-1 
  4561.  
  4562.  
  4563. ΓòÉΓòÉΓòÉ 5.2.2.2. Floating point types ΓòÉΓòÉΓòÉ
  4564.  
  4565. IDL supports the float and double floating-point types. The float type 
  4566. represents the IEEE single-precision floating-point numbers; double represents 
  4567. the IEEE double-precision floating-point numbers. 
  4568.  
  4569.  
  4570. ΓòÉΓòÉΓòÉ 5.2.2.3. Character type ΓòÉΓòÉΓòÉ
  4571.  
  4572. IDL supports a char type, which represents an 8-bit quantity. The ISO Latin-1 
  4573. (8859.1) character set defines the meaning and representation of graphic 
  4574. characters. The meaning and representation of null and formatting characters is 
  4575. the numerical value of the character as defined in the ASCII (ISO 646) 
  4576. standard. Unlike C/C++, type char cannot be qualified as signed or unsigned. 
  4577. (The octet type, below, can be used in place of unsigned char.) 
  4578.  
  4579.  
  4580. ΓòÉΓòÉΓòÉ 5.2.2.4. Boolean type ΓòÉΓòÉΓòÉ
  4581.  
  4582. IDL supports a boolean type for data items that can take only the values TRUE 
  4583. and FALSE. 
  4584.  
  4585.  
  4586. ΓòÉΓòÉΓòÉ 5.2.2.5. Octet type ΓòÉΓòÉΓòÉ
  4587.  
  4588. IDL supports an octet type, an 8-bit quantity guaranteed not to undergo 
  4589. conversion when transmitted by the communication system. The octet type can be 
  4590. used in place of the unsigned char type. 
  4591.  
  4592.  
  4593. ΓòÉΓòÉΓòÉ 5.2.2.6. Any type ΓòÉΓòÉΓòÉ
  4594.  
  4595. IDL supports an any type, which permits the specification of values of any IDL 
  4596. type. In the SOM C and C++ bindings, the any type is mapped onto the following 
  4597. struct: 
  4598.  
  4599.    typedef struct any {
  4600.        TypeCode _type;
  4601.        void *_value;
  4602.    } any;
  4603.  
  4604. The "_value" member for an any type is a pointer to the actual value. The 
  4605. "_type" member is a pointer to an instance of a TypeCode that represents the 
  4606. type of the value. The TypeCode provides functions for obtaining information 
  4607. about an IDL type. Chapter 7, "The Interface Repository Framework," describes 
  4608. TypeCodes and their associated functions. 
  4609.  
  4610.  
  4611. ΓòÉΓòÉΓòÉ 5.2.2.7. Constructed types ΓòÉΓòÉΓòÉ
  4612.  
  4613. In addition to the above basic types, IDL also supports three constructed 
  4614. types: struct, union, and enum. The structure and enumeration types are 
  4615. specified in IDL the same as they are in C and C++ [Kernighan-Ritchie 
  4616. references: struct, p. 128; union, p. 147; enum, p. 39], with the following 
  4617. restrictions: 
  4618.  
  4619.       Unlike C/C++, recursive type specifications are allowed only through the 
  4620.       use of the sequence template type (see below). 
  4621.  
  4622.       Unlike C/C++, structures, discriminated unions, and enumerations in IDL 
  4623.       must be tagged. For example, "struct { int a; ... }" is an invalid type 
  4624.       specification. The tag introduces a new type name. 
  4625.  
  4626.       In IDL, constructed type definitions need not be part of a typedef 
  4627.       statement; furthermore, if they are part of a typedef statement, the tag 
  4628.       of the struct must differ from the type name being defined by the 
  4629.       typedef. For example, the following are valid IDL struct and enum 
  4630.       definitions: 
  4631.  
  4632.                struct myStruct {
  4633.                   long x;
  4634.                   double y;
  4635.                };                               /* defines type name myStruct*/
  4636.  
  4637.                enum colors { red, white, blue };  /* defines type name colors */
  4638.  
  4639.       By contrast, the following definitions are not valid: 
  4640.  
  4641.                typedef struct myStruct {        /*  NOT VALID  */
  4642.                   long x;
  4643.                   double y;
  4644.                } myStruct;                      /* myStruct has been redefined */
  4645.  
  4646.                typedef enum colors { red, white, blue } colors;  /* NOT VALID */
  4647.  
  4648.  The valid IDL struct and enum definitions shown above are translated by the 
  4649.  SOM Compiler into the following definitions in the C and C++ bindings, 
  4650.  assuming they were declared within the scope of interface "Hello": 
  4651.  
  4652.      typedef struct Hello_myStruct {  /* C/C++ bindings for IDL struct */
  4653.         long x;
  4654.         double y;
  4655.      } Hello_myStruct;
  4656.  
  4657.      typedef unsigned long Hello_colors; /* C/C++ bindings for IDL enum */
  4658.      #define Hello_red 1UL
  4659.      #define Hello_white 2UL
  4660.      #define Hello_blue 3UL
  4661.  
  4662.  When an enumeration is defined within an interface statement for a class, then 
  4663.  within C/C++ programs, the enumeration names must be referenced by prefixing 
  4664.  the class name. For example, if the colors enum, above, were defined within 
  4665.  the interface statement for class Hello, then the enumeration names would be 
  4666.  referenced as Hello_red, Hello_white, and Hello_blue. Notice the first 
  4667.  identifier in an enumeration is assigned the value 1. 
  4668.  
  4669.  All types and constants generated by the SOM Compiler are fully qualified. 
  4670.  That is, prepended to them is the fully qualified name of the interface or 
  4671.  module in which they appear.  For example, consider the following fragment of 
  4672.  IDL: 
  4673.  
  4674.      module M {
  4675.          typedef long long_t;
  4676.          module  N {
  4677.              typedef long long_t;
  4678.              interface I {
  4679.                  typedef long long_t;
  4680.              };
  4681.          };
  4682.      };
  4683.  
  4684.  That specification would generate the following three types: 
  4685.  
  4686.      typedef long  M_long_t;
  4687.      typedef long  M_N_long_t;
  4688.      typedef long  M_N_I_long_t;
  4689.  
  4690.  For programmer convenience, the SOM Compiler also generates shorter bindings, 
  4691.  without the interface qualification. Consider the next IDL fragment: 
  4692.  
  4693.      module M {
  4694.          typedef long long_t;
  4695.          module  N {
  4696.              typedef short short_t;
  4697.              interface I {
  4698.                  typedef char char_t;
  4699.              };
  4700.          };
  4701.      };
  4702.  
  4703.  In the C/C++ bindings of the preceding fragment, you can refer to "M_long_t" 
  4704.  as "long_t", to "M_N_short_t" as "short_t", and to "M_N_I_char_t" as "char_t". 
  4705.  
  4706.  However, these shorter forms are available only when their interpretation is 
  4707.  not ambiguous. Thus, in the first example the shorthand for "M_N_I_long_t" 
  4708.  would not be allowed, since it clashes with "M_long_t" and "M_N_long_t". If 
  4709.  these shorter forms are not required, they can be ignored by setting #define 
  4710.  SOM_DONT_USE_SHORT_NAMES before including the public header files, or by using 
  4711.  the SOM Compiler option -mnouseshort so that they are not generated in the 
  4712.  header files. 
  4713.  
  4714.  In the SOM documentation and samples, both long and short forms are 
  4715.  illustrated, for both type names and method calls. It is the responsibility of 
  4716.  each user to adopt a style according to personal preference. It should be 
  4717.  noted, however, that CORBA specifies that only the long forms must be present. 
  4718.  
  4719.  
  4720. ΓòÉΓòÉΓòÉ 5.2.2.7.1. Union type ΓòÉΓòÉΓòÉ
  4721.  
  4722. IDL also supports a union type, which is a cross between the C union and switch 
  4723. statements. The syntax of a union type declaration is as follows: 
  4724.  
  4725. union identifier switch ( switch-type )
  4726.   { case+ }
  4727.  
  4728. The "identifier" following the union keyword defines a new legal type. (Union 
  4729. types may also be named using a typedef declaration.) The "switch-type" 
  4730. specifies an integral, character, boolean, or enumeration type, or the name of 
  4731. a previously defined integral, boolean, character, or enumeration type. Each 
  4732. "case" of the union is specified with the following syntax: 
  4733.  
  4734. case-label+  type-spec  declarator ; 
  4735.  
  4736. where "type-spec" is any valid type specification; "declarator" is an 
  4737. identifier, an array declarator (such as, foo[3][5]), or a pointer declarator 
  4738. (such as, *foo); and each "case-label" has one of the following forms: 
  4739.  
  4740. case const-expr: 
  4741. default: 
  4742.  
  4743. The "const-expr" is a constant expression that must match or be automatically 
  4744. castable to the "switch-type". A default case can appear no more than once. 
  4745.  
  4746. Unions are mapped onto C/C++ structs. For example, the following IDL 
  4747. declaration: 
  4748.  
  4749.    union Foo switch (long) {
  4750.      case 1: long x;
  4751.      case 2: float y;
  4752.      default: char z;
  4753.    };
  4754.  
  4755. is mapped onto the following C struct: 
  4756.  
  4757.    typedef Hello_struct {
  4758.      long _d;
  4759.      union {
  4760.        long x;
  4761.        float y;
  4762.        char z;
  4763.      } _u;
  4764.    } Hello_foo;
  4765.  
  4766. The discriminator is referred to as "_d", and the union in the struct is 
  4767. referred to as "_u". Hence, elements of the union are referenced just as in C: 
  4768.  
  4769.    Foo v;
  4770.  
  4771.    /* get a pointer to Foo in v: */
  4772.    switch(v->_d) {
  4773.      case 1: printf("x = %ld\n", v->_u.x); break;
  4774.      case 2: printf("y = %f\n", v->_u.y); break;
  4775.      default: printf("z = %c\n", v->_u.z); break;
  4776.    }
  4777.  
  4778. Note: This example is from The Common Object Request Broker: Architecture and 
  4779. Specification, revision 1.1, page 90. 
  4780.  
  4781.  
  4782. ΓòÉΓòÉΓòÉ 5.2.2.8. Template types (sequences and strings) ΓòÉΓòÉΓòÉ
  4783.  
  4784. IDL defines two template types not found in C and C++: sequences and strings. A 
  4785. sequence is a one-dimensional array with two characteristics:  a maximum size 
  4786. (specified at compile time) and a length (determined at run time). Sequences 
  4787. permit passing unbounded arrays between objects. Sequences are specified as 
  4788. follows: 
  4789.  
  4790. sequence < simple-type [, positive-integer-const] > 
  4791.  
  4792. where "simple-type" specifies any valid IDL type, and the optional 
  4793. "positive-integer-const" is a constant expression that specifies the maximum 
  4794. size of the sequence (as a positive integer). 
  4795.  
  4796. Note: The "simple-type" cannot have a '*' directly in the sequence statement. 
  4797. Instead, a typedef for the pointer type must be used. For example, instead of: 
  4798.  
  4799.    typedef sequence<long *> seq_longptr; // Error: '*' not allowed.
  4800.  
  4801. use: 
  4802.  
  4803.    typedef long * longptr;
  4804.    typedef sequence<longptr> seq_longptr;  // Ok.
  4805.  
  4806. In SOM's C and C++ bindings, sequences  are mapped onto structs with the 
  4807. following members: 
  4808.  
  4809. unsigned long _maximum; 
  4810. unsigned long _length; 
  4811. simple-type *_buffer; 
  4812.  
  4813. where "simple-type" is the specified type of the sequence.  For example, the 
  4814. IDL declaration 
  4815.  
  4816.    typedef sequence<long, 10> vec10;
  4817.  
  4818. results in the following C struct: 
  4819.  
  4820.    #ifndef _IDL_SEQUENCE_long_defined
  4821.    #define _IDL_SEQUENCE_long_defined
  4822.    typedef struct {
  4823.        unsigned long _maximum;
  4824.        unsigned long _length;
  4825.        long *_buffer;
  4826.    } _IDL_SEQUENCE_long;
  4827.    #endif /* _IDL_SEQUENCE_long_defined */
  4828.    typedef _IDL_SEQUENCE_long vec10;
  4829.  
  4830. and an instance of this type is declared as follows: 
  4831.  
  4832.    vec10 v = {10L, 0L, (long *)NULL};
  4833.  
  4834. The "_maximum" member designates the actual size of storage allocated for the 
  4835. sequence, and the "_length" member designates the number of values contained in 
  4836. the "_buffer" member. For bounded sequences, it is an error to set the 
  4837. "_length" or "_maximum" member to a value larger than the specified bound of 
  4838. the sequence. 
  4839.  
  4840. Before a sequence is passed as the value of an "in" or "inout" method 
  4841. parameter, the "_buffer" member must point to an array of elements of the 
  4842. appropriate type, and the "_length" member must contain the number of elements 
  4843. to be passed. (If the parameter is "inout" and the sequence is unbounded, the 
  4844. "_maximum" member must also be set to the actual size of the array. Upon 
  4845. return, "_length" will contain the number of values copied into "_buffer", 
  4846. which must be less than "_maximum".) When a sequence is passed as an "out" 
  4847. method parameter or received as the return value, the method procedure 
  4848. allocates storage for "_buffer" as needed, the "_length" member contains the 
  4849. number of elements returned, and the "_maximum" member contains the number of 
  4850. elements allocated. (The client is responsible for subsequently freeing the 
  4851. memory pointed to by  "_buffer".) 
  4852.  
  4853. C and C++ programs using SOM's language bindings can refer to sequence types 
  4854. as: 
  4855.  
  4856. _IDL_SEQUENCE_type 
  4857.  
  4858. where "type" is the effective type of the sequence members. For example, the 
  4859. IDL type sequence<long,10> is referred to in a C/C++ program by the type name 
  4860. _IDL_SEQUENCE_long. If longint is defined via a typedef to be type long, then 
  4861. the IDL type sequence<longint,10> is also referred to by the type name 
  4862. _IDL_SEQUENCE_long. 
  4863.  
  4864. If the typedef is for a pointer type, then the effective type is the name of 
  4865. the pointer type. For example, the following statements define a C/C++ type 
  4866. _IDL_SEQUENCE_longptr and not _IDL_SEQUENCE_long: 
  4867.  
  4868.    typedef long * longptr;
  4869.    typedef sequence<longptr> seq_longptr;
  4870.  
  4871. A string is similar to a sequence of type char. It can contain all possible 
  4872. 8-bit quantities except NULL. Strings are specified as follows: 
  4873.  
  4874. string  [ < positive-integer-const > ] 
  4875.  
  4876. where the optional "positive-integer-const" is a constant expression that 
  4877. specifies the maximum size of the string (as a positive integer, which does not 
  4878. include the extra byte to hold a NULL as required in C/C++). In SOM's C and C++ 
  4879. bindings, strings are mapped onto zero-byte terminated character arrays. The 
  4880. length of the string is encoded by the position of the zero-byte. For example, 
  4881. the following IDL declaration: 
  4882.  
  4883.    typedef string<10> foo;
  4884.  
  4885. is converted to the following C/C++ typedef: 
  4886.  
  4887.    typedef char *foo;
  4888.  
  4889. A variable of this type is then declared as follows: 
  4890.  
  4891.    foo s = (char *) NULL;
  4892.  
  4893. C and C++ programs using SOM's language bindings can refer to string types by 
  4894. the type name string. 
  4895.  
  4896. When an unbounded string is passed as the value of an "inout" method parameter, 
  4897. the returned value is constrained to be no longer than the input value. Hence, 
  4898. using unbounded strings as "inout" parameters is not advised. 
  4899.  
  4900.  
  4901. ΓòÉΓòÉΓòÉ 5.2.2.9. Arrays ΓòÉΓòÉΓòÉ
  4902.  
  4903. Multidimensional, fixed-size arrays can be declared in IDL as follows: 
  4904.  
  4905. identifier {[ positive-integer-const ] }+ 
  4906.  
  4907. where the "positive-integer-const" is a constant expression that specifies the 
  4908. array size, in each dimension, as a positive integer. The array size is fixed 
  4909. at compile time. 
  4910.  
  4911.  
  4912. ΓòÉΓòÉΓòÉ 5.2.2.10. Pointers ΓòÉΓòÉΓòÉ
  4913.  
  4914. Although the CORBA standard for IDL does not include them, SOM IDL offers 
  4915. pointer types. Declarators of a pointer type are specified as in C and C++: 
  4916.  
  4917. type *declarator 
  4918.  
  4919. where "type" is a valid IDL type specification and "declarator" is an 
  4920. identifier or an array declarator. 
  4921.  
  4922.  
  4923. ΓòÉΓòÉΓòÉ 5.2.2.11. Object types ΓòÉΓòÉΓòÉ
  4924.  
  4925. The name of the interface to a class of objects can be used as a type. For 
  4926. example, if an IDL specification includes an interface declaration (described 
  4927. below) for a class (of objects)  "C1", then "C1" can be used as a type name 
  4928. within that IDL specification. When used as a type, an interface name indicates 
  4929. a pointer to an object that supports that interface. An interface name can be 
  4930. used as the type of a method argument, as a method return type, or as the type 
  4931. of a member of a constructed type (a struct, union, or enum). In all cases, the 
  4932. use of an interface name implicitly indicates a pointer to an object that 
  4933. supports that interface. 
  4934.  
  4935. As explained in Using SOM Classes in Client Programs, SOM's C usage bindings 
  4936. for SOM classes also follow this convention.  However, within SOM's C++ 
  4937. bindings, the pointer is made explicit, and the use of an interface name as a 
  4938. type refers to a class instance itself, rather than a pointer to a class 
  4939. instance. For example, to declare a variable "myobj" that is a pointer to an 
  4940. instance of class "Foo" in an IDL specification and in a C program, the 
  4941. following declaration is required: 
  4942.  
  4943.    Foo myobj;
  4944.  
  4945. However, in a C++ program, the following declaration is required: 
  4946.  
  4947.    Foo *myobj;
  4948.  
  4949. If a C programmer uses the SOM Compiler option -maddstar, then the bindings 
  4950. generated for C will also require an explicit '*' in declarations. Thus, 
  4951.  
  4952.  Foo myobj;               in IDL requires 
  4953.  
  4954.  Foo *myobj;              in both C and C++ programs 
  4955.  
  4956.  This style of bindings for C is permitted for two reasons: 
  4957.  
  4958.      It more closely resembles the bindings for C++, thus making it easier to 
  4959.       change to the C++ bindings at a later date; and 
  4960.  
  4961.      It is required for compatibility with existing SOM OIDL code. 
  4962.  
  4963.  Note: The same C and C++ binding emitters should not be run in the same SOM 
  4964.  Compiler command. For example, 
  4965.  
  4966.      sc "-sh;xh" cls.idl    // Not valid.
  4967.  
  4968.  If you wish to generate both C and C++ bindings, you should issue the commands 
  4969.  separately: 
  4970.  
  4971.      sc -sh cls.idl
  4972.      sc -sxh cls.idl
  4973.  
  4974.  
  4975. ΓòÉΓòÉΓòÉ 5.2.3. Exception declarations ΓòÉΓòÉΓòÉ
  4976.  
  4977. IDL specifications may include exception declarations, which define data 
  4978. structures to be returned when an exception occurs during the execution of a 
  4979. method. (IDL exceptions are implemented by simply passing back error 
  4980. information after a method call, as opposed to the "catch/throw" model where an 
  4981. exception is implemented by a long jump or signal.)  Associated with each type 
  4982. of exception is a name and, optionally, a struct-like data structure for 
  4983. holding error information. Exceptions are declared as follows: 
  4984.  
  4985. exception  identifier { member* }; 
  4986.  
  4987. The "identifier" is the name of the exception, and each "member" has the 
  4988. following form: 
  4989.  
  4990. type-spec declarators ; 
  4991.  
  4992. where "type-spec" is a valid IDL type specification and "declarators" is a list 
  4993. of identifiers, array declarators, or pointer declarators, delimited by commas. 
  4994. The members of an exception structure should contain information to help the 
  4995. caller understand the nature of the error. The exception declaration can be 
  4996. treated like a struct  definition; that is, whatever you can access in an IDL 
  4997. struct, you can access in an exception declaration.  Alternatively, the 
  4998. structure can be empty, whereby the exception is just identified by its name. 
  4999.  
  5000. If an exception is returned as the outcome of a method, the exception 
  5001. "identifier" indicates which exception occurred. The values of the members of 
  5002. the exception provide additional information specific to the exception. The 
  5003. topic "Method declarations" below describes how to indicate that a particular 
  5004. method may raise a particular exception, and Using SOM Classes in Client 
  5005. Programs, describes how exceptions are handled, in the section entitled 
  5006. "Exceptions and error handling." 
  5007.  
  5008. Following is an example declaration of a "BAD_FLAG" exception: 
  5009.  
  5010.    exception BAD_FLAG { long ErrCode; char Reason[80]; };
  5011.  
  5012. The SOM Compiler will map the above exception declaration to the following C 
  5013. language constructs: 
  5014.  
  5015.    #define ex_BAD_FLAG "::BAD_FLAG"
  5016.    typedef struct BAD_FLAG {
  5017.        long  ErrCode;
  5018.        char  Reason[80];
  5019.    } BAD_FLAG;
  5020.  
  5021. Thus, the ex_BAD_FLAG symbol can be used as a shorthand for naming the 
  5022. exception. 
  5023.  
  5024. An exception declaration within an interface "Hello", such as this: 
  5025.  
  5026.    interface Hello {
  5027.        exception LOCAL_EXCEPTION { long ErrCode; };
  5028.    };
  5029.  
  5030. would map onto: 
  5031.  
  5032.    #define ex_Hello_LOCAL_EXCEPTION "::Hello::LOCAL_EXCEPTION"
  5033.    typedef struct Hello_LOCAL_EXCEPTION {
  5034.        long  ErrCode;
  5035.    } Hello_LOCAL_EXCEPTION;
  5036.    #define ex_LOCAL_EXCEPTION ex_Hello_LOCAL_EXCEPTION
  5037.  
  5038. In addition to user-defined exceptions, there are several predefined exceptions 
  5039. for system run-time errors. The standard exceptions as prescribed by CORBA are 
  5040. shown in the table "Standard Exceptions Defined by CORBA". These exceptions 
  5041. correspond to standard run-time errors that may occur during the execution of 
  5042. any method (regardless of the list of exceptions listed in its IDL 
  5043. specification). 
  5044.  
  5045. Each of the standard exceptions has the same structure: an error code (to 
  5046. designate the subcategory of the exception) and a completion status code. For 
  5047. example, the NO_MEMORY standard exception has the following definition: 
  5048.  
  5049.    enum completion_status {YES, NO, MAYBE};
  5050.    exception NO_MEMORY { unsigned long minor;
  5051.                          completion_status completed; };
  5052.  
  5053. The "completion_status" value indicates whether the method was never initiated 
  5054. (NO), completed its execution prior to the exception (YES), or the completion 
  5055. status is indeterminate (MAYBE). 
  5056.  
  5057. Since all the standard exceptions have the same structure,  somcorba.h 
  5058. (included by som.h) defines a generic StExcep typedef which can be used instead 
  5059. of the specific typedefs: 
  5060.  
  5061.    typedef struct StExcep {
  5062.         unsigned long minor;
  5063.         completion_status completed;
  5064.    } StExcep;
  5065.  
  5066. The standard exceptions shown in the table "Standard Exceptions Defined by 
  5067. CORBA". are defined in an IDL module called StExcep, in the file called 
  5068. stexcep.idl, and the C definitions can be found in stexcep.h. 
  5069.  
  5070. Standard Exceptions Defined by CORBA 
  5071.  
  5072. module StExcep {
  5073.   #define ex_body { unsigned long minor; completion_status completed; }
  5074.  
  5075.   enum completion_status { YES, NO, MAYBE };
  5076.  
  5077.   enum exception_type {NO_EXCEPTION, USER_EXCEPTION, SYSTEM_EXCEPTION};
  5078.  
  5079.   exception UNKNOWN              ex_body;   // the unknown exception
  5080.   exception BAD_PARAM            ex_body;   // an invalid parameter was passed
  5081.   exception NO_MEMORY            ex_body;   // dynamic memory allocation failure
  5082.   exception IMP_LIMIT            ex_body;   // violated implementation limit
  5083.   exception COMM_FAILURE         ex_body;   // communication failure
  5084.   exception INV_OBJREF           ex_body;   // invalid object reference
  5085.   exception NO_PERMISSION        ex_body;   // no permission for attempted op.
  5086.   exception INTERNAL             ex_body;   // ORB internal error
  5087.   exception MARSHAL              ex_body;   // error marshalling param/result
  5088.   exception INITIALIZE           ex_body;   // ORB initialization failure
  5089.   exception NO_IMPLEMENT         ex_body;   // op. implementation unavailable
  5090.   exception BAD_TYPECODE         ex_body;   // bad typecode
  5091.   exception BAD_OPERATION        ex_body;   // invalid operation
  5092.   exception NO_RESOURCES         ex_body;   // insufficient resources for
  5093.                                  request
  5094.   exception NO_RESPONSE          ex_body;   // response to req. not yet
  5095.                                  available
  5096.   exception PERSIST_STORE        ex_body;   // persistent storage failure
  5097.   exception BAD_INV_ORDER        ex_body;   // routine invocations out
  5098.                                  of order
  5099.   exception TRANSIENT            ex_body;   // transient failure - reissue
  5100.                                  request
  5101.   exception FREE_MEM             ex_body;   // cannot free memory
  5102.   exception INV_IDENT            ex_body;   // invalid identifier syntax
  5103.   exception INV_FLAG             ex_body;   // invalid flag was specified
  5104.   exception INTF_REPOS           ex_body;   // error accessing interface
  5105.                                  repository
  5106.   exception CONTEXT              ex_body;   // error processing context object
  5107.   exception OBJ_ADAPTER          ex_body;   // failure detected by object adapter
  5108.   exception DATA_CONVERSION      ex_body;   // data conversion error
  5109. };
  5110.  
  5111.  
  5112. ΓòÉΓòÉΓòÉ 5.2.4. Interface declarations ΓòÉΓòÉΓòÉ
  5113.  
  5114. The IDL specification for a class of objects must contain a declaration of the 
  5115. interface these objects will support. Because, in SOM, objects are implemented 
  5116. using classes, the interface name is always used as a class name as well. 
  5117. Therefore, an interface declaration can be understood to specify a class name, 
  5118. and its parent (direct base) class names. This is the approach used in the 
  5119. following description of an interface declaration. In addition to the class 
  5120. name and its parents names, an interface indicates new methods (operations), 
  5121. and any constants, type definitions, and exception structures that the 
  5122. interface exports. An interface declaration has the following syntax: 
  5123.  
  5124. interface class-name [: parent-class1, parent-class2, ...]
  5125. {
  5126. constant declarations       (optional)
  5127. type declarations         (optional)
  5128. exception declarations      (optional)
  5129. attribute declarations      (optional)
  5130. method declarations        (optional)
  5131. implementation statement     (optional)
  5132. };
  5133.  
  5134. Many class implementers distinguish a "class-name" by using an initial capital 
  5135. letter, but that is optional. The "parent-class" (or base-class) names specify 
  5136. the interfaces from which the interface of "class-name" instances is derived. 
  5137. Parent-class names are required only for the immediate parent(s). Each parent 
  5138. class must have its own IDL specification (which must be #included in the 
  5139. subclass's .idl file). A parent class cannot be named more than once in the 
  5140. interface statement header. 
  5141.  
  5142. Note: In general, an "interface class-name" header must precede any subsequent 
  5143. implementation that references "class-name." For more discussion of multiple 
  5144. interface statements, refer to the later topic "Module declarations to define 
  5145. multiple interfaces in an .idl file." 
  5146.  
  5147. The following topics describe the various declarations/statements that can be 
  5148. specified within the body of an interface declaration. The order in which these 
  5149. declarations are specified is usually optional, and declarations of different 
  5150. kinds can be intermixed. Although all of the declarations/statements are listed 
  5151. above as "optional," in some cases using one of them may mandate another. For 
  5152. example, if a method raises an exception, the exception structure must be 
  5153. defined beforehand. In general, types, constants, and exceptions, as well as 
  5154. interface declarations, must be defined before they are referenced, as in 
  5155. C/C++. 
  5156.  
  5157.  
  5158. ΓòÉΓòÉΓòÉ 5.2.5. Constant, type, and exception declarations ΓòÉΓòÉΓòÉ
  5159.  
  5160. The form of a constant, type, or exception declaration within the body of an 
  5161. interface declaration is the same as described previously in this chapter. 
  5162. Constants and types defined within an interface for a class are transferred by 
  5163. the SOM Compiler to the binding files it generates for that class, whereas 
  5164. constants and types defined outside of an interface are not. 
  5165.  
  5166. Global types (such as, those defined outside of an interface and module) can be 
  5167. emitted by surrounding them with the following #pragmas: 
  5168.  
  5169.    #pragma somemittypes on
  5170.         typedef sequence <long,10> vec10;
  5171.         exception BAD_FLAG { long ErrCode; char Reason[80]; };
  5172.         typedef long long_t;
  5173.    #pragma somemittypes off
  5174.  
  5175. Types, constants, and exceptions defined in a parent class are also accessible 
  5176. to the child class. References to them, however, must be unambiguous. Potential 
  5177. ambiguities can be resolved by prefacing a name with the name of the class that 
  5178. defines it, separated by the characters "::" as illustrated below: 
  5179.  
  5180.    MyParentClass::myType
  5181.  
  5182. The child class can redefine any of the type, constant, and exception names 
  5183. that have been inherited, although this is not advised. The derived class 
  5184. cannot, however, redefine attributes or methods. It can only replace the 
  5185. implementation of methods through overriding (as in example 3 of the Tutorial). 
  5186. To refer to a constant, type, or exception "name" defined by a parent class and 
  5187. redefined by "class-name," use the "parent-name::name" syntax as before. 
  5188.  
  5189. Note: A name reference such as MyParentClass::myType required in IDL syntax is 
  5190. equivalent to MyParentClass_myType in C/C++. For a full discussion of name 
  5191. recognition in SOM, see "Scoping and name resolution" later in this chapter. 
  5192.  
  5193.  
  5194. ΓòÉΓòÉΓòÉ 5.2.6. Attribute declarations ΓòÉΓòÉΓòÉ
  5195.  
  5196. Declaring an attribute as part of an interface is equivalent to declaring two 
  5197. accessor methods: one to retrieve the value of the attribute (a "get" method, 
  5198. named "_get_<attributeName>") and one to set the value of the attribute (a 
  5199. "set" method, named "_set_<attributeName>"). 
  5200.  
  5201. Attributes are declared as follows: 
  5202.  
  5203. [ readonly ]  attribute  type-spec declarators ; 
  5204.  
  5205. where "type-spec" specifies any valid IDL type and "declarators" is a list of 
  5206. identifiers or pointer declarators, delimited by commas. (An array declarator 
  5207. cannot be used directly when declaring an attribute, but the type of an 
  5208. attribute can be a user-defined type that is an array.) The optional readonly 
  5209. keyword specifies that the value of the attribute can be accessed but not 
  5210. modified by client programs.  (In other words, a readonly attribute has no 
  5211. "set" method.) Below are examples of attribute declarations, which are 
  5212. specified within the body of an interface statement for a class: 
  5213.  
  5214.    interface Goodbye: Hello, SOMObject
  5215.    {
  5216.      void  sayBye();
  5217.  
  5218.      attribute short xpos;
  5219.      attribute char c1, c2;
  5220.      readonly attribute float xyz;
  5221.    };
  5222.  
  5223. The preceding attribute declarations are equivalent to defining the following 
  5224. methods: 
  5225.  
  5226.    short _get_xpos();
  5227.    void  _set_xpos(in short xpos);
  5228.    char  _get_c1();
  5229.    void  _set_c1(in char c1);
  5230.    char  _get_c2();
  5231.    void  _set_c2(in char c2);
  5232.    float _get_xyz();
  5233.  
  5234. Note: Although the preceding attribute declarations are equivalent to the 
  5235. explicit method declarations above, these method declarations are not legal 
  5236. IDL, because the method names begin with an '_'. All IDL identifiers must begin 
  5237. with an alphabetic character, not including '_'. 
  5238.  
  5239. Attributes are inherited from ancestor classes (indirect base classes). An 
  5240. inherited attribute name cannot be redefined to be a different type. 
  5241.  
  5242.  
  5243. ΓòÉΓòÉΓòÉ 5.2.7. Method (operation) declarations ΓòÉΓòÉΓòÉ
  5244.  
  5245. Method (operation) declarations define the interface of each method introduced 
  5246. by the class. A method declaration is similar to a C/C++ function definition: 
  5247.  
  5248. [oneway] type-spec identifier ( parameter-list)
  5249. [raises-expr]  [context-expr] ;
  5250. where "identifier" is the name of the method and "type-spec" is any valid IDL 
  5251. type (or the keyword void, indicating that the method returns no value). Unlike 
  5252. C and C++ procedures, methods that do not return a result must specify void as 
  5253. their return type. The remaining syntax of a method declaration is elaborated 
  5254. in the following subtopics. 
  5255.  
  5256. Note:  Although IDL does not allow methods to receive and return values whose 
  5257. type is a pointer to a function, it does allow methods to receive and return 
  5258. method names (as string values). Thus, rather than defining methods that pass 
  5259. pointers to functions (and that subsequently invoke those functions), 
  5260. programmers should instead define methods that pass method names (and 
  5261. subsequently invoke those methods using one of the SOM-supplied 
  5262. method-dispatching or method-resolution methods or functions, such as 
  5263. somDispatch). 
  5264.  
  5265.  
  5266. ΓòÉΓòÉΓòÉ 5.2.7.1. Oneway keyword ΓòÉΓòÉΓòÉ
  5267.  
  5268. The optional oneway keyword specifies that when a client invokes the method, 
  5269. the invocation semantics are "best-effort", which does not guarantee delivery 
  5270. of the call. "Best-effort" implies that the method will be invoked at most 
  5271. once. A oneway method should not have any output parameters and should have a 
  5272. return type of void. A oneway method also should not include a "raises 
  5273. expression" (see below), although it may raise a standard exception. 
  5274.  
  5275. If the oneway keyword is not specified, then the method has "at-most-once" 
  5276. invocation semantics if an exception is raised, and it has "exactly-once" 
  5277. semantics if the method succeeds. This means that a method that raises an 
  5278. exception has been executed zero or one times, and a method that succeeds has 
  5279. been executed exactly once. 
  5280.  
  5281. Note: Currently the "oneway" keyword, although accepted, has no effect on the 
  5282. C/C++ bindings that are generated. 
  5283.  
  5284.  
  5285. ΓòÉΓòÉΓòÉ 5.2.7.2. Parameter list ΓòÉΓòÉΓòÉ
  5286.  
  5287. The "parameter-list" contains zero or more parameter declarations for the 
  5288. method, delimited by commas. (The target object for the method is not 
  5289. explicitly specified as a method parameter in IDL, nor are the Environment or 
  5290. Context parameters.)  If there are no explicit parameters, the syntax "( )" 
  5291. must be used, rather than "(void)". A parameter declaration has the following 
  5292. syntax: 
  5293.  
  5294. { in ╨ó out ╨ó inout }  type-spec  declarator 
  5295.  
  5296. where "type-spec" is any valid IDL type and "declarator" is an identifier, 
  5297. array declarator, or pointer declarator. 
  5298.  
  5299. In, out, inout parameters:  The required in╨óout╨óinout directional attribute 
  5300. indicates whether the parameter is to be passed from client to server (in), 
  5301. from server to client (out), or in both directions (inout). A method must not 
  5302. modify an in  parameter. If a method raises an exception, the values of the 
  5303. return result and the values of the out and inout parameters (if any) are 
  5304. undefined. When an unbounded string or sequence is passed as an inout 
  5305. parameter, the returned value must be no longer than the input value. 
  5306.  
  5307. The following are examples of valid method declarations in SOM IDL: 
  5308.  
  5309.    short meth1(in char c, out float f);
  5310.    oneway void meth2(in char c);
  5311.    float meth3();
  5312.  
  5313. Classes derived from SOMObject can declare methods that take a pointer to a 
  5314. block of memory containing a variable number of arguments, using a final 
  5315. parameter of type va_list. The va_list must use the parameter name "ap", as in 
  5316. the following example: 
  5317.  
  5318.    void MyMethod(in short numArgs, in va_list ap);
  5319.  
  5320. For in parameters of type array, C and C++ clients must pass the address of the 
  5321. first element of the array. For in parameters of type struct,  union, sequence 
  5322. or any, C/C++ clients must pass the address of a variable of that type, rather 
  5323. than the variable itself. 
  5324.  
  5325. For all IDL types except arrays, if a parameter of a method is out or inout, 
  5326. then C/C++ clients must pass the address of a variable of that type (or the 
  5327. value of a pointer to that variable) rather than the variable itself. (For 
  5328. example, to invoke method "meth1" above, a pointer to a variable of type float 
  5329. must be passed in place of parameter "f".) For arrays, C/C++ clients must pass 
  5330. the address of the first element of the array. 
  5331.  
  5332. If the return type of a method is a struct, union, sequence, or any type, then 
  5333. for C/C++ clients, the method returns the value of the C/C++ struct 
  5334. representing the IDL struct, union, sequence, or any. If the return type is 
  5335. string, then the method returns a pointer to the first character of the string. 
  5336. If the return type is array, then the method returns a pointer to the first 
  5337. element of the array. 
  5338.  
  5339. The pointers implicit in the parameter types and return types for IDL method 
  5340. declarations are made explicit in SOM's C and C++ bindings. Thus, the stub 
  5341. procedure that the SOM Compiler generates for method "meth1", above, has the 
  5342. following signature: 
  5343.  
  5344.    SOM_Scope short  SOMLINK meth1(char c, float *f)
  5345.  
  5346. For C and C++ clients, if a method has an out parameter of type  string 
  5347. sequence, or any, then the method must allocate the storage for the string, for 
  5348. the "_buffer" member of the struct that represents the sequence, or for the 
  5349. "_value" member of the struct that represents the any. It is then the 
  5350. responsibility of the client program to free the storage when it is no longer 
  5351. needed. Similarly, if the return type of a method is string, sequence, array, 
  5352. or any, then storage must be allocated by the method, and it will be the 
  5353. responsibility of the client program to subsequently free it. 
  5354.  
  5355. Note: The foregoing description also applies for the _get_ <attributeName> 
  5356. method associated with an attribute of type string, sequence, any, or array. 
  5357. Hence, the attribute should be specified with a "noget" modifier to override 
  5358. automatic implementation of the attribute's "get" method.  Then, needed memory 
  5359. can be allocated by the developer's "get" method implementation and 
  5360. subsequently deallocated by the caller.  (The "noget" modifier is described 
  5361. under the topic "Modifier statements" later in this section.) 
  5362.  
  5363.  
  5364. ΓòÉΓòÉΓòÉ 5.2.7.3. Raises expression ΓòÉΓòÉΓòÉ
  5365.  
  5366. The optional raises expression ("raises-expr") in a method declaration 
  5367. indicates which exceptions the method may raise. (IDL exceptions are 
  5368. implemented by simply passing back error information after a method call, as 
  5369. opposed to the "catch/throw" model where an exception is implemented by a long 
  5370. jump or signal.)  A raises expression is specified as follows: 
  5371.  
  5372. raises ( identifier1, identifier2,... ) 
  5373.  
  5374. where each "identifier" is the name of a previously defined exception. In 
  5375. addition to the exceptions listed in the raises expression, a method may also 
  5376. signal any of the standard exceptions. Standard exceptions, however, should not 
  5377. appear in a raises expression. If no raises expression is given, then a method 
  5378. can raise only the standard exceptions. (See the earlier topic "Exception 
  5379. declarations" for information on defining exceptions and for the list of 
  5380. standard exceptions. See Chapter 3, the section entitled "Exceptions and error 
  5381. handling," for information on using exceptions.) 
  5382.  
  5383.  
  5384. ΓòÉΓòÉΓòÉ 5.2.7.4. Context expression ΓòÉΓòÉΓòÉ
  5385.  
  5386. The optional context expression ("context-expr") in a method declaration 
  5387. indicates which elements of the client's context the method may consult. A 
  5388. context expression is specified as follows: 
  5389.  
  5390. context ( identifier1, identifier2, ... ) 
  5391.  
  5392. where each "identifier" is a string literal made up of alphanumeric characters, 
  5393. periods, underscores, and asterisks. (The first character must be alphabetic, 
  5394. and an asterisk can only appear as the last character, where it serves as a 
  5395. wildcard matching any characters. If convenient, identifiers may consist of 
  5396. period-separated valid identifier names, but that form is optional.) 
  5397.  
  5398. The Context is a special object that is specified by the CORBA standard.  It 
  5399. contains a properly list - a set of property-name/string-value pairs that the 
  5400. client can use to store information about its environment that methods may find 
  5401. useful.  It is used in much the same way as environment variables.  It is 
  5402. passed as an additional (third) parameter to CORBA-compliant methods that are 
  5403. defined as "context-sensitive" in IDL, along with the CORBA-defined Environment 
  5404. structure. 
  5405.  
  5406. The context expression of a mehod declaration in IDL specifies which property 
  5407. names the method uses.  If these properties are present in the Context object 
  5408. supplied by the client, they will be passed to the object implementation, which 
  5409. can access them via the get_values method of the Context object. However, the 
  5410. argument that is passed to the method having a context expression is a Context 
  5411. object, not the names of the properties.  The client program must either create 
  5412. a Context object and use the set_values or set_one_value method of the Context 
  5413. class to set the context properties, or use the get_default_context method. The 
  5414. client program then passes the Context object in the method invocation.  Note 
  5415. that the CORBA standard also allows properties in addition to those in the 
  5416. context expression to be passed in the Context object. 
  5417.  
  5418. In Chapter 3, "Using SOM Classes in Client Programs," the topic "Invoking 
  5419. Methods" describes the placement of a context parameter in a method call. See 
  5420. also Chapter 6 of The Common Object Request Broker: Architecture and 
  5421. Specification for a discussion of how clients associate values with context 
  5422. identifiers. A description of the Context class and its methods is contained in 
  5423. the SOMobjects Developer Toolkit: Programmers Reference Manual. 
  5424.  
  5425.  
  5426. ΓòÉΓòÉΓòÉ 5.2.8. Implementation statements ΓòÉΓòÉΓòÉ
  5427.  
  5428. A SOM IDL interface statement for a class may contain an implementation 
  5429. statement, which specifies information about how the class will be implemented 
  5430. (version numbers for the class, overriding of inherited methods, what 
  5431. resolution mechanisms the bindings for a particular method will support, and so 
  5432. forth). If the implementation statement is omitted, default information is 
  5433. assumed. 
  5434.  
  5435. Because the implementation statement is specific to SOM IDL (and is not part of 
  5436. the CORBA standard), the implementation statement should be preceded by an 
  5437. "#ifdef _ _SOMIDL_ _" directive and followed by an "#endif" directive. (See 
  5438. Example 3 in the SOM IDL Tutorial presented earlier.) 
  5439.  
  5440. The syntax for the implementation statement is as follows: 
  5441.  
  5442.    #ifdef __SOMIDL__
  5443.    implementation
  5444.    {
  5445.      implementation*
  5446.    };
  5447.    #endif
  5448.  
  5449. where each "implementation" can be a modifier  statement, a passthru statement, 
  5450. or a declarator of an instance variable, terminated by a semicolon. These 
  5451. constructs are described below. An interface statement may not contain multiple 
  5452. implementation statements. 
  5453.  
  5454.  
  5455. ΓòÉΓòÉΓòÉ 5.2.8.1. Modifier statements ΓòÉΓòÉΓòÉ
  5456.  
  5457. A modifier statement gives additional implementation information about IDL 
  5458. definitions, such as interfaces, attributes, methods, and types. Modifiers can 
  5459. be unqualified or qualified: An unqualified modifier is associated with the 
  5460. interface it is defined in. An unqualified modifier statement has the following 
  5461. two syntactic forms: 
  5462.  
  5463.   modifier
  5464.   modifier = value
  5465. where "modifier" is either a SOM Compiler-defined identifier or a user-defined 
  5466. identifier, and where "value" is an identifier, a string enclosed in double 
  5467. quotes (" "), or a number. 
  5468.  
  5469. For example: 
  5470.  
  5471.    filestem = foo;
  5472.    nodata;
  5473.    persistent;
  5474.    dllname = "E:/som/dlls";
  5475.  
  5476. A qualified modifier is associated with a qualifier.  The qualified modifier 
  5477. has the syntax: 
  5478.  
  5479.    qualifier : modifier
  5480.    qualifier : modifier = value
  5481.    #pragma modifier qualifier : modifier
  5482.    #pragma modifier qualifier : modifier = value
  5483.  
  5484. where "qualifier" is the identifier of an IDL definition or is user defined. If 
  5485. the "qualifier" is an IDL definition introduced in the current interface, 
  5486. module, or global scope, then the modifier is attached to that definition. 
  5487. Otherwise, if the qualifier is user defined, the modifier is attached to the 
  5488. interface it occurs in. If a user-defined modifier is defined outside of an 
  5489. interface body (by using #pragma modifier), then it is ignored. 
  5490.  
  5491. For example, consider the following IDL file.  (Notice that qualified modifiers 
  5492. can be defined with the "qualifier" and "modifier[=value]" in either order. 
  5493. Also observe that additional modifiers can be included by separating them with 
  5494. commas.) 
  5495.  
  5496.    #include <somobj.idl>
  5497.    #include <somcls.idl>
  5498.  
  5499.  
  5500.    typedef long newInt;
  5501.    #pragma somemittypes on
  5502.    #pragma modifier newInt : nonportable;
  5503.    #pragma somemittypes off
  5504.    module M {
  5505.        typedef long long_t;
  5506.        module  N {
  5507.            typedef short short_t;
  5508.            interface M_I : SOMClass {
  5509.                implementation {
  5510.                    somInit : override;
  5511.                };
  5512.            };
  5513.            interface I : SOMObject {
  5514.                void op ();
  5515.                #pragma modifier op : persistent;
  5516.  
  5517.  
  5518.                typedef char char_t;
  5519.                implementation {
  5520.                    releaseorder : op;
  5521.                    metaclass = M_I;
  5522.                    callstyle = oidl;
  5523.                    mymod : a, b;
  5524.                    mymod : c, d;
  5525.                    e     : mymod;
  5526.                    f     : mymod;
  5527.                    op : persistent;
  5528.                };
  5529.           };
  5530.        };
  5531.     };
  5532.  
  5533. From the preceding IDL file, we associate modifiers with the following 
  5534. definitions: 
  5535.  
  5536.    TypeDef "::newInt"             1  modifier: nonportable
  5537.    InterfaceDef "::M::N::M_I"     1  modifier: override = somInit
  5538.    InterfaceDef "::M::N::I"       9 modifiers: metaclass = M_I,
  5539.                                                releaseorder = op
  5540.                                                callstyle = oidl
  5541.                                                mymod = a,b,c,d,e,f
  5542.                                                a = mymod
  5543.                                                b = mymod
  5544.                                                c = mymod
  5545.                                                d = mymod
  5546.                                                e = mymod
  5547.                                                f = mymod
  5548.    OperationDef "::M::N::I::op"   1 modifier: persistent
  5549.  
  5550. Notice, how the modifiers for the user-defined qualifier "mymod": 
  5551.  
  5552.    mymod : a, b;
  5553.    mymod : c, d;
  5554.    e     : mymod;
  5555.    f     : mymod;
  5556.  
  5557. map onto: 
  5558.  
  5559.    mymod = a,b,c,d,e,f
  5560.    a     = mymod
  5561.    b     = mymod
  5562.    c     = mymod
  5563.    d     = mymod
  5564.    e     = mymod
  5565.    f     = mymod
  5566.  
  5567. This enables users to look up the modifiers with "mymod", either by looking for 
  5568. "mymod" or by using each individual value that uses "mymod". These user-defined 
  5569. modifiers are available for Emitter writers (see the Emitter Writer's Guide and 
  5570. Reference) and from the Interface Repository (see Chapter 7, "The Interface 
  5571. Repository Framework"). 
  5572.  
  5573.  
  5574. ΓòÉΓòÉΓòÉ 5.2.8.2. SOM Compiler unqualified modifiers ΓòÉΓòÉΓòÉ
  5575.  
  5576. Unqualified modifiers (described below) include the SOM Compiler-defined 
  5577. identifiers abstract, baseproxyclass, callstyle, classinit, directinitclasses, 
  5578. dllname, filestem, functionprefix, majorversion, metaclass, memory_management, 
  5579. minorversion, somallocte and somdeallocate. 
  5580.  
  5581.  abstract                 Specifies that the class is intended for use as a 
  5582.                           parent for subclass derivations, but not for creating 
  5583.                           instances. 
  5584.  
  5585.  baseproxyclass =class    Specifies the base proxy class to be used by DSOM 
  5586.                           when dynamically creating a proxy class for the 
  5587.                           current class. The base proxy class must be derived 
  5588.                           from the class SOMDClientProxy  The SOMDClientProxy 
  5589.                           class will be used if the baseproxyclass modifier is 
  5590.                           unspecified. (See chapter 6, "distributed SOM," for a 
  5591.                           discussion on customizing proxy classes.) 
  5592.  
  5593.  callstyle = oidl         Specifies that the method stub procedures generated 
  5594.                           by SOM's C/C++ bindings will not include the 
  5595.                           CORBA-specified (Environment *ev) and (context *ctx) 
  5596.                           parameters. 
  5597.  
  5598.  classinit = procedure    Specifies a user-written procedure that will be 
  5599.                           executed to complete the initialization of a class 
  5600.                           object after it is created. The classinit modifier is 
  5601.                           needed if something should happen exactly once when a 
  5602.                           class is created. (That is, you want to define an 
  5603.                           action that will not be inherited when subclasses are 
  5604.                           created. One example of this is for staticdata 
  5605.                           variables.) When the classinit modifier is specified 
  5606.                           in the .idl file for a class, the implementation file 
  5607.                           generated by the SOM Compiler provides a template for 
  5608.                           the procedure, which includes a parameter that is a 
  5609.                           pointer to the class. The class implementor can then 
  5610.                           fill in the body of this procedure template. (For an 
  5611.                           example, see the examples following the staticdata 
  5612.                           modifier under "SOM Compiler qualified modifiers.") 
  5613.  
  5614.  directinitclasses ="ancestor1, ancestor2, ..." 
  5615.  
  5616.  
  5617.                           Specifies the ancestor class(es) whose initializers 
  5618.                           (and destructors) will be directly invoked by this 
  5619.                           class's initialization (and destruction) routines. 
  5620.                           If this modifier is not explicitly specified, the 
  5621.                           default setting is the parents of the class. For 
  5622.                           further information, see "Initializing and 
  5623.                           Uninitializing Objects" in Chapter 5, "Implementing 
  5624.                           Classes in SOM." 
  5625.  
  5626.  dllname = filename       Specifies the name of the library file that will 
  5627.                           contain the class's implementation. If filename 
  5628.                           contains special characters (e.g., periods, 
  5629.                           backslashes), then filename should be surrounded by 
  5630.                           double quotes (""). The filename specified can be 
  5631.                           either a full pathname, or an unqualified (or 
  5632.                           partially qualified) filename. In the latter cases, 
  5633.                           the LIBPATH environment variable is used to locate 
  5634.                           the file. 
  5635.  
  5636.  filestem  = stem         Specifies how the SOM Compiler will construct file 
  5637.                           names for the binding files it generates (<stem>.h, 
  5638.                           <stem>.c, etc.). The default stem is the file stem of 
  5639.                           the .idl file for the class. 
  5640.  
  5641.  functionprefix  = prefix Directs the SOM Compiler to construct 
  5642.                           method-procedure names by prefixing method names with 
  5643.                           "prefix". For example, "functionprefix = xx;"  within 
  5644.                           an implementation statement would result in a 
  5645.                           procedure name of xxfoo for method foo.  The default 
  5646.                           for this attribute is the empty string. If an 
  5647.                           interface is defined in a module, then the default 
  5648.                           function prefix is the fully scooped interface name. 
  5649.                           Tip:  Using a function prefix with the same name as 
  5650.                           the class makes it easier to remember 
  5651.                           method-procedure names when debugging. 
  5652.  
  5653.                           When an .idl file defines multiple interfaces not 
  5654.                           contained within a module, use of a function prefix 
  5655.                           for each interface is essential to avoid name 
  5656.                           collisions. 
  5657.  
  5658.                                                      For example, if one interface introduces a
  5659.                           method and another interface in the same .idl file 
  5660.                           overrides it, then the implementation file for the 
  5661.                           classes will contain two method procedures of the 
  5662.                           same name (unless function prefixes are defined for 
  5663.                           one of the classes), resulting in a name collision at 
  5664.                           compile time. 
  5665.  
  5666.  majorversion = number    Specifies the major version number of the current 
  5667.                           class definition. The major version number of a class 
  5668.                           definition usually changes only when a significant 
  5669.                           enhancement or incompatible change is made to the 
  5670.                           class. The "number" must be a positive integer less 
  5671.                           than 2[32]-1.  If a non-zero major version number is 
  5672.                           specified, SOM will verify that any code that 
  5673.                           purports to implement the class has the same major 
  5674.                           version number. The default major version number is 
  5675.                           zero. 
  5676.  
  5677.  memory_management = corba 
  5678.  
  5679.  
  5680.                           Specifies that all methods introduced by the class 
  5681.                           follow the CORBA specification for parameter memory 
  5682.                           management, except where a particular method has an 
  5683.                           explicit modifier indicating otherwise (either 
  5684.                           "object_owns_result" or "object_owns_parameters"). 
  5685.                           See the section in Chapter 6 entitled "Memory 
  5686.                           Management" for a discussion of the CORBA 
  5687.                           memory-management requirements. 
  5688.  
  5689.  metaclass = class        Specifies the class's metaclass. The specified 
  5690.                           metaclass (or one automatically derived from it at 
  5691.                           run time) will be used to create the class object for 
  5692.                           the class. If a metaclass is specified, its .idl file 
  5693.                           (if separate) must be included in the include section 
  5694.                           of the class's .idl file. If no metaclass is 
  5695.                           specified, the metaclass will be defined 
  5696.                           automatically. 
  5697.  
  5698.  minorversion = number    Specifies the minor version number of the current 
  5699.                           class definition. The minor version number of a class 
  5700.                           definition changes whenever minor enhancements or 
  5701.                           fixes are made to a class. Class implementers usually 
  5702.                           maintain backward compatibility across changes in the 
  5703.                           minor version number. The "number" must be a positive 
  5704.                           integer less than 2[32]-1. If a non-zero minor 
  5705.                           version number is specified, SOM will verify that any 
  5706.                           code that purports to implement the class has the 
  5707.                           same or a higher minor version number. The default 
  5708.                           minor version number is zero. 
  5709.  
  5710.  somallocate=procedure    Specifies a user-written procedure that will be 
  5711.                           executed to allocate memory for class instances when 
  5712.                           the somAllocate class method is invoked. 
  5713.  
  5714.  somdeallocate=procedure  Specifies a user-written procedure that will be 
  5715.                           executed to deallocate memory for class instances 
  5716.                           when the somDeallocate class method is invoked. 
  5717.  
  5718.  The following example illustrates the specification of unqualified interface 
  5719.  modifiers: 
  5720.  
  5721.      implementation
  5722.      {
  5723.        filestem = hello;
  5724.        functionprefix = hel;
  5725.        majorversion = 1;
  5726.        minorversion = 2;
  5727.        classinit = helloInit;
  5728.        metaclass = M_Hello;
  5729.      };
  5730.  
  5731.  
  5732. ΓòÉΓòÉΓòÉ 5.2.8.3. SOM Compiler qualified modifiers ΓòÉΓòÉΓòÉ
  5733.  
  5734. Qualified modifiers are categorized according to the IDL component (class, 
  5735. attribute, method, or type) to which each modifier applies. Listed below are 
  5736. the SOM Compiler-defined identifiers used as qualified modifiers, along with 
  5737. the IDL component to which it applies. Descriptions of all qualified modifiers 
  5738. are then given in alphabetical order. Recall that qualified modifiers are 
  5739. defined using the syntax qualifier: modifier[=value]. 
  5740.  
  5741.  For classes: 
  5742.       releaseorder 
  5743.  
  5744.  For attributes: 
  5745.       indirect, nodata, noget, noset 
  5746.  
  5747.  For methods: 
  5748.       caller_owns_parameters, caller_owns_result, const, init, method, migrate, 
  5749.       namelookup, nocall, noenv, nonstatic, nooverride, noself, 
  5750.       object_owns_parameters, object_owns_result, offset, override, procedure, 
  5751.       reintroduce, and select 
  5752.  
  5753.  For variables: 
  5754.       staticdata 
  5755.  
  5756.  For types: 
  5757.       impctx 
  5758.  
  5759.  caller_owns_parameters ="p1,p2,...,pn" 
  5760.  
  5761.  
  5762.                           Specifies the names of the method's parameters whose 
  5763.                           ownership is retained by (in the case of 
  5764.                           "in"parameters) or transferred to (for "inout" or 
  5765.                           "out" parameters) the caller. This modifier is only 
  5766.                           valid in the interface specification of the method's 
  5767.                           introducing class.  This modifier only makes sense 
  5768.                           for parameters whose IDL type is a data item that can 
  5769.                           be freed (string, object, array, pointer, or 
  5770.                           TypeCode), or a data item containing memory that can 
  5771.                           be freed (for example, a sequence or any), or a 
  5772.                           struct or union. 
  5773.  
  5774.                           For parameters whose type is an object, ownership 
  5775.                           applies to the object reference rather than to the 
  5776.                           object (that is, the caller should invoke release on 
  5777.                           the parameter, rather than somFree). 
  5778.  
  5779.  caller_owns_result       Specifies that ownership of the return result of  the 
  5780.                           method is transferred to the caller, and that the 
  5781.                           caller is responsible for freeing the memory. This 
  5782.                           modifier is only valid in the interface specification 
  5783.                           of the method's introducing class. This modifier only 
  5784.                           makes sense when the method's return type is a data 
  5785.                           type that can be freed (string, object, array, 
  5786.                           pointer, or TypeCode), or a data item containing 
  5787.                           memory that can be freed (for example, a sequence or 
  5788.                           any). For methods that return an object, ownership 
  5789.                           applies to the object reference rather than to the 
  5790.                           object (that is, the caller should invoke release on 
  5791.                           the result, rather than somFree). 
  5792.  
  5793.  const                    Indicates that implementations of the related method 
  5794.                           should not modify their target argument. SOM provides 
  5795.                           no way to verify or guarantee that implementations do 
  5796.                           not modify the targets of such methods, and the 
  5797.                           information provided by this modifier is not 
  5798.                           currently of importance to any of the Toolkit 
  5799.                           emitters. However, the information may prove useful 
  5800.                           in the future. For example, since modifiers are 
  5801.                           available in the Interface Repository, there may be 
  5802.                           future uses of this information by DSOM. 
  5803.  
  5804.  impctx                   Supports types that cannot be fully defined using 
  5805.                           IDL. For full information, see "Using the tk_foreign 
  5806.                           TypeCode" in Chapter 7, "The Interface Repository 
  5807.                           Framework." 
  5808.  
  5809.  indirect                 Directs the SOM Compiler to generate "get" and "set" 
  5810.                           methods for the attribute that take and return a 
  5811.                           pointer to the attribute's value, rather than the 
  5812.                           attribute value itself. For example, if an attribute 
  5813.                           x of type float is declared to be an indirect 
  5814.                           attribute, then the "_get_x" method will return a 
  5815.                           pointer to a float, and the input to the "_set_x" 
  5816.                           method must be a pointer to a float. (This modifier 
  5817.                           is provided for OIDL compatibility only.) 
  5818.  
  5819.  init                     Indicates that a method is an initializer method. 
  5820.                           For information concerning the use of this modifier, 
  5821.                           see "Initializing and Uninitializing Objects: in 
  5822.                           Chapter 5, "Implementing Classes in SOM" 
  5823.  
  5824.  method or nonstatic or  procedure 
  5825.  
  5826.  
  5827.                           Indicates the category of method implementation. 
  5828.                           Refer to the topic "The four kinds of SOM methods" in 
  5829.                           Chapter 5, "Implementing Classes in SOM," for an 
  5830.                           explanation of the meanings of these different method 
  5831.                           modifiers.  If none of these modifiers is specified, 
  5832.                           the default is method.  Methods with the procedure 
  5833.                           modifier cannot be invoked remotely using DSOM. 
  5834.  
  5835.  migrate  = ancestor      Indicates that a method originally introduced by this 
  5836.                           interface has been moved upward to a specified 
  5837.                           <ancestor> interface. When this is done, the method 
  5838.                           introduction must be removed from this interface 
  5839.                           (because the method is now inherited). However, the 
  5840.                           original  releaseorder entry for the method should be 
  5841.                           retained, and migrate should be used to assure that 
  5842.                           clients compiled based on the original interface will 
  5843.                           not require recompilation. The ancestor interface is 
  5844.                           specified using a C-scoped interface name. For 
  5845.                           example, "Module_InterfaceName", not 
  5846.                           "Module::InterfaceName". See the later topic "Name 
  5847.                           usage in client programs" for an explanation of 
  5848.                           C-scoped names. 
  5849.  
  5850.  namelookup               See "offset or namelookup." 
  5851.  
  5852.  nocall                   Specifies that the related method should not be 
  5853.                           invoked on an instance of this class even though it 
  5854.                           is supported by the interface. 
  5855.  
  5856.  nodata                   Directs the SOM Compiler not to define an instance 
  5857.                           variable corresponding to the attribute. For example, 
  5858.                           a "time" attribute would not require an instance 
  5859.                           variable to maintain its value, because the value can 
  5860.                           be obtained from the operating system.  The "get" and 
  5861.                           "set" methods for "nodata" attributes must be defined 
  5862.                           by the class implementer; stub method procedures for 
  5863.                           them are automatically generated in the 
  5864.                           implementation template for the class by the SOM 
  5865.                           Compiler. 
  5866.  
  5867.  noenv                    Indicates that a direct-call procedure does not 
  5868.                           receive an environment as an argument. 
  5869.  
  5870.  noget                    Directs the SOM Compiler not to automatically 
  5871.                           generate a "get" method procedure for the attribute 
  5872.                           in the .ih/.xih binding file for the class. Instead, 
  5873.                           the "get" method must be implemented by the class 
  5874.                           implementer. A stub method procedure for the "get" 
  5875.                           method is automatically generated in the 
  5876.                           implementation template for the class by the SOM 
  5877.                           Compiler, to be filled in by the implementer. 
  5878.  
  5879.  nonstatic                See "method or nonstatic or procedure." 
  5880.  
  5881.  nooverride               Indicates that the method should not be overridden by 
  5882.                           subclasses. The SOM Compiler will generate an error 
  5883.                           if this method is overridden. 
  5884.  
  5885.  noself                   Indicates that a direct-call procedure does not 
  5886.                           receive a target object as an argument. 
  5887.  
  5888.  noset                    Directs the SOM Compiler not  to automatically 
  5889.                           generate a "set" method procedure for the attribute 
  5890.                           in the .ih/.xih binding file for the class. Instead, 
  5891.                           the "set" method must be implemented by the class 
  5892.                           implementer. A stub method procedure for the "set" 
  5893.                           method is automatically generated in the 
  5894.                           implementation template for the class by the SOM 
  5895.                           Compiler. 
  5896.  
  5897.                           Note: The "set" method procedure that the SOM 
  5898.                           Compiler generates by default for an attribute in the 
  5899.                           .h/.xh binding file (when the noset modifier is not 
  5900.                           used) does a shallow copy of the value that is passed 
  5901.                           to the attribute. For some attribute types, including 
  5902.                           strings and pointers, this may not be appropriate. 
  5903.                           For instance, the "set" method for an attribute of 
  5904.                           type string should perform a string copy, rather than 
  5905.                           a shallow copy, if the attribute's value may be 
  5906.                           needed after the client program has freed the memory 
  5907.                           occupied by the string. In such situations, the class 
  5908.                           implementer should specify the noset attribute 
  5909.                           modifier and implement the attribute's "set" method 
  5910.                           manually, rather than having SOM implement the "set" 
  5911.                           method automatically. 
  5912.  
  5913.  object_owns_parameters  ="p1, p2, ..., pn" 
  5914.  
  5915.  
  5916.                           Specifies the names of the method's parameters whose 
  5917.                           ownership is transferred to (in the case of "in" 
  5918.                           parameters) or is retained by (for "inout" or "out" 
  5919.                           parameters) the object.  For "in" parameters, the 
  5920.                           object can free the parameter at any time after 
  5921.                           receiving it. (Hence, the caller should not reuse the 
  5922.                           parameter or pass it as any other object-owned 
  5923.                           parameter in the same method call.) For "inout" and 
  5924.                           "out" parameters, the object is responsible for 
  5925.                           freeing the parameter sometime before the object is 
  5926.                           destroyed. This modifier is only valid in the 
  5927.                           interface specification of the method's introducing 
  5928.                           class. This modifier only makes sense for parameters 
  5929.                           whose IDL type is a data item that can be freed 
  5930.                           (string, object, array, pointer, or TypeCode), or a 
  5931.                           data item containing memory that can be freed (for 
  5932.                           example, a sequence or any), or a struct or union. 
  5933.  
  5934.                           For parameters whose type is an object, ownership 
  5935.                           applies to the object reference  rather than to the 
  5936.                           object (that is, the object will invoke release on 
  5937.                           the parameter, rather than somFree). For "in" and 
  5938.                           "out" parameters whose IDL-to-C/C++ mapping 
  5939.                           introduces a pointer, ownership applies only to the 
  5940.                           data item itself, and not to the introduced pointer. 
  5941.                           (For example, even if an "out string" IDL parameter 
  5942.                           (which becomes a "string *" C/C++ parameter) is 
  5943.                           designated as "object-owned,"  the object assumes 
  5944.                           ownership of the string, but not of the pointer to 
  5945.                           the string.) 
  5946.  
  5947.  object_owns_result       Specifies that the object retains ownership of the 
  5948.                           return result of the method, and that the caller must 
  5949.                           not free the memory. The object is responsible for 
  5950.                           freeing the memory sometime before the object is 
  5951.                           destroyed. This modifier is only valid in the 
  5952.                           interface specification of the method's introducing 
  5953.                           class. This modifier only makes sense when the 
  5954.                           method's return type is a data type that can be freed 
  5955.                           (string, object, array, pointer, or TypeCode), or a 
  5956.                           data item containing memory that can be freed (for 
  5957.                           example, a sequence or any). For methods that return 
  5958.                           an object, ownership applies to the object reference 
  5959.                           rather than to the object (that is, the object will 
  5960.                           be responsible for invoking release on the result, 
  5961.                           rather than somFree). 
  5962.  
  5963.  offset or namelookup     Indicates whether the SOM Compiler should generate 
  5964.                           bindings for invoking the method using offset 
  5965.                           resolution or name lookup. Offset resolution requires 
  5966.                           that the class of the method's target object be known 
  5967.                           at compile time. When different methods of the same 
  5968.                           name are defined by several classes, namelookup is a 
  5969.                           more appropriate technique for method resolution than 
  5970.                           is offset resolution. (See Chapter 3, the section 
  5971.                           entitled "Invoking Methods.")  The default modifier 
  5972.                           is offset. 
  5973.  
  5974.  override                 Indicates that the method is one introduced by an 
  5975.                           ancestor class and that this class will re-implement 
  5976.                           the method. See also the related modifier, select. 
  5977.  
  5978.  procedure                See "method or nonstatic or procedure." 
  5979.  
  5980.  reintroduce              Indicates that this interface will "hide" a method 
  5981.                           introduced by some ancestor interface, and will 
  5982.                           replace it with another implementation. Methods 
  5983.                           introduced as direct-call procedures or nonstatic 
  5984.                           methods can be reintroduced. However, static methods 
  5985.                           (the default implementation category for SOM met 
  5986.                           hods) cannot be reintroduced. 
  5987.  
  5988.  releaseorder: a, b, c, ... Specifies the order in which the SOM Compiler will 
  5989.                           place the class's methods in the data structures it 
  5990.                           builds to represent the class. Maintaining a 
  5991.                           consistent release order for a class allows the 
  5992.                           implementation of a class to change without requiring 
  5993.                           client programs to be recompiled. 
  5994.  
  5995.                           The release order should contain every method name 
  5996.                           introduced by the class (private and nonprivate), but 
  5997.                           should not include any inherited methods, even if 
  5998.                           they are overridden by the class. The "get" and "set" 
  5999.                           methods defined automatically for each new attribute 
  6000.                           (named "_get_<attributeName>" and 
  6001.                           "_set_<attributeName>") should also be included in 
  6002.                           the release order list. The order of the names on the 
  6003.                           list is unimportant except that once a name is on the 
  6004.                           list and the class has client programs, it should not 
  6005.                           be reordered or removed, even if the method is no 
  6006.                           longer supported by the class, or the client programs 
  6007.                           will require recompilation. New methods should be 
  6008.                           added only to the end of the list. If a method named 
  6009.                           on the list is to be moved up in the class hierarchy, 
  6010.                           its name should remain on the current list, but it 
  6011.                           should also be added to the release order list for 
  6012.                           the class that will now introduce it. 
  6013.  
  6014.                           If not explicitly specified, the release order will 
  6015.                           be determined by the SOM Compiler, and a warning will 
  6016.                           be issued for each missing method. If new methods or 
  6017.                           attributes are subsequently added to the class, the 
  6018.                           default release order might change; programs using 
  6019.                           the class would then require recompilation. Thus, it 
  6020.                           is advisable to explicitly give a release order. 
  6021.  
  6022.  select = parent          Used in conjunction with the override modifier, this, 
  6023.                           indicates that an inherited static method will use 
  6024.                           the implementation inherited from the indicated 
  6025.                           <parent> class. The parent is specified using the 
  6026.                           C-scoped name. For example, "Module_InterfaceName", 
  6027.                           not "Module:: InterfaceName". See the later topic 
  6028.                           "Name usage in client programs" for an explanation of 
  6029.                           C-scoped names. 
  6030.  
  6031.  staticdata               Indicates that the declared variable is not stored 
  6032.                           within objects, but, instead, that the ClassData 
  6033.                           structure for the implementing class will contain a 
  6034.                           pointer to the staticdata variable. This is similar 
  6035.                           in concept to C++ static data members. The staticdata 
  6036.                           variable must also be included in the releaseorder. 
  6037.                           The class implementor has responsibility for 
  6038.                           allocating the staticdata variable and for loading 
  6039.                           the ClassData structure's pointer to the staticdata 
  6040.                           variable during class initialization. (The pointer is 
  6041.                           accessible as <className>ClassData.<variableName>.) 
  6042.                           The implementor's responsibility can be facilitated 
  6043.                           by writing a special class initialization function 
  6044.                           and indicating its name using the classinit 
  6045.                           unqualified modifier. (See also the examples that 
  6046.                           follow.) 
  6047.  
  6048.                           Note:  Attributes can be declared as staticdata. This 
  6049.                                  is an important implementation technique that 
  6050.                                  allows classes to introduce attributes whose 
  6051.                                  backing storage is not inherited by 
  6052.                                  subclasses. 
  6053.  
  6054.  The following example illustrates the specification of qualified modifiers: 
  6055.  
  6056.   implementation
  6057.   {
  6058.     releaseorder : op1, op3, op2, op5, op6, x, y, _set_z, _get_z;
  6059.     op1 : persistent;
  6060.     somDefaultInit : override, init;
  6061.     op2: reintroduce, procedure;
  6062.     op3: reintroduce, nonstatic;
  6063.     op4: override, select = ModuleName_parentInterfaceName;
  6064.     op5: migrate = ModuleName_ancestorInterfaceName;
  6065.     op6: procedure, noself, noenv;
  6066.     long x;
  6067.     x: staticdata;
  6068.     y: staticdata; // y and z are attributes
  6069.     _set_z: object_owns_parameters = "name";
  6070.     _get_z: object_owns_result;
  6071.     mymod : a, b;
  6072.   };
  6073.  
  6074.  As shown above for attribute z, separate modifiers can be declared for an 
  6075.  attribute's _set and _get methods, using method modifiers. This capability may 
  6076.  be useful for DSOM applications. (See the DSOM sample program "animal" that is 
  6077.  distributed with the SOMobjects Toolkit.) 
  6078.  
  6079.  The next example for classes "X" and "Y" illustrates the use of a staticdata 
  6080.  modifier, along with its corresponding classinit modifier and the template 
  6081.  procedure generated for classinit by the SOM Compiler. 
  6082.  
  6083.   /* IDL for staticdata and classinit example: */
  6084.  
  6085.   #include <somobj.idl>
  6086.  
  6087.   interface X : SOMObject {
  6088.           attribute long staticAttribute;
  6089.           attribute long normalAttribute;
  6090.           implementation {
  6091.                   staticAttribute: staticdata;
  6092.                   classinit = Xinit;
  6093.                   releaseorder: staticAttribute,
  6094.                                       _get_staticAttribute,
  6095.                                       _set_staticAttribute,
  6096.                                       _get_normalAttribute,
  6097.                                       _set_normalAttribute;
  6098.           };
  6099.   };
  6100.  
  6101.   interface Y : X { };
  6102.  
  6103.   /* Template procedure for classInit: */
  6104.  
  6105.   #ifndef SOM_Module_classinit_Source
  6106.   #define SOM_Module_classinit_Source
  6107.   #endif
  6108.   #define X_Class_Source
  6109.  
  6110.   #include "classInit.ih"
  6111.  
  6112.   static long holdStaticAttribute = 1234;
  6113.   void SOMLINK Xinit(SOMClass *cls)
  6114.   {
  6115.           XClassData.staticAttribute = &holdStaticAttribute;
  6116.   }
  6117.  
  6118.   main()
  6119.   {
  6120.           X *x = XNew();
  6121.           Y *y = YNew();
  6122.  
  6123.           somPrintf("initial staticAttribute = x(%d) = y(%d)\n",
  6124.                                   _get_staticAttribute(x,0),
  6125.                                   _get_staticAttribute(y,0));
  6126.  
  6127.           _set_staticAttribute(x,0,42);
  6128.           _set_staticAttribute(y,0,4321);
  6129.  
  6130.           somPrintf("changed staticAttribute = x(%d) = y(%d)\n",
  6131.                                   _get_staticAttribute(x,0),
  6132.                                   _get_staticAttribute(y,0));
  6133.   }
  6134.  
  6135.   /* Program output:
  6136.  
  6137.           initial staticAttribute = x(1234) = y(1234)
  6138.           changed staticAttribute = x(4321) = y(4321)
  6139.           after setting normalAttribute, x(10) != y(20)
  6140.   */
  6141.  
  6142.  
  6143. ΓòÉΓòÉΓòÉ 5.2.8.4. Passthru statements ΓòÉΓòÉΓòÉ
  6144.  
  6145. A passthru statement (used within the body of an implementation statement, 
  6146. described above) allows a class implementer to specify blocks of code (for 
  6147. C/C++ programmers, usually only #include directives) that the SOM compiler will 
  6148. pass into the header files it generates. 
  6149.  
  6150. Passthru statements are included in SOM IDL primarily for backward 
  6151. compatibility with the SOM OIDL language, and their use by C and C++ 
  6152. programmers should be limited to #include directives. C and C++ programmers 
  6153. should use IDL type and constant declarations rather than passthru statements 
  6154. when possible. (Users of other languages, however, may require passthru 
  6155. statements for type and constant declarations.) 
  6156.  
  6157. The contents of the passthru lines are ignored by the SOM compiler and can 
  6158. contain anything that needs to placed near the beginning of a header file for a 
  6159. class. Even comments contained in passthru lines are processed without 
  6160. modification. The syntax for specifying passthru lines is one of the following 
  6161. forms: 
  6162.  
  6163.  passthru language_suffix      = literal+ ; 
  6164.  passthru language_suffix_before = literal+ ; 
  6165.  passthru language_suffix_after = literal+ ; 
  6166.  
  6167.  where "language" specifies the programming language and "suffix" indicates 
  6168.  which header files will be affected. The SOM Compiler supports suffixes h, ih, 
  6169.  xh, and xih. For both C and C++, "language" is specified as C. 
  6170.  
  6171.  Each "literal" is a string literal (enclosed in double quotes) to be placed 
  6172.  verbatim into the specified header file.  [Double quotes within the passthru 
  6173.  literal should be preceded by a backslash. No other characters escaped with a 
  6174.  backslash will be interpreted, and formatting characters (newlines, tab 
  6175.  characters, etc.) are passed through without processing.]  The last literal 
  6176.  for a passthru statement must not end in a backslash (put a space or other 
  6177.  character between a final backslash and the closing double quote). 
  6178.  
  6179.  When either of the first two forms is used, passthru  lines are placed before 
  6180.  the #include statements in the header file. When the third form is used, 
  6181.  passthru lines are placed just after the #include statements in the header 
  6182.  file. 
  6183.  
  6184.  For example, the following passthru statement 
  6185.  
  6186.      implementation
  6187.      {
  6188.        passthru C_h = "#include <foo.h>";
  6189.      };
  6190.  
  6191.  results in the directive #include <foo.h> being placed at the beginning of the 
  6192.  .h C binding file that the SOM Compiler generates. 
  6193.  
  6194.  For any given target file (as indicated by language_suffix), only one passthru 
  6195.  statement may be defined within each implementation section. You may, however, 
  6196.  define multiple #include statements in a single passthru. For legibility, each 
  6197.  #include should begin on a new line, optionally with a blank line to precede 
  6198.  and follow the #include list. For an example, see "Introducing non-IDL data 
  6199.  types or classes" later in this section. 
  6200.  
  6201.  
  6202. ΓòÉΓòÉΓòÉ 5.2.8.5. Declaring instance variables and staticdata variables ΓòÉΓòÉΓòÉ
  6203.  
  6204. Declarators are used within the body of an implementation statement (described 
  6205. above) to specify the instance variables that are introduced by a class, and 
  6206. the staticdata variables pointed to by the class's ClassData structure. These 
  6207. variables are declared using ANSI C syntax for variable declarations, 
  6208. restricted to valid SOM IDL types (see "Type and constant declarations," 
  6209. above). For example, the following implementation statement declares two 
  6210. instance variables, x and y, and a staticdata variable, z, for class "Hello," : 
  6211.  
  6212. implementation
  6213. {
  6214.   short x;
  6215.   long y;
  6216.   double z;
  6217.   z: staticdata;
  6218. };
  6219.  
  6220. Instance variables are normally intended to be accessed only by the class's 
  6221. methods and not by client programs or subclasses' methods. For data to be 
  6222. accessed by client programs or subclass methods, attributes should be used 
  6223. instead of instance variables. (Note, however, that declaring an attribute has 
  6224. the effect of also declaring an instance variable of the same name, unless the 
  6225. "nodata" attribute modifier is specified.) 
  6226.  
  6227. Staticdata variables, by contrast, are publicly available and are associated 
  6228. specifically with their introducing class. They are, however, very different in 
  6229. concept from class variables. Class variables are really instance variables 
  6230. introduced by a metaclass, and are therefore present in any class that is an 
  6231. instance of the introducing metaclass (or of any metaclass derived from this 
  6232. metaclass). As a result, class variables present in any given class will also 
  6233. be present in any class derived from this class (that is, class variables are 
  6234. inherited). In contrast, staticdata variables are introduced by a class (not a 
  6235. metaclass) and are (only) accessed from the class's ClassData structure - they 
  6236. are not inherited. 
  6237.  
  6238.  
  6239. ΓòÉΓòÉΓòÉ 5.2.8.6. Introducing non-IDL data types or classes ΓòÉΓòÉΓòÉ
  6240.  
  6241. On occasion, you may want a new .idl file to reference some element that the 
  6242. SOM Compiler would not recognize, such as a user-defined class or an instance 
  6243. variable or attribute with a user-defined data type. You can reference such 
  6244. elements if they already exist in .h or .xh files that the SOM Compiler can 
  6245. #include with your new .idl file, as follows: 
  6246.  
  6247.      To introduce a non-IDL class, insert an interface statement that is a 
  6248.       forward reference to the existing user-defined class. It must precede the 
  6249.       interface statement for the new class in the .idl file. 
  6250.  
  6251.      To declare an instance variable or attribute that is not a valid IDL 
  6252.       type, declare a dummy typedef preceding the interface declaration. 
  6253.  
  6254.      In each case above, in the implementation section use a passthru 
  6255.       statement to pass an #include statement into the language-specific 
  6256.       binding file(s) of the new .idl file (a) for the existing user-defined 
  6257.       class or (b) for the real typedef. 
  6258.  
  6259.  In the following example, the generic SOM type somToken is used in the .idl 
  6260.  file for the user's types "myRealType" and "myStructType". The passthru 
  6261.  statement then causes an appropriate #include statement to be emitted into the 
  6262.  C/C++ binding file, so that the file defining types "myRealType" and 
  6263.  "myStructType" will be included when the binding files process. In addition, 
  6264.  an interface declaration for "myOtherClass" is defined as a forward reference, 
  6265.  so that an instance of that class can be used within the definition of 
  6266.  "myCurrentClass". The passthru statement also #includes the binding file for 
  6267.  "myOtherClass": 
  6268.  
  6269.   typedef somToken myRealType;
  6270.   typedef somToken myStructType;
  6271.  
  6272.   interface myOtherClass;
  6273.  
  6274.   interface myCurrentClass : SOMObject {
  6275.   . . .
  6276.           implementation {
  6277.                   . . .
  6278.                   myRealType myInstVar;
  6279.                   attribute myStructType st1;
  6280.                   passthru C_h =
  6281.                           ""
  6282.                           "#include <myTypes.h>"
  6283.                           "#include <myOtherClass.h>"
  6284.                           "";
  6285.           };
  6286.   };
  6287.  
  6288.  Note: See also the section "Using the tk_foreign TypeCode" in Chapter 7, "The 
  6289.  Interface Repository Framework." 
  6290.  
  6291.  
  6292. ΓòÉΓòÉΓòÉ 5.2.9. Comments within a SOM IDL file ΓòÉΓòÉΓòÉ
  6293.  
  6294. SOM IDL supports both C and C++ comment styles. The characters "//" start a 
  6295. line comment, which finishes at the end of the current line. The characters 
  6296. "/*" start a block comment that finishes with the "*/". Block comments do not 
  6297. nest. The two comment styles can be used interchangeably. 
  6298.  
  6299. Comments in a SOM IDL specification must be strictly associated with particular 
  6300. syntactic elements, so that the SOM Compiler can put them at the appropriate 
  6301. place in the header and implementation files it generates. Therefore, comments 
  6302. may appear only in these locations (in general, following the syntactic unit 
  6303. being commented): 
  6304.  
  6305.      At the beginning of the IDL specification 
  6306.  
  6307.      After a semicolon 
  6308.  
  6309.      Before or after the opening brace of a module, interface statement, 
  6310.       implementation statement, structure definition, or union definition 
  6311.  
  6312.      After a comma that separates parameter declarations or enumeration 
  6313.       members 
  6314.  
  6315.      After the last parameter in a prototype (before the closing parenthesis) 
  6316.  
  6317.      After the last enumeration name in an enumeration definition (before the 
  6318.       closing brace) 
  6319.  
  6320.      After the colon following a case label of a union definition 
  6321.  
  6322.      After the closing brace of an interface statement 
  6323.  
  6324.  Numerous examples of the use of comments can be found in the Tutorial of 
  6325.  Chapter 2. 
  6326.  
  6327.  Because comments appearing in a SOM IDL specification are transferred to the 
  6328.  files that the SOM Compiler generates, and because these files are often used 
  6329.  as input to a programming language compiler, it is best within the body of 
  6330.  comments to avoid using characters that are not generally allowed in comments 
  6331.  of most programming languages. For example, the C language does not allow "*/" 
  6332.  to occur within a comment, so its use is to be avoided, even when using C++ 
  6333.  style comments in the .idl file. 
  6334.  
  6335.  SOM IDL also supports throw-away comments. They may appear anywhere in an IDL 
  6336.  specification, because they are ignored by the SOM Compiler and are not 
  6337.  transferred to any file it generates. Throw-away comments start with the 
  6338.  string "//#" and end at the end of the line. Throw-away comments can be used 
  6339.  to "comment out" portions of an IDL specification. 
  6340.  
  6341.  To disable comment processing (that is, to prevent the SOM Compiler from 
  6342.  transferring comments from the IDL specification to the binding files it 
  6343.  generates), use the -c option of the sc or somc command when running the SOM 
  6344.  Compiler (See Section 4.3, "The SOM Compiler").  When comment processing is 
  6345.  disabled, comment placement is not restricted and comments can appear anywhere 
  6346.  in the IDL specification. 
  6347.  
  6348.  
  6349. ΓòÉΓòÉΓòÉ 5.2.10. Designating 'private' methods and attributes ΓòÉΓòÉΓòÉ
  6350.  
  6351. To designate methods or attributes within an IDL specification as "private," 
  6352. the declaration of the method or attribute must be surrounded with the 
  6353. preprocessor commands #ifdef__PRIVATE__ (with two leading underscores and two 
  6354. following underscores) and #endif. For example, to declare a method "foo" as a 
  6355. private method, the following declaration would appear within the interface 
  6356. statement: 
  6357.  
  6358.    #ifdef __PRIVATE__
  6359.    void foo();
  6360.    #endif
  6361.  
  6362. Any number of methods and attributes can be designated as private, either 
  6363. within a single #ifdef or in separate ones. [Kernighan-Ritchie reference for 
  6364. the C preprocessor: pages 88-92.] 
  6365.  
  6366. When compiling an .idl file, the SOM Compiler normally recognizes only public 
  6367. (nonprivate) methods and attributes, as that is generally all that is needed. 
  6368. To generate header files for client programs that do need to access private 
  6369. methods and attributes, or for use when implementing a class library containing 
  6370. private methods, the -p option should be included when running the SOM 
  6371. Compiler. The resulting header files will then include bindings for private, as 
  6372. well as public, methods and attributes. Both the implementation bindings (.ih 
  6373. or .xih file) and the usage bindings to be #included in the implementation (.h 
  6374. or .xh file) should be generated under the -p option. The -p option is 
  6375. described in the topic "Running the SOM Compiler" later in this chapter. 
  6376.  
  6377. The SOMobjects Toolkit also provides a pdl (Public Definition Language) emitter 
  6378. that can be used with the SOM Compiler to generate a copy of an .idl file which 
  6379. has the portions designated as private removed. The next main section of this 
  6380. chapter describes how to invoke the SOM Compiler and the various emitters. 
  6381.  
  6382.  
  6383. ΓòÉΓòÉΓòÉ 5.2.11. Module declarations to define multiple interfaces in a .idl file ΓòÉΓòÉΓòÉ
  6384.  
  6385. A single .idl file can define multiple interfaces. This allows, for example, a 
  6386. class and its metaclass to be defined in the same file. When a file defines two 
  6387. (or more) interfaces that reference one another, forward declarations can be 
  6388. used to declare the name of an interface before it is defined. This is done as 
  6389. follows: 
  6390.  
  6391. interface class-name ; 
  6392.  
  6393. The actual definition of the interface for "class-name" must appear later in 
  6394. the same .idl file. 
  6395.  
  6396. If multiple interfaces are defined in the same .idl file, and the classes are 
  6397. not a class-metaclass pair, they can be grouped into modules, by using the 
  6398. following syntax: 
  6399.  
  6400. module module-name { definition+ }; 
  6401.  
  6402. where each "definition" is a type declaration, constant declaration, exception 
  6403. declaration, interface statement, or nested module statement. Modules are used 
  6404. to scope identifiers (see below). 
  6405.  
  6406. Alternatively, multiple interfaces can be defined in a single .idl file without 
  6407. using a module to group the interfaces. Whether or not a module is used for 
  6408. grouping multiple interfaces, the languages bindings produced from the .idl 
  6409. file will include support for all of the defined interfaces. 
  6410.  
  6411. Note:  When multiple interfaces are defined in a single .idl file and a module 
  6412.        statement is not used for grouping these interfaces, it is necessary to 
  6413.        use the functionprefix modifier to assure that different names exist for 
  6414.        functions that provide different implementations for a method.  In 
  6415.        general, it is a good idea to always use the functionprefix modifier, 
  6416.        but in this case it is essential. 
  6417.  
  6418.  
  6419. ΓòÉΓòÉΓòÉ 5.2.12. Scooping and name resolution ΓòÉΓòÉΓòÉ
  6420.  
  6421. A .idl file forms a naming scope (or scope). Modules, interface statements, 
  6422. structures, unions, methods, and exceptions form nested scopes. An identifier 
  6423. can only be defined once in a particular scope. Identifiers can be redefined in 
  6424. nested scopes. 
  6425.  
  6426. Names can be used in an unqualified form within a scope, and the name will be 
  6427. resolved by successively searching the enclosing scopes. Once an unqualified 
  6428. name is defined in an enclosing scope, that name cannot be redefined. 
  6429.  
  6430. Fully qualified names are of the form: 
  6431.  
  6432. scoped-name::identifier 
  6433.  
  6434. For example, method name "meth" defined within interface "Test" of module "M1" 
  6435. would have the fully qualified name: 
  6436.  
  6437.   M1::Test::meth
  6438.  
  6439. A qualified name is resolved by first resolving the "scoped-name" to a 
  6440. particular scope S, then locating the definition of "identifier" within that 
  6441. scope. Enclosing scopes of S are not searched. 
  6442.  
  6443. Qualified names of the form: 
  6444.  
  6445. ::identifier 
  6446.  
  6447. These names are resolved by locating the definition of "identifier" within the 
  6448. smallest enclosing module. 
  6449.  
  6450. Every name defined in an IDL specification is given a global name, constructed 
  6451. as follows: 
  6452.  
  6453.      Before the SOM Compiler scans an .idl file, the name of the current root 
  6454.       and the name of the current scope are empty. As each module is 
  6455.       encountered, the string "::" and the module name are appended to the name 
  6456.       of the current root. At the end of the module, they are removed. 
  6457.  
  6458.      As each interface, struct, union, or exception definition is encountered, 
  6459.       the string "::" and the associated name are appended to the name of the 
  6460.       current scope. At the end of the definition, they are removed. While 
  6461.       parameters of a method declaration are processed, a new unnamed scope is 
  6462.       entered so that parameter names can duplicate other identifiers. 
  6463.  
  6464.      The global name of an IDL definition is then the concatenation of the 
  6465.       current root, the current scope, a "::", and the local name for the 
  6466.       definition. 
  6467.  
  6468.  The names of types, constants, and exceptions defined by the parents of a 
  6469.  class are accessible in the child class. References to these names must be 
  6470.  unambiguous. Ambiguities can be resolved  by using a scoped name (prefacing 
  6471.  the name with the name of the class that defines it and the characters "::", 
  6472.  as in "parent-class::identifier). Scope names can also be used to refer to a 
  6473.  constant, type, or exception name defined by a parent class but redefined by 
  6474.  the child class. 
  6475.  
  6476.  
  6477. ΓòÉΓòÉΓòÉ 5.2.12.1. Name usage in client programs ΓòÉΓòÉΓòÉ
  6478.  
  6479. Within a C or C++ program, the global name for a type, constant, or exception 
  6480. corresponding to an IDL scoped name is derived by converting the string "::" to 
  6481. an underscore ("_") and removing the leading underscore. Such names are 
  6482. referred to as C-scoped names. This means that types, constants, and exceptions 
  6483. defined within the interface statement for a class can be referenced in a C/C++ 
  6484. program by prepending the class name to the name of the type, constant, or 
  6485. exception. For example, consider the types defined in the following IDL 
  6486. specification: 
  6487.  
  6488.    typedef sequence<long,10> mySeq;
  6489.    interface myClass : SOMObject
  6490.    {
  6491.       enum color {red, white, blue};
  6492.       typedef string<100> longString;
  6493.       ...
  6494.    }
  6495.  
  6496. These types could be accessed within a C or C++ program with the following 
  6497. global names: 
  6498.  
  6499. mySeq,
  6500. myClass_color,
  6501. myClass_red,
  6502. myClass_white,
  6503. myClass_blue, and
  6504. myClass_longString.
  6505.  
  6506. Type, constant, and exception names defined within modules similarly have the 
  6507. module name prepended. When using SOM's C/C++ bindings, the short form of type, 
  6508. constant, and exception names (such as, color, longString) can also be used 
  6509. where unambiguous, except that enumeration names must be referred to using the 
  6510. long form (for example, myClass_red and not simply red). 
  6511.  
  6512. Because replacing "::" with an underscore to create global names can lead to 
  6513. ambiguity if an IDL identifier contains underscores, it is best to avoid the 
  6514. use of underscores when defining IDL identifiers. 
  6515.  
  6516.  
  6517. ΓòÉΓòÉΓòÉ 5.2.13. Extensions to CORBA IDL permitted by SOM IDL ΓòÉΓòÉΓòÉ
  6518.  
  6519. The following topics describe several SOM-unique extensions of the standard 
  6520. CORBA syntax that are permitted by SOM IDL for convenience. These constructs 
  6521. can be used in an .idl file without generating a SOM Compiler error. 
  6522.  
  6523. If you want to verify that an IDL file contains only standard CORBA 
  6524. specifications, the SOM Compiler option -mcorba turns off each of these 
  6525. extensions and produces compiler errors wherever non-CORBA specifications are 
  6526. used. (The SOM Compiler command and options are described in the topic "Running 
  6527. the SOM Compiler" later in this chapter.) 
  6528.  
  6529.  
  6530. ΓòÉΓòÉΓòÉ 5.2.13.1. Pointer '*' types ΓòÉΓòÉΓòÉ
  6531.  
  6532. In addition to the base CORBA types, SOM IDL permits the use of pointer types 
  6533. ('*'). As well as increasing the range of base types available to the SOM IDL 
  6534. programmer, using pointer types also permits the construction of more complex 
  6535. data types, including self-referential and mutually recursive structures and 
  6536. unions. 
  6537.  
  6538. If self-referential structures and unions are required, then, instead of using 
  6539. the CORBA approach for IDL sequences, such as the following: 
  6540.  
  6541.    struct X {
  6542.        ...
  6543.        sequence <X> self;
  6544.        ...
  6545.    };
  6546.  
  6547. it is possible to use the more typical C/C++ approach. For example: 
  6548.  
  6549.    struct X {
  6550.        ...
  6551.        X *self;
  6552.        ...
  6553.    };
  6554.  
  6555. SOM IDL does not permit an explicit '*' in sequence declarations. If a sequence 
  6556. is required for a pointer type, then it is necessary to typedef the pointer 
  6557. type before use.  For example: 
  6558.  
  6559.    sequence <long *> long_star_seq;        // error.
  6560.  
  6561.    typedef long * long_star;
  6562.    sequence <long_star> long_star_seq;      // OK.
  6563.  
  6564.  
  6565. ΓòÉΓòÉΓòÉ 5.2.13.2. Unsigned types ΓòÉΓòÉΓòÉ
  6566.  
  6567. SOM IDL permits the syntax "unsigned <type>", where <type> is a previously 
  6568. declared type mapping onto "short" or "long".  (Note that CORBA permits only 
  6569. "unsigned short" and "unsigned long".) 
  6570.  
  6571.  
  6572. ΓòÉΓòÉΓòÉ 5.2.13.3. Implementation section ΓòÉΓòÉΓòÉ
  6573.  
  6574. SOM IDL permits an implementation section in an IDL interface specification to 
  6575. allow the addition of instance variables, method overrides, metaclass 
  6576. information, passthru information, and "pragma-like" information, called 
  6577. modifiers, for the emitters. See the topic "Implementation statements" earlier 
  6578. in this chapter. 
  6579.  
  6580.  
  6581. ΓòÉΓòÉΓòÉ 5.2.13.4. Comment processing ΓòÉΓòÉΓòÉ
  6582.  
  6583. The SOM IDL Compiler by default does not remove comments in the input source; 
  6584. instead, it attaches them to the nearest preceding IDL statement. This facility 
  6585. is useful, since it allows comments to be emitted in header files, C template 
  6586. files, documentation files, and so forth. However, if this capability is 
  6587. desired, this does mean that comments cannot be placed with quite as much 
  6588. freedom as with an ordinary IDL compiler. To turn off comment processing so 
  6589. that you can compile .idl files containing comments placed anywhere, you can 
  6590. use the compiler option -c or use "throw-away" comments throughout the .idl 
  6591. file (that is, comments preceded by //#); as a result, no comments will be 
  6592. included in the output files. 
  6593.  
  6594.  
  6595. ΓòÉΓòÉΓòÉ 5.2.13.5. Generated header files ΓòÉΓòÉΓòÉ
  6596.  
  6597. CORBA expects one header file, <file>.h, to be generated from <file>.idl. 
  6598. However, SOM IDL permits use of a class modifier, filestem, that changes this 
  6599. default output file name.  (See "Running the SOM Compiler" later in this 
  6600. chapter.) 
  6601.  
  6602.  
  6603. ΓòÉΓòÉΓòÉ 5.3. The SOM Compiler ΓòÉΓòÉΓòÉ
  6604.  
  6605. The SOM Compiler translates the IDL definition of a SOM class into a set of 
  6606. "binding files" appropriate for the language that will implement the class's 
  6607. methods and the language(s) that will use the class. These bindings make it 
  6608. more convenient for programmers to implement and use SOM classes. The SOM 
  6609. Compiler currently produces binding files for the C and C++ languages. 
  6610.  
  6611. Important Note: C and C++ bindings can not both be generated during the same 
  6612. execution of the SOM compiler. 
  6613.  
  6614.  
  6615. ΓòÉΓòÉΓòÉ 5.3.1. Generating binding files ΓòÉΓòÉΓòÉ
  6616.  
  6617. The SOM Compiler operates in two phases: 
  6618.  
  6619.      A precompile phase, in which a precompiler analyzes an OIDL or IDL class 
  6620.       definition, and 
  6621.  
  6622.      An emission phase, in which one or more  emitter programs produce 
  6623.       binding files. 
  6624.  
  6625.  Each binding file is generated by a separate emitter program. Setting the 
  6626.  SMEMIT environment variable determines which emitters will be used, as 
  6627.  described below. Note: In the discussion below, the <filesystem> is determined 
  6628.  by default from the name of the source .idl file with the ".idl" extension 
  6629.  removed. Otherwise, a "filestem" modifier can be defined in the .idl file to 
  6630.  specify another file name (see "Modifier statements" above). 
  6631.  
  6632.  Note: If changes to definitions in the .idl file later become necessary, the 
  6633.  SOM Compiler should be rerun to update the current implementation template 
  6634.  file, provided that the c or xc emitter is specified (either with the -s 
  6635.  option or the SMEMIT environment variable, as described below). For more 
  6636.  information on generating updates, see "Running incremental updates of the 
  6637.  implementation template file" later in this chapter. 
  6638.  
  6639.  The emitters for the C language produce the following binding files: 
  6640.  
  6641.  <filestem>.c             (produced by the c emitter) 
  6642.  
  6643.                           This is a template for a C source program that 
  6644.                           implements a class's methods. This will become the 
  6645.                           primary source file for the class. (The other binding 
  6646.                           files can be generated from the .idl file as needed.) 
  6647.                           This template implementation file contains "stub" 
  6648.                           procedures for each method introduced or overridden 
  6649.                           by the class. (The stub procedures are empty of code 
  6650.                           except for required initialization and debugging 
  6651.                           statements.) 
  6652.  
  6653.                           After the class implementer has supplied the code for 
  6654.                           the method procedures, running the c emitter again 
  6655.                           will update the implementation file to reflect 
  6656.                           changes made to the class definition (in the .idl 
  6657.                           file). These updates include adding new stub 
  6658.                           procedures, adding comments, and changing method 
  6659.                           prototypes to reflect changes made to the method 
  6660.                           definitions in the IDL specification. Existing code 
  6661.                           within method procedures is not disturbed, however. 
  6662.  
  6663.                           The .c file contains an #include directive for the 
  6664.                           .ih file, described below. 
  6665.  
  6666.                           The contents of the C source template is controlled 
  6667.                           by the Emitter Framework file 
  6668.                           <SOMBASE>/include/ctm.efw. This file can be 
  6669.                           customized to change the template produced. For 
  6670.                           detailed information on changing the template file 
  6671.                           see the Emitter Framework Guide and Reference. 
  6672.  
  6673.  <filestem>.h             (produced by the h emitter) 
  6674.  
  6675.                           This is the header file to be included by C client 
  6676.                           programs (programs that use the class). It contains 
  6677.                           the C usage bindings for the class, including macros 
  6678.                           for accessing the class's methods and a macro for 
  6679.                           creating new instances of the class. This header file 
  6680.                           includes the header files for the class's parent 
  6681.                           classes and its metaclass, as well as the header file 
  6682.                           that defines SOM's generic C bindings, som.h. 
  6683.  
  6684.  <filestem>.ih            (produced by the ih emitter) 
  6685.  
  6686.                           This is the header file to be included in the 
  6687.                           implementation file (the file that implements the 
  6688.                           class's methods-the .c file). It contains the 
  6689.                           implementation bindings for the class, including: 
  6690.  
  6691.                               a struct defining the class's instance 
  6692.                                variables, 
  6693.                               macros for accessing instance variables, 
  6694.                               macros for invoking parent methods the class 
  6695.                                overrides, 
  6696.                               the <className>GetData  macro used by the method 
  6697.                                procedures in the <filestem>.c file (see "Stub 
  6698.                                procedures for methods" in Section 5.4 of 
  6699.                                Chapter 5.) 
  6700.                               a <className>NewClass procedure for constructing 
  6701.                                the class object at run time, and 
  6702.                               any IDL types and constants defined in the IDL 
  6703.                                interface. 
  6704.  
  6705.  The emitters for the C++ language produce the following binding files: 
  6706.  
  6707.  <filestem>.C (for AIX) or  <filestem>.cpp (for OS/2) (produced by the xc 
  6708.                           emitter) 
  6709.  
  6710.                           This is a template for a C++ source program that 
  6711.                           implements a class's methods. This will become the 
  6712.                           primary source file for the class. (The other binding 
  6713.                           files can be generated from the .idl file as needed.) 
  6714.                           This template implementation file contains "stub" 
  6715.                           procedures for each method introduced or overridden 
  6716.                           by the class. (The stub procedures are empty of code 
  6717.                           except for required initialization and debugging 
  6718.                           statements.) 
  6719.  
  6720.                           After the class implementer has supplied the code for 
  6721.                           the method procedures, running the xc emitter again 
  6722.                           will update this file to reflect changes made to the 
  6723.                           class definition (in the .idl file). These updates 
  6724.                           include adding new stub procedures, adding comments, 
  6725.                           and changing method prototypes to reflect changes 
  6726.                           made to the method definitions in the IDL 
  6727.                           specification. Existing code within method procedures 
  6728.                           is not disturbed, however. 
  6729.  
  6730.                           The C++ implementation file contains an #include 
  6731.                           directive for the .xih file, described below. 
  6732.  
  6733.                           The contents of the C++ source template is controlled 
  6734.                           by the Emitter Framework file 
  6735.                           <SOMBASE>/include/ctm.efw. This file can be 
  6736.                           customized to change the template produced. For 
  6737.                           detailed information on changing the template file 
  6738.                           see the Emitter Framework Guide and Reference. 
  6739.  
  6740.  <filestem>.xh            (produced by the xh emitter) 
  6741.  
  6742.                           This is the header file to be included by C++ client 
  6743.                           programs that use the class. It contains the usage 
  6744.                           bindings for the class, including a C++ definition of 
  6745.                           the class, macros for accessing the class's methods, 
  6746.                           and the new operator for creating new instances of 
  6747.                           the class. This header file includes the header files 
  6748.                           for the class's parent classes and its metaclass, as 
  6749.                           well as the header file that defines SOM's generic 
  6750.                           C++ bindings, som.xh. 
  6751.  
  6752.  <filestem>.xih           (produced by the xih emitter) 
  6753.  
  6754.                           This is the header file to be included in the 
  6755.                           implementation file (the file that implements the 
  6756.                           class's methods). It contains the implementation 
  6757.                           bindings for the class, including: 
  6758.  
  6759.                               a struct defining the class's instance 
  6760.                                variables, 
  6761.                               macros for accessing instance variables, 
  6762.                               macros for invoking parent methods the class 
  6763.                                overrides, 
  6764.                               the <className>GetData  macro (see section 5.4), 
  6765.                               a <className>NewClass procedure for constructing 
  6766.                                the class object at run time, and 
  6767.                               any IDL types and constants defined in the IDL 
  6768.                                interface. 
  6769.  
  6770.  Other files the SOM Compiler generates: 
  6771.  
  6772.  <filestem>.hh            (produced by the hh emitter) 
  6773.  
  6774.                           This file is a DirectToSOM C++ header file that 
  6775.                           describes a SOMobjects class in a way appropriate to 
  6776.                           DTS C++. When running this emitter, you must include 
  6777.                           the noqualitytypes command-line modifier for the -m 
  6778.                           optionof the SOM Compiler command sc or somc. 
  6779.  
  6780.  <filestem>pdl            (produced by the pdl emitter) This file is the same 
  6781.                           as the .idl file from which it is produced except 
  6782.                           that all items within the .idl file that are marked 
  6783.                           as "private" have been removed.  (an item is marked 
  6784.                           as private by surrounding it with "#ifdef_PRIVATE_" 
  6785.                           and "#endif" directives.  Thus, the pdl (Public 
  6786.                           Definition Lnguage) emitter can be used to generate a 
  6787.                           "public" version of the .idl file. 
  6788.  
  6789.  <filestem>.def (for OS/2) (produced by the def emitter) 
  6790.  
  6791.                           This file is used by the linker to package a class as 
  6792.                           a library. To combine several classes into a single 
  6793.                           library, you must merge the exports statements from 
  6794.                           each of their .def  files into a single .def file for 
  6795.                           the entire library. When packaging multiple classes 
  6796.                           in a single library, you must also write a simple C 
  6797.                           procedure named SOMInitModule and add it to the 
  6798.                           export list. This procedure should call the routine 
  6799.                           <className>NewClass for each class packaged in the 
  6800.                           library. The SOMInitModule procedure is called by the 
  6801.                           SOM Class Manager when the library is dynamically 
  6802.                           loaded. 
  6803.  
  6804.  <filestem>.exp  (for AIX) (produced by the exp emitter) 
  6805.  
  6806.                           This file is used by the linker to package a class as 
  6807.                           a library. To combine several classes into a single 
  6808.                           library, you must merge the exports statements from 
  6809.                           each of their .exp  files into a single .exp file for 
  6810.                           the entire library. When packaging multiple classes 
  6811.                           in a single library, you must also write a simple C 
  6812.                           procedure named SOMInitModule and add it to the 
  6813.                           export list. This procedure should call the routine 
  6814.                           <className>NewClass for each class packaged in the 
  6815.                           library The SOMInitModule procedure is called by the 
  6816.                           SOM Class Manager when the library is dynamically 
  6817.                           loaded. 
  6818.  
  6819.  The Interface Repository (produced by the ir emitter) 
  6820.  
  6821.                           See Chapter 7 for a discussion on the Interface 
  6822.                           Repository. 
  6823.  Note: The C/C++ bindings generated by the SOM Compiler have the following 
  6824.  limitation: If two classes named "ClassName" and "ClassNameC" are defined, the 
  6825.  bindings for these two classes will clash. That is, if a client program uses 
  6826.  the C/C++ bindings (includes the .h/.xh header file) for both classes, a name 
  6827.  conflict will occur. Thus, class implementers should keep this limitation in 
  6828.  mind when naming their classes. 
  6829.  
  6830.  SOM users can extend the SOM Compiler to generate additional files by writing 
  6831.  their own emitters. To assist users in extending the SOM Compiler, SOM 
  6832.  provides an Emitter Framework a collection of classes and methods useful for 
  6833.  writing object-oriented emitters that the SOM Compiler can invoke. For more 
  6834.  information, see the Emitter Framework Guide and Reference. 
  6835.  
  6836.  Note re:  porting SOM classes: The header files (binding files) that the SOM 
  6837.  Compiler generates will only work on the platform (operating system) on which 
  6838.  they were generated. Thus, when porting SOM classes from the platform where 
  6839.  they were developed to another platform, the header files must be regenerated 
  6840.  from the .idl file by the SOM Compiler on that target platform. 
  6841.  
  6842.  
  6843. ΓòÉΓòÉΓòÉ 5.3.2. Environment variables affecting the SOM Compiler ΓòÉΓòÉΓòÉ
  6844.  
  6845. To execute the SOM Compiler on one or more files that contain IDL 
  6846. specifications for one or more classes, use the sc. or somc as follows: 
  6847.  
  6848. sc [-options] files       (on AIX or OS/2) 
  6849.  
  6850.  
  6851. somc [-options] files         (on Windows) 
  6852.  
  6853. where "files" specifies one or more .idl files. 
  6854.  
  6855. Available "-options" for the command are detailed in the next topic. The 
  6856. operation of the SOM Compiler (whether it produces C binding files or C++ 
  6857. binding files, for example) is also controlled by a set of environment 
  6858. variables that can be set before the sc command is issued. The applicable 
  6859. environment variables are as follows: 
  6860.  
  6861.  SMEMIT              Determines which output files the SOM Compiler produces. 
  6862.                      Its value consists of a list of items separated by 
  6863.                      semicolons for OS/2, or by semicolons or colons for AIX. 
  6864.                      Each item designates an emitter to execute.  For example, 
  6865.                      the statement: 
  6866.  
  6867.                      SET SMEMIT=c;h;ih             (for OS/2, for C binding 
  6868.                                                    files) 
  6869.                      export SMEMIT="c;h;ih"        (for AIX) 
  6870.  
  6871.                      directs the SOM Compiler to produce the C binding files 
  6872.                      "hello.c", "hello.h", and"hello.ih" from the "hello.idl" 
  6873.                      input specification. By comparison, 
  6874.  
  6875.                      SET SMEMIT=xc;xh;xih          (for OS/2) 
  6876.                      export SMEMIT="xc;xh;xih"     (for AIX) 
  6877.  
  6878.                      directs the SOM Compiler to produce C++ binding files 
  6879.                      "hello.C" (for AIX) or "hello.cpp" (for OS/2), "hello.xh", 
  6880.                      and "hello.xih" from the "hello.idl" input specification. 
  6881.  
  6882.                      By default, all output files are placed in the same 
  6883.                      directory as the input file. If the SMEMIT environment 
  6884.                      variable is not set, then a default value of "h;ih" is 
  6885.                      assumed. 
  6886.  
  6887.                      Windows note: The SMEMIT environmental variable can be set 
  6888.                      by using the SET command before the somc command is 
  6889.                      issued.  For example: 
  6890.  
  6891.                                             SET SMEMIT="c;h;ih"             (for Windows)
  6892.  
  6893.                      If you are running the SOM Compiler from a DOS box under 
  6894.                      Windows, make sure to define SMEMIT before Windows is 
  6895.                      started. 
  6896.  
  6897.  SMINCLUDE           Specifies where the SOM Compiler should look for .idl 
  6898.                      files #included by the .idl file being compiled. Its value 
  6899.                      should be one or more directory names separated by a 
  6900.                      semicolon when using OS/2, or separated by a semicolon or 
  6901.                      colon when using AIX. Directory names can be specified 
  6902.                      with absolute or relative pathnames. For example: 
  6903.  
  6904.                      SET SMINCLUDE=.;..\MYSCDIR;C:\TOOLKT20\C\INCLUDE; (for 
  6905.                                                    OS/2 or Windows) 
  6906.  
  6907.                      export SMINCLUDE=.:myscdir:/u/som/include (for AIX) 
  6908.  
  6909.                      The default value of the SMINCLUDE environment variable is 
  6910.                      the "include" subdirectory of the directory into which SOM 
  6911.                      has been installed. 
  6912.  
  6913.  SMTMP               Specifies the directory that the SOM Compiler should use 
  6914.                      to hold intermediate output files. This directory should 
  6915.                      not coincide with the directory of the input or output 
  6916.                      files. For AIX, the default setting of SMTMP is /tmp; for 
  6917.                      OS/2, the default setting of SMTMP is the root directory 
  6918.                      of the current drive. 
  6919.  
  6920.                      OS/2 or Windows example: 
  6921.  
  6922.                                              SET SMTMP=..\MYSCDIR\GARBAGE
  6923.  
  6924.                      tells the SOM Compiler to place the temporary files in the 
  6925.                      GARBAGE directory. 
  6926.  
  6927.  
  6928.                      Or, on OS/2 only: 
  6929.  
  6930.                                              SET SMTMP=%TMP%
  6931.  
  6932.                      tells the SOM Compiler to use the same directory for 
  6933.                      temporary files as given by the setting of the TMP 
  6934.                      environment variable (the defult location for temporary 
  6935.                      system files). (On Windows, you cannot set one variable to 
  6936.                      another.) 
  6937.  
  6938.                      AIX example: 
  6939.  
  6940.                                              export SMTMP=$TMP
  6941.                                              export SMTMP=../myscdir/garbage
  6942.  
  6943.  SMKNOWNEXTS         Specifies additional emitters to which the SOM Compiler 
  6944.                      should add a header. For example, if you were to write a 
  6945.                      new emitter for Pascal, called "emitpas", then by default 
  6946.                      the SOM Compiler would not add any header comments to it. 
  6947.                      However, by setting SMKNOWNEXTS=pas, as shown: 
  6948.  
  6949.                        set SMKNOWNEXTS=pas         (for OS/2 or Windows) 
  6950.  
  6951.                        export SMKNOWNEXTS=pas      (for AIX) 
  6952.  
  6953.                      the SOM Compiler will add a header to files generated with 
  6954.                      the "emitpas" emitter. The "header" added is a SOM 
  6955.                      Compiler-generated message plus any comments, such as 
  6956.                      copyright statements, that appear at the head of your .idl 
  6957.                      input file. For details on writing your own emitter, see 
  6958.                      the Emitter Framework Guide and Reference. 
  6959.  
  6960.  SOMIR               Specifies the name (or list of names) of the Interface 
  6961.                      Repository file. The ir emitter, if run, creates the 
  6962.                      Interface Repository, or checks it for consistency if it 
  6963.                      already exists. If the -u option is specified when 
  6964.                      invoking the SOM Compiler, the ir emitter also updates an 
  6965.                      existing Interface Repository. 
  6966.  
  6967.  SMADDSTAR           When defined, causes all interface references to have a 
  6968.                      "*" added to them for the C bindings. The command-line 
  6969.                      options -maddstar and -mnoaddstar supercede and override 
  6970.                      the SMADDSTAR setting, however. 
  6971.  
  6972.  Note:  Environment variables that affect the SOM Compiler can be set for any 
  6973.         -m options of the SOM Compiler command. See the -m option in the 
  6974.         following topic, "Running the SOM Compiler." Also, the -E option in the 
  6975.         following topic can be used to set an environment variable. 
  6976.  
  6977.  
  6978. ΓòÉΓòÉΓòÉ 5.3.3. Running the SOM Compiler ΓòÉΓòÉΓòÉ
  6979.  
  6980. The syntax of the command for running the SOM Compiler takes the forms: 
  6981.  
  6982. sc  [-options] files 
  6983.  
  6984.  
  6985. somc[-options] files 
  6986.  
  6987. The "files" specified in the sc or somc command denote one or more files 
  6988. containing the IDL class definitions to be compiled. If no extension is 
  6989. specified, .idl is assumed. By default, the <filestem> of the .idl file 
  6990. determines the filestem of each emitted file. Otherwise, a "filestem" modifier 
  6991. can be defined in the .idl file to specify another name (see "Modifier 
  6992. statements" discussed earlier). 
  6993.  
  6994. Selected "-options" can be specified individually, as a string of option 
  6995. characters, or as a combination of both. Any option that takes an argument 
  6996. either must be specified individually or must appear as the final option in a 
  6997. string of option characters. Available options and their purposes are as 
  6998. follows: 
  6999.  
  7000.  -C n        Sets the maximum allowable size for a simple comment in the .idl 
  7001.              file (default: 32767). This is only needed for very large single 
  7002.              comments. 
  7003.  
  7004.  -D name[=def] Defines name as in a #define directive. The default def is 1. 
  7005.              This option is the same as the -D option for the C compiler. Note: 
  7006.              This option can be used to define __PRIVATE__ so that the SOM 
  7007.              Compiler will also compile any methods and attributes that have 
  7008.              been defined as private using the directive  #ifdef__PRIVATE__; 
  7009.              however, the -p option does the same thing more easily. When a 
  7010.              class contains private methods or attributes, both the 
  7011.              implementation bindings and the usage bindings to be #included in 
  7012.              the implementation should be generated using either the -p or 
  7013.              -D_PRIVATE_ option. 
  7014.  
  7015.  -E variable=value Sets an environment variable. (See the previous topic for a 
  7016.              discussion of the available environment variables: SMADDSTAR, 
  7017.              SMEMIT, SMINCLUDE, SMTMP, SMKNOWNEXTS, and SOMIR.) 
  7018.  
  7019.  -I dir      When looking for #included files, looks first in dir, then in the 
  7020.              standard directories (same as the C compiler -I option). 
  7021.  
  7022.  -S n        Sets the total allowable amount of unique string space used in the 
  7023.              IDL specification for names and passthru lines (default: 32767). 
  7024.              This is only needed for very large .idl files. 
  7025.  
  7026.  -U name     Removes any initial definition (via a #define preprocessor 
  7027.              directive) of symbol name. 
  7028.  
  7029.  -V          Displays version information about the SOM Compiler. 
  7030.  
  7031.  -c          Turns off comment processing. This allows comments to appear 
  7032.              anywhere within an IDL specification (rather than in restricted 
  7033.              places), and it causes comments not to be transferred to the 
  7034.              output files that the SOM Compiler produces. 
  7035.  
  7036.  -d  directory Specifies a directory where all output files should be placed. 
  7037.              If the -d option is not used, all output files are placed in the 
  7038.              same directory as the input file. 
  7039.  
  7040.  -h or -?    Produces a listing of this option list. (This option is typically 
  7041.              used in an sc or somc command that does not include a .idl file 
  7042.              name) 
  7043.  
  7044.  -i filename Specifies the name of the class definition file. Use this option 
  7045.              to override the built-in assumption that the input file will have 
  7046.              a .idl extension. Any filename supplied with the -i option is used 
  7047.              exactly as it is specified. 
  7048.  
  7049.  -m name[=value] Adds a global modifier. (See the following Note on the -m 
  7050.              options, which explains how to convert any "-m name" modifier to 
  7051.              an environment variable.) 
  7052.  
  7053.              Note:  All command-line -m modifier options can be specified in 
  7054.                     the environment by changing them to UPPERCASE and 
  7055.                     prepending " SM" to them. For example, if you want to 
  7056.                     always set the options "-mnotc" and "-maddstar", set 
  7057.                     corresponding environment variables as follows: 
  7058.  
  7059.                     On OS/2: 
  7060.  
  7061.                                             set SMNOTC=1
  7062.                                             set SMADDSTAR=1
  7063.  
  7064.                     On AIX: 
  7065.  
  7066.                                             export SMNOTC=1
  7067.                                             export SMADDSTAR=1
  7068.  
  7069.              The currently supported global modifiers for the -m name[=value] 
  7070.              option are as follows: 
  7071.  
  7072.              addprefixes         Adds 'functionprefixes' to the method 
  7073.                                  procedure prototypes during an incremental 
  7074.                                  update of the implementation template file. 
  7075.                                  This option applies only when rerunning the c 
  7076.                                  or xc emitter on an IDL file that previously 
  7077.                                  did not specify a functionprefix. A class 
  7078.                                  implementor who later decides to use prefixes 
  7079.                                  should add a line in the 'implementation' 
  7080.                                  section of the .idl file containing the 
  7081.                                  specification: 
  7082.  
  7083.                                  functionprefix = prefix 
  7084.  
  7085.                                  (as described earlier in the topic "Modifier 
  7086.                                  statements") and then rerun the c or xc 
  7087.                                  emitter using the -maddprefixes option. The 
  7088.                                  method procedure prototypes in the 
  7089.                                  implementation file will then be updated so 
  7090.                                  that each method name includes the assigned 
  7091.                                  prefix. (This option does not support changes 
  7092.                                  to existing prefix names, nor does it apply 
  7093.                                  for OIDL files.) 
  7094.  
  7095.              addstar             This option causes all interface references to 
  7096.                                  have a '*' added to them for the C bindings. 
  7097.                                  See the earlier section entitled "Object 
  7098.                                  types" for further details. 
  7099.  
  7100.              comment=comment string where comment string can be either of the 
  7101.                                  designations: "/*"  or "//". This option 
  7102.                                  indicates that comments marked in the 
  7103.                                  designated manner in the .idl file are to be 
  7104.                                  completely ignored by the SOM Compiler and 
  7105.                                  will not be included in the output files. 
  7106.                                  Note: Comments on lines beginning with "//#" 
  7107.                                  are always ignored by the SOM Compiler. 
  7108.  
  7109.              corba               This option directs the SOM Compiler to 
  7110.                                  compile the input definition according to 
  7111.                                  strict CORBA-defined IDL syntax. This means, 
  7112.                                  for example, that comments may appear anywhere 
  7113.                                  and that pointers are not allowed. When the 
  7114.                                  -mcorba option is used, parts of a .idl file 
  7115.                                  surrounded by #ifdef__SOMIDL__ and #endif 
  7116.                                  directives are ignored. This option can be 
  7117.                                  used to determine whether all nonstandard 
  7118.                                  constructs (those specific to SOM IDL) are 
  7119.                                  properly protected by #ifdef__SOMIDL__ and 
  7120.                                  #endif directives. 
  7121.  
  7122.              csc                 This option forces the OIDL compiler to be 
  7123.                                  run. This is required only if you want to 
  7124.                                  compile an OIDL file that does not have an 
  7125.                                  extension of .csc or .sc. 
  7126.  
  7127.              emitappend          This option causes emitted files to be 
  7128.                                  appended at the end of existing files of the 
  7129.                                  same name. 
  7130.  
  7131.              noaccessors         This option turns off the automatic creation 
  7132.                                  of OperationDef entries in the Interface 
  7133.                                  Repository for attribute accessors (that is, 
  7134.                                  for an attribute's _set and _get methods). 
  7135.  
  7136.              noaddstar           This option ensures that interface references 
  7137.                                  will not have a "*" added to them for the C 
  7138.                                  bindings. This is the default setting; it is 
  7139.                                  the opposite of the -m compiler option 
  7140.                                  addstar. 
  7141.  
  7142.              noint               This option directs the SOM Compiler not to 
  7143.                                  warn about the portability problems of using 
  7144.                                  int's in the source. 
  7145.  
  7146.              nolock              This option causes the Interface Repository 
  7147.                                  Emitter emitir (see Chapter 7, "Interface 
  7148.                                  Repository Framework") to leave the IR 
  7149.                                  unlocked when updates are made to it. This can 
  7150.                                  improve performance on networked file systems. 
  7151.                                  By not locking the IR, however, there is the 
  7152.                                  risk of multiple processes attempting to write 
  7153.                                  to the same IR, with unpredictable results. 
  7154.                                  This option should only be used when you know 
  7155.                                  that only one process is updating an IR at 
  7156.                                  once. 
  7157.  
  7158.              nopp                This option directs the SOM Compiler not to 
  7159.                                  run the SOM preprocessor on the .idl input 
  7160.                                  file. 
  7161.  
  7162.              noqualifytypes      This option prevents the use od C-scoped names 
  7163.                                  in emitter output, and is used in conjunction 
  7164.                                  with the .hh emitter. 
  7165.  
  7166.              notc                This option directs the SOM Compiler not to 
  7167.                                  create TypeCode information when emitting IDL 
  7168.                                  files that contain some undeclared types. This 
  7169.                                  option is only used when compiling converted 
  7170.                                  .csc files (that is, OIDL files originally) 
  7171.                                  that have not had typing information added. 
  7172.  
  7173.              nouseshort          This option directs the SOM Compiler not to 
  7174.                                  generate short forms for type names in the .h 
  7175.                                  and .xh public header files. This can be 
  7176.                                  useful to save disk space. 
  7177.  
  7178.              pbl                 This option tells the SOM Compiler that, in 
  7179.                                  declarations containing a linkage specifier, 
  7180.                                  the "*" will appear before the linkage 
  7181.                                  specifier. This is required when using any C++ 
  7182.                                  compiler (Watcom is a known example) that 
  7183.                                  cannot handle declarations in the default 
  7184.                                  format where the "*" follows the linkage 
  7185.                                  specifier. A default example is the 
  7186.                                  declaration: 
  7187.  
  7188.                                                                   typedef void (SOMLINK * somTD_SOMObject_somFree)
  7189.                                                                                (SOMObject *somSelf);
  7190.  
  7191.                                  Under the -mpbl option of the SOM Compiler 
  7192.                                  command, the same example would be declared 
  7193.                                  as: 
  7194.  
  7195.                                                                   typedef void (* SOMLINK somTD_SOMObject_somFree)
  7196.                                                                                (SOMObject *somSelf);
  7197.  
  7198.              pp=preprocessor     This option directs the SOM Compiler to use 
  7199.                                  the specified preprocessor as the SOM 
  7200.                                  preprocessor, rather than the default 
  7201.                                  "somcpp". Any standard C/C++ preprocessor can 
  7202.                                  be used as a preprocessor for IDL 
  7203.                                  specifications. 
  7204.  
  7205.              tcconsts            This option directs the SOM Compiler to 
  7206.                                  generate TypeCode constants in the h and .xh 
  7207.                                  public header files. Please refer to the 
  7208.                                  Interface Repository (described in Chapter 7) 
  7209.                                  for more details. 
  7210.  
  7211.  -p          Causes the "private" sections of the IDL file to be included in 
  7212.              the compilation (that is, sections preceded by #ifdef __PRIVATE__ 
  7213.              that contain private methods and attributes). Note: If -p is used, 
  7214.              it must be applied for both the implementation bindings (.ih or 
  7215.              .xih file) and the usage bindings (.h or .xh file) to be #included 
  7216.              in the implementation. 
  7217.  
  7218.  -r          Checks that all names specified in the release order statement are 
  7219.              valid method names (default: FALSE). 
  7220.  
  7221.  -s string   Substitutes string in place of the contents of the SMEMIT 
  7222.              environment variable for the duration of the current sc command. 
  7223.              This determines which emitters will be run and, hence, which 
  7224.              output files will be produced. (If a list of values is given, on 
  7225.              OS/2 only the list must be enclosed in double quotes.) 
  7226.  
  7227.              The -s option is a convenient way to override the SMEMIT 
  7228.              environment variable. In OS/2 for example, the command: 
  7229.  
  7230.                              > SC -s"h;c" EXAMPLE
  7231.  
  7232.              is equivalent to the following sequence of commands: 
  7233.  
  7234.                              > SET OLDSMEMIT=%SMEMIT%
  7235.                              > SET SMEMIT=H;C
  7236.                              > SC EXAMPLE
  7237.                              > SET SMEMIT=%OLDSMEMIT%
  7238.  
  7239.              Similarly, in AIX the command: 
  7240.  
  7241.                              > sc -sh";"c example
  7242.  
  7243.              is equivalent to the following sequence of commands: 
  7244.  
  7245.                              > export OLDSMEMIT=$SMEMIT
  7246.                              > export SMEMIT=h";"c
  7247.                              > sc example
  7248.                              > export SMEMIT=$OLDSMEMIT
  7249.  
  7250.  -u          Updates the Interface Repository (default: no update). With this 
  7251.              option, the Interface Repository will be updated even if the ir 
  7252.              emitter is not explicitly requested in the SMEMIT environment 
  7253.              variable or the -s option. 
  7254.  
  7255.  -v          Uses verbose mode to display informational messages (default: 
  7256.              FALSE). This option is primarily intended for debugging purposes 
  7257.              and for writers of emitters. 
  7258.  
  7259.  -w          Suppresses warning messages (default: FALSE). 
  7260.  
  7261.  The following sample commands illustrate various options for the sc command or 
  7262.  similarly with somc): 
  7263.  
  7264.  sc -sc hello.idl         Generates file "hello.c". 
  7265.  
  7266.  sc -hV                   Generates a help message and displays the version of 
  7267.                           the SOM Compiler currently available. 
  7268.  
  7269.  sc -vsh";"ih hello.idl   Generates "hello.h" and "hello.ih" with informational 
  7270.                           messages. 
  7271.  
  7272.  sc -sxc -doutdir hello.idl Generates "hello.xc" in directory "outdir". 
  7273.  
  7274.  
  7275. ΓòÉΓòÉΓòÉ 5.4. The 'pdl' Facility ΓòÉΓòÉΓòÉ
  7276.  
  7277. As discussed earlier in this chapter, the SOM Compiler provides a pdl (Public 
  7278. Definition Language) emitter. This emitter generates a file that is the same as 
  7279. the .idl file from which it is produced, except that it removes all items 
  7280. within the .idl file that are marked as "private." An item is marked as private 
  7281. by surrounding it with "#ifdef_ _PRIVATE_ _" and "#endif" directives. Thus, the 
  7282. pdl emitter can be used to generate a "public" version of a .idl file. 
  7283. (Generally, client programs will need only the "public" methods and 
  7284. attributes.) 
  7285.  
  7286. The SOMobjects Toolkit also provides a separate program, pdl, which performs 
  7287. the same function as the pdl emitter, but can be invoked independently of the 
  7288. SOM Compiler. In addition, the pdl program can remove any kind of items in the 
  7289. .idl file that are preceded by a user-specified "#ifdef" directive and followed 
  7290. by an "#endif" directive:  The pdl  program is invoked as follows: 
  7291.  
  7292.         pdl [ -c | d | f | h | s |/]  files 
  7293.  
  7294.  where "files" specifies one or more .idl files whose specified "#ifdef" 
  7295.  sections are to be removed.  Filenames must be completely specified (with the 
  7296.  .idl extension).  If no "#ifdef" directive is specified (by including a 
  7297.  -/<string> option), then the "#ifdef_ _PRIVATE_ __"sections will be removed by 
  7298.  default. 
  7299.  
  7300.  The pdl command supports the following options.  (Selected options can be 
  7301.  specified individually, as a string of option characters, or as a combination 
  7302.  of both. Any option that takes an argument either must be specified 
  7303.  individually or must appear as the final option in a string of option 
  7304.  characters.) 
  7305.  
  7306.  -c cmd      Specifies that, for each .idl file, the pdl program is to run the 
  7307.              specified system command. This command may contain a single 
  7308.              occurrence of the string "%s", which will be replaced with the 
  7309.              source file name before the command is executed. For example the 
  7310.              option -c"sc -sh %s" has the same effect as issuing the sc command 
  7311.              with the -sh option. 
  7312.  
  7313.  -d dir      Specifies a directory in which the output files are to be placed. 
  7314.              (The output files are given the same name as the input files.) If 
  7315.              no directory is specified, the output files are named 
  7316.              <fileStem>.pdl (where fileStem is the file stem of the input file) 
  7317.              and are placed in the current working directory. 
  7318.  
  7319.  -h          Requests this description of the pdl command syntax and options. 
  7320.  
  7321.  -f          Specifies that output files are to replace existing files with the 
  7322.              same name, even if the existing files are read-only. By default, 
  7323.              files are replaced only if they have write access. 
  7324.  
  7325.  -s smemit   Specifies the SMEMIT variable with which the pdl program is to 
  7326.              invoke the SOM Compiler. 
  7327.  
  7328.  -/ <string> Specifies the "#ifdef" pattern for which the pdl program will 
  7329.              strip out .idl statements. The default is "#ifdef _ _PRIVATE_ _". 
  7330.  
  7331.  For example, to install public versions of the .idl files in the directory 
  7332.  "pubinclude", type: 
  7333.  
  7334.      pdl -d pubinclude *.idl
  7335.  
  7336.  
  7337. ΓòÉΓòÉΓòÉ 6. Implementing Classes in SOM ΓòÉΓòÉΓòÉ
  7338.  
  7339. This chapter begins with a more in-depth discussion of SOM concepts and the SOM 
  7340. run-time environment than was appropriate in Tutorial for Implementing SOM 
  7341. Classes. Subsequent sections then provide information about completing an 
  7342. implementation template file, updating the template file, compiling and 
  7343. linking, packaging classes in libraries, and other useful topics for class 
  7344. implementors. During this process, you can refer to Chapter 4, "SOM IDL and the 
  7345. SOM Compiler," if you want to read the reference information or see the full 
  7346. syntax related to topics discussed in this chapter. The current chapter ends 
  7347. with topics describing how to customize SOMobjects execution in various ways. 
  7348.  
  7349.  
  7350. ΓòÉΓòÉΓòÉ 6.1. The SOM Run-Time Environment ΓòÉΓòÉΓòÉ
  7351.  
  7352. The SOMobjects Developer Toolkit provides 
  7353.  
  7354.      The SOM Compiler, used when creating SOM class libraries, and 
  7355.  
  7356.      The SOM run-time library, for using SOM classes at execution time. 
  7357.  
  7358.  The SOM run-time library provides a set of functions used primarily for 
  7359.  creating objects and invoking methods on them. The data structures and objects 
  7360.  that are created, maintained, and used by the functions in the SOM run-time 
  7361.  library constitute the SOM run-time environment. 
  7362.  
  7363.  A distinguishing characteristic of the SOM run-time environment is that SOM 
  7364.  classes are represented by run-time objects; these objects are called class 
  7365.  objects.  By contrast, other object-oriented languages such as C++ treat 
  7366.  classes strictly as compile-time structures that have no properties at run 
  7367.  time. In SOM, however, each class has a corresponding run-time object. This 
  7368.  has three advantages:  First, application programs can access information 
  7369.  about a class at run time, including its relationships with other classes, the 
  7370.  methods it supports, the size of its instances, and so on. Second, because 
  7371.  much of the information about a class is established at run time rather than 
  7372.  at compile time, application programs needn't be recompiled when this 
  7373.  information changes. Finally, because class objects can be instances of 
  7374.  user-defined classes in SOM, users can adapt the techniques for subclassing 
  7375.  and inheritance in order to build object-oriented solutions to problems that 
  7376.  are otherwise not easily addressed within an OOP context. 
  7377.  
  7378.  
  7379. ΓòÉΓòÉΓòÉ 6.1.1. Run-time environment initialization ΓòÉΓòÉΓòÉ
  7380.  
  7381. When the SOM run-time environment is initialized, four primitive SOM objects 
  7382. are automatically created. Three of these are class objects (SOMObject, 
  7383. SOMClass, and SOMClassMgr), and one is an instance of SOMClassMgr, called the 
  7384. SOMClassMgrObject. Once loaded, application programs can invoke methods on 
  7385. these class objects to perform tasks such as creating other objects, printing 
  7386. the contents of an object, freeing objects, and the like. These four primitive 
  7387. objects are discussed below. 
  7388.  
  7389. In addition to creating the four primitive SOM objects, initialization of the 
  7390. SOM run-time environment also involves initializing global variables to hold 
  7391. data structures that maintain the state of the environment.  Other functions in 
  7392. the SOM run-time library rely on these global variables. 
  7393.  
  7394. For application programs written in C or C++ that use the language-specific 
  7395. bindings provided by SOM, the SOM run-time environment is automatically 
  7396. initialized the first time any object is created.  Programmers using other 
  7397. languages must initialize the run-time environment explicitly by calling the 
  7398. somEnvironmentNew function (provided by the SOM run-time library) before using 
  7399. any other SOM functions or methods. 
  7400.  
  7401.  
  7402. ΓòÉΓòÉΓòÉ 6.1.1.1. SOMObject class object ΓòÉΓòÉΓòÉ
  7403.  
  7404. SOMObject is the root class for all SOM classes. It defines the essential 
  7405. behavior common to all SOM objects.  All user-defined SOM classes are derived, 
  7406. directly or indirectly, from this class. That is, every SOM class is a subclass 
  7407. of SOMObject or of some other class derived from SOMObject. SOMObject has no 
  7408. instance variables, thus objects that inherit from SOMObject incur no size 
  7409. increase. They do inherit a suite of methods that provide the behavior required 
  7410. of all SOM objects. 
  7411.  
  7412.  
  7413. ΓòÉΓòÉΓòÉ 6.1.1.2. SOMClass class object ΓòÉΓòÉΓòÉ
  7414.  
  7415. Because SOM classes are run-time objects, and since all run-time objects are 
  7416. instances of some class, it follows that a SOM class object must also be an 
  7417. instance of some class. The class of a class is called a metaclass. Hence, the 
  7418. instances of an ordinary class are individuals (nonclasses), while the 
  7419. instances of a metaclass are class objects. 
  7420.  
  7421. In the same way that the class of an object defines the "instance methods" that 
  7422. the object can perform, the metaclass of a class defines the "class methods" 
  7423. that the class itself can perform. Class methods (sometimes called factory 
  7424. methods or constructors) are performed by class objects. Class methods perform 
  7425. tasks such as creating new instances of a class, maintaining a count of the 
  7426. number of instances of the class, and other operations of a "supervisory" 
  7427. nature. Also, class methods facilitate inheritance of instance methods from 
  7428. parent classes. For information on the distinction between parent classes and 
  7429. metaclasses, see the section "Parent Class vs. metaclass," later in this 
  7430. chapter. 
  7431.  
  7432. SOMClass is the root class for all SOM metaclasses.  That is, all SOM 
  7433. metaclasses must be subclasses of SOMClass or of some metaclass derived from 
  7434. SOMClass. SOMClass defines the essential behavior common to all SOM class 
  7435. objects.  In particular, SOMClass provides: 
  7436.  
  7437.      Six class methods for creating new class instances: somNew, somNewNoInit, 
  7438.       somRenew, somRenewNoInit, somRenewNoZero  and somRenewNoInitNoZero. 
  7439.  
  7440.      A number of class methods that dynamically obtain or update information 
  7441.       about a class and its methods at run time, including: 
  7442.  
  7443.         -  somInitMIClass, for implementing multiple inheritance from parent 
  7444.            classes, 
  7445.  
  7446.         -  somOverrideSMethod, for overriding inherited methods, and 
  7447.  
  7448.         -  somAddStaticMethod and somAddDynamicMethod, for including new 
  7449.            methods. 
  7450.  
  7451.  SOMClass is a subclass (or child) of SOMObject. Hence, SOM class objects can 
  7452.  also perform the same set of basic instance methods common to all SOM objects. 
  7453.  This is what allows SOM classes to be real objects in the SOM run-time 
  7454.  environment. SOMClass also has the unique distinction of being its own 
  7455.  metaclass (that is, SOMClass defines its own class methods). 
  7456.  
  7457.  A user-defined class can designate as its metaclass either SOMClass or another 
  7458.  user-written metaclass descended from SOMClass. If a metaclass is not 
  7459.  explicitly specified, SOM determines one automatically. 
  7460.  
  7461.  
  7462. ΓòÉΓòÉΓòÉ 6.1.1.3. SOMClassMgr class object and SOMClassMgrObject ΓòÉΓòÉΓòÉ
  7463.  
  7464. The third primitive SOM class is SOMClassMgr. A single instance of the 
  7465. SOMClassMgr class is created automatically during SOM initialization. This 
  7466. instance is referred to as the SOMClassMgrObject, because it is pointed to by 
  7467. the global variable SOMClassMgrObject. The object SOMClassMgrObject has the 
  7468. responsibility to 
  7469.  
  7470.      Maintain a registry (a run-time directory) of all SOM classes that exist 
  7471.       within the current process, and to 
  7472.  
  7473.      Assist in the dynamic loading and unloading of class libraries. 
  7474.  
  7475.  For C/C++ application programs using the SOM C/C++ language bindings, the 
  7476.  SOMClassMgrObject automatically loads the appropriate library file and 
  7477.  constructs a run-time object for the class the first time an instance of a 
  7478.  class is created. For programmers using other languages, SOMClassMgr provides 
  7479.  a method, somFindClass, for directing the SOMClassMgrObject to load the 
  7480.  library file for a class and create its class object. 
  7481.  
  7482.  Again, the primitive classes supplied with SOM are SOMObject, SOMClass, and 
  7483.  SOMClassMgr.  During SOM initialization, the latter class generates an 
  7484.  instance called SOMClassMgrObject. The SOMObject class is the parent class of 
  7485.  SOMClass and SOMClassMgr. The SOMClass class is the metaclass of itself, of 
  7486.  SOMObject, and of SOMClassMgr, which are all class objects at run time. 
  7487.  SOMClassMgr is the class of SOMClassMgrObject. 
  7488.  
  7489.  
  7490. ΓòÉΓòÉΓòÉ 6.1.2. Parent class vs. metaclass ΓòÉΓòÉΓòÉ
  7491.  
  7492. There is a distinct difference between the notions of "parent" (or base) class 
  7493. and "metaclass." Both notions are related to the fact that a class defines the 
  7494. methods and variables of its instances, which are therefore called instance 
  7495. methods and instance variables. 
  7496.  
  7497. A parent of a given class is a class from which the given class is derived  by 
  7498. subclassing. (Thus, the given class is called a child or a subclass  of the 
  7499. parent.) A parent class is a class from which instance methods and instance 
  7500. variables are inherited. For example, the parent of class "Dog" might be class 
  7501. "Animal". Hence, the instance methods and variables introduced by "Animal" 
  7502. (such as methods for breathing and eating, or a variable for storing an 
  7503. animal's weight) would also apply to instances of "Dog", because "Dog" inherits 
  7504. these from "Animal", its parent class. As a result, any given dog instance 
  7505. would be able to breath and eat, and would have a weight. 
  7506.  
  7507. A metaclass is a class whose instances are class objects, and whose instance 
  7508. methods and instance variables (as described above) are therefore the methods 
  7509. and variables of class objects. For this reason, a metaclass is said to define 
  7510. class methods-the methods that a class object performs. For example, the 
  7511. metaclass of "Animal" might be "AnimalMClass", which defines the methods that 
  7512. can be invoked on class "Animal" (such as, to create Animal instances-objects 
  7513. that are not classes, like an individual pig or cat or elephant or dog). 
  7514.  
  7515. Note: It is important to distinguish the methods of a class object (that is, 
  7516. the methods that can be invoked on the class object, which are defined by its 
  7517. metaclass) from the methods that the class defines for its instances. 
  7518.  
  7519. To summarize: the parent of a class provides inherited methods that the class's 
  7520. instances can perform; the metaclass of a class provides class methods that the 
  7521. class itself can perform.  These distinctions are further summarized below: The 
  7522. distinctions between parent class and metaclass are summarized in A class has 
  7523. both parent classes and a metaclass. 
  7524.  
  7525.  
  7526. A class has both parent classes and a metaclass
  7527.  
  7528. Any class "C" has both a metaclass and one or more parent class(es). 
  7529.  
  7530.      The parent class(es) of "C" provide the inherited instance methods that 
  7531.       individual instances (objects "O{i}") of class "C" can perform. Instance 
  7532.       methods that an instance "O{i}" performs might include (a) initializing 
  7533.       itself, (b) performing computations using its instance variables, (c) 
  7534.       printing its instance variables, or (d) returning its size. New instance 
  7535.       methods are defined by "C" itself, in addition to those inherited from 
  7536.       C's parent classes. 
  7537.  
  7538.      The metaclass "M"defines the class methods that class "C" can perform. 
  7539.       For example, class methods defined by metaclass "M" include those that 
  7540.       allow "C" to (a) inherit its parents' instance methods and instance 
  7541.       variables, (b) tell its own name, (c) create new instances, and (d) tell 
  7542.       how many instance methods it supports. These methods are inherited from 
  7543.       SOMClass. Additional methods supported by "M" might allow "C" to count 
  7544.       how many instances it creates. 
  7545.  
  7546.      Each class "C" has one or more parent classes and exactly one metaclass. 
  7547.       (The single exception is SOMObject, which has no parent class.)  Parent 
  7548.       class(es) must be explicitly identified in the IDL declaration of a 
  7549.       class. (SOMObject is given as a parent if no subsequently-derived class 
  7550.       applies.)  If a metaclass is not explicitly listed, the SOM run time will 
  7551.       determine an applicable metaclass. 
  7552.  
  7553.      An instance of a metaclass is always another class object. For example, 
  7554.       class "C" is an instance of metaclass "M".  SOMClass is the SOM-provided 
  7555.       metaclass from which all subsequent metaclasses are derived. 
  7556.  
  7557.  A metaclass has its own inheritance hierarchy (through its parent classes) 
  7558.  that is independent of its instances' inheritance hierarchies. For example, 
  7559.  suppose a series of classes is defined (or derived), stemming from SOMObject. 
  7560.  The child class (or subclass) at the end of this line ("C[2]") inherits 
  7561.  instance methods from all of its ancestor classes (here, SOMObject  and 
  7562.  "C[1]"). An instance created by "C2" can perform any of these instance 
  7563.  methods.  In an analogous manner, a line of metaclasses can be defined, 
  7564.  stemming from SOMClass. Just as a new class is derived from an existing class 
  7565.  (such as SOMObject), a new metaclass is derived from an existing metaclass 
  7566.  (such as SOMClass). 
  7567.  
  7568.  
  7569.   Parent classes and metaclasses each have their own
  7570.   independent inheritance hierrarchies
  7571.  
  7572.  
  7573. ΓòÉΓòÉΓòÉ 6.1.3. SOM-derived metaclasses ΓòÉΓòÉΓòÉ
  7574.  
  7575. As previously discussed, a class object can perform any of the class methods 
  7576. that its metaclass defines. New metaclasses are typically created to modify 
  7577. existing class methods or introduce new class method(s). Chapter 8, "Metaclass 
  7578. Framework," discusses metaclass programming. 
  7579.  
  7580. Three factors are essential for effective use of metaclasses in SOM: 
  7581.  
  7582.      First, every class in SOM is an object that is implemented by a 
  7583.       metaclass. 
  7584.  
  7585.      Second, programmers can define and name new metaclasses, and can use 
  7586.       these metaclasses when defining new SOM classes. 
  7587.  
  7588.      Finally, and most importantly, metaclasses cannot interfere with the 
  7589.       fundamental guarantee required of every OOP system: specifically, any 
  7590.       code that executes without method-resolution error on instances of a 
  7591.       given class will also execute without method-resolution errors on 
  7592.       instances of any subclass of this class. 
  7593.  
  7594.  Surprisingly, SOM is currently the only OOP system that can make this final 
  7595.  guarantee while also allowing programmers to explicitly define and use named 
  7596.  metaclasses. This is possible because SOM automatically determines an 
  7597.  appropriate metaclass that supports this guarantee, automatically deriving new 
  7598.  metaclasses by subclassing at run time when this is necessary. As an example, 
  7599.  suppose class "A" is an instance of metaclass "AMeta". 
  7600.  
  7601.  Assume that "AMeta" supports a method "bar" and that "A" supports a method 
  7602.  "foo" that uses the expression "_bar( _somGetClass(somSelf ) )." That is, 
  7603.  method "foo" invokes "bar" on the class of the object on which "foo" is 
  7604.  invoked. For example, when method "foo" is invoked on an instance of class "A" 
  7605.  (say, object "O{1}"), this in turn invokes "bar" on class "A" itself. 
  7606.  
  7607.  Now consider what happens if class "A" were subclassed by "B," a class that 
  7608.  has the explicit metaclass "BMeta" declared in its SOM IDL source file (and 
  7609.  assuming "BMeta" is not derived from "AMeta"). Also assume that object "O{2}" 
  7610.  is an instance of class "B." 
  7611.  
  7612.  Recall that "AMeta" supports method "bar" and that class "A" supports method 
  7613.  "foo" (which incorporates "bar" in its definition). Given the hierarchy 
  7614.  described above, an invocation of "foo" on "O {2}" would fail, because 
  7615.  metaclass "BMeta" does not support the "bar" method. 
  7616.  
  7617.  
  7618.   Example of Metaclass Incompatibility
  7619.  
  7620.  There is only one way that "BMeta" can support this specific method-by 
  7621.  inheriting it from "AMeta" ("BMeta" could introduce another method named 
  7622.  "bar", but this would be a different method from the one introduced by 
  7623.  "AMeta"). Therefore, in this example, because "BMeta" is not a subclass of 
  7624.  "AMeta", "BMeta" cannot be allowed to be the metaclass of "B". That is, 
  7625.  "BMeta" is not compatible with the requirements placed on "B" by the 
  7626.  fundamental principle of OOP referred to above. This situation is referred to 
  7627.  as metaclass incompatibility. 
  7628.  
  7629.  SOM does not allow hierarchies with metaclass incompatibilities. Instead, SOM 
  7630.  automatically builds derived metaclasses when this is necessary. For example, 
  7631.  SOM would create a "DerivedMeta" metaclass that has both "AMeta" and "BMeta" 
  7632.  as parents. This ensures that the invocation of method "foo" on instances of 
  7633.  class "B" will not fail, and also ensures that the desired class methods 
  7634.  provided by "BMeta" will be available on class "B". 
  7635.  
  7636.  
  7637.   Example of a Derived Metaclass
  7638.  
  7639.  There are three important aspects of SOM's approach to derived metaclasses: 
  7640.  
  7641.      First, the creation of SOM-derived metaclasses is integrated with 
  7642.       programmer-specified metaclasses. If a programmer-specified metaclass 
  7643.       already supports all the class methods and variables needed by a new 
  7644.       class, then the programmer-specified metaclass will be used as is. 
  7645.  
  7646.      Second, if SOM must derive a different metaclass than the one explicitly 
  7647.       indicated by the programmer (in order to support all the necessary class 
  7648.       methods and variables), then the SOM-derived metaclass inherits from the 
  7649.       explicitly indicated metaclass first. As a result, the method procedures 
  7650.       defined by the specified metaclass take precedence over other 
  7651.       possibilities (see the following section on inheritance and the 
  7652.       discussion of resolution of ambiguity in the case of multiple 
  7653.       inheritance). 
  7654.  
  7655.      Finally, the class methods defined by the derived metaclass invoke the 
  7656.       appropriate initialization methods of its parents to ensure that the 
  7657.       class variables of its instances are correctly initialized. 
  7658.  
  7659.  As further explanation for the automatic derivation of metaclasses, consider 
  7660.  the following multiple-inheritance example. Class "C" (derived from classes 
  7661.  "A" and "B") does not have an explicit metaclass declaration in its SOM IDL, 
  7662.  yet its parents "A" and "B" do. As a result, class "C" requires a derived 
  7663.  metaclass. (If you still have trouble following the reasoning behind derived 
  7664.  metaclasses, ask yourself the following question: What class should "C" be an 
  7665.  instance of? After a bit of reflection, you will conclude that, if SOM did not 
  7666.  build the derived metaclass, you would have to do so yourself.) 
  7667.  
  7668.  
  7669.   Multiple Inheritance requires Derived Metaclasses
  7670.  
  7671.  In summary, SOM allows and encourages the definition and explicit use of named 
  7672.  metaclasses. With named metaclasses, programmers can not only affect the 
  7673.  behavior of class instances by choosing the parents of classes, but they can 
  7674.  also affect the behavior of the classes themselves by choosing their 
  7675.  metaclasses.  Because the behavior of classes in SOM includes the 
  7676.  implementation of inheritance itself, metaclasses in SOM provide an extremely 
  7677.  flexible and powerful capability allowing classes to package solutions to 
  7678.  problems that are otherwise very difficult to address within an OOP context. 
  7679.  
  7680.  At the same time, SOM is unique in that it relieves programmers of the 
  7681.  responsibility for avoiding metaclass incompatibility when defining a new 
  7682.  class. At first glance, this might seem to be merely a useful (though very 
  7683.  important) convenience. But, in fact, it is absolutely essential, because SOM 
  7684.  is predicated on binary compatibility with respect to changes in class 
  7685.  implementations. 
  7686.  
  7687.  A programmer might, at one point in time, know the metaclasses of all ancestor 
  7688.  classes of a new subclass, and, as a result, be able to explicitly derive an 
  7689.  appropriate metaclass for the new class. Nevertheless, SOM must guarantee that 
  7690.  this new class will still execute and perform correctly when any of its 
  7691.  ancestor class's implementations are changed (which could even include 
  7692.  specifying different metaclasses). Derived metaclasses allow SOM to make this 
  7693.  guarantee.  A SOM programmer need never worry about the problem of metaclass 
  7694.  incompatibility; SOM does this for the programmer. Instead, explicit 
  7695.  metaclasses can simply be used to "add in" whatever behavior is desired for a 
  7696.  new class. SOM automatically handles anything else that is needed. Chapter 10 
  7697.  provides useful examples of such metaclasses. A SOM programmer should find 
  7698.  numerous applications for the techniques that are illustrated there. 
  7699.  
  7700.  
  7701. ΓòÉΓòÉΓòÉ 6.2. Inheritance ΓòÉΓòÉΓòÉ
  7702.  
  7703. One of the defining aspects of an object model is its characterization of 
  7704. inheritance. This section describes SOM's model for inheritance. 
  7705.  
  7706. A class in SOM defines an implementation for objects that support a specific 
  7707. interface: 
  7708.  
  7709.      The interface defines the methods supported by objects of the class, and 
  7710.       is specified using SOM IDL. 
  7711.  
  7712.      The implementation  defines what instance variables implement an object's 
  7713.       state and what procedures implement its methods. 
  7714.  
  7715.  New classes are derived (by subclassing) from previously existing classes 
  7716.  through inheritance, specialization, and addition.  Subclasses inherit 
  7717.  interface from their parent classes: any method available on instances of a 
  7718.  class is also available on instances of any class derived from it (either 
  7719.  directly or indirectly).  Subclasses also inherit implementation (the 
  7720.  procedures that implement the methods) from their parent classes unless the 
  7721.  methods are overridden (redefined or specialized). In addition, a subclass may 
  7722.  introduce new instance methods and instance variables that will be inherited 
  7723.  by other classes derived from it. 
  7724.  
  7725.  SOM also supports multiple inheritance. That is, a class may be derived from 
  7726.  (and may inherit interface and implementation from) multiple parent classes. 
  7727.  Note: Multiple inheritance is available only to SOM classes whose interfaces 
  7728.  are specified in IDL, and not to SOM classes whose interfaces are specified in 
  7729.  SOM's earlier interface definition language, OIDL. See Appendix B for 
  7730.  information on how to automatically convert existing OIDL files to IDL. 
  7731.  
  7732.  It is possible under multiple inheritance to encounter potential conflicts or 
  7733.  ambiguities with respect to inheritance. All multiple inheritance models must 
  7734.  face these issues, and resolve the ambiguities in some way. For example, when 
  7735.  multiple inheritance is allowed, it is possible that a class will inherit the 
  7736.  same method or instance variable from different parents (because each of these 
  7737.  parents has some common ancestor that introduces the method or instance 
  7738.  variable). In this situation, a SOM subclass inherits only one implementation 
  7739.  of the method or instance variable. (The implementation of an instance 
  7740.  variable within an object is just the location where it is stored. The 
  7741.  implementation of a method is a procedure pointer, stored within a method 
  7742.  table.) The following illustration addresses the question of which method 
  7743.  implementation would be inherited. 
  7744.  
  7745.  Consider this situation: Class "W" defines a method "foo", implemented by 
  7746.  procedure "proc1". Class "W" has two subclasses, "X" and "Y". Subclass "Y" 
  7747.  overrides the implementation of "foo" with procedure "proc2". Subclass "X" 
  7748.  does not override "foo". In addition, classes "X" and "Y" share a common 
  7749.  subclass, "Z". That is, the IDL interface statement for class "Z" lists its 
  7750.  parents as "X" and "Y" in that order. (These relationships form a diamond 
  7751.  shape, with class "W" at the top.) 
  7752.  
  7753.  The question is thus: which implementation of method "foo" does class "Z" 
  7754.  inherit-procedure "proc1" defined by class "W", or procedure "proc2" defined 
  7755.  by class "Y"? The procedure for performing inheritance that is defined by 
  7756.  SOMClass resolves this ambiguity by using the left path precedence rule: when 
  7757.  the same method is inherited from multiple ancestors, the procedure used to 
  7758.  support the method is the one used by the leftmost ancestor from which the 
  7759.  method is inherited. (The ordering of parent classes is determined by the 
  7760.  order in which the class implementor lists the parents in the IDL 
  7761.  specification for the class.) 
  7762.  
  7763.  Class "Z" inherits the implementation of method "foo" defined by class "W" 
  7764.  (procedure "proc1"), rather than the implementation defined by class "Y" 
  7765.  (procedure "proc2"), because "X" is the leftmost ancestor of "Z" from which 
  7766.  the method "foo" is inherited. This rule may be interpreted as giving priority 
  7767.  to classes whose instance interfaces are mentioned first in IDL interface 
  7768.  definitions. 
  7769.  
  7770.  If a class implementor decides that the default inherited implementation is 
  7771.  not appropriate (for example, procedure "proc2" is desired), then SOM IDL 
  7772.  allows the class designer to select the parent whose implementation is 
  7773.  desired. For more information concerning this approach, see the Select 
  7774.  modifier, which is documented in the topic "Modifier statements" in Chapter 4, 
  7775.  "SOM IDL and the SOM Compiler." 
  7776.  
  7777.  Note:  Alternatively, an explicit metaclass for "Z" could be introduced to 
  7778.         change the way methods are inherited. However, this would be a fairly 
  7779.         serious step to take-it would also affect the semantics of inheritance 
  7780.         for all of Z's descendant classes. 
  7781.  
  7782.  Another conflict that may arise with the use of multiple inheritance is when 
  7783.  two ancestors of a class define different methods (in general, with different 
  7784.  signatures) of the same name. For example, suppose Class "X" defines a method 
  7785.  "bar" with type T1, and class "Y" defines a method "bar" with type T2. Class 
  7786.  "Z" is derived from both "X" and "Y", and "Z" does not override method "bar". 
  7787.  
  7788.  This example illustrates a method name that is "overloaded"-that is, used to 
  7789.  name two entirely different methods (note that overloading is completely 
  7790.  unrelated to overriding). This is not necessarily a difficult problem to 
  7791.  handle. Indeed, the run-time SOM API allows the construction of a class that 
  7792.  supports the two different "bar" methods. (They are implemented using two 
  7793.  different method-table entries, each of which is associated with its 
  7794.  introducing class.) 
  7795.  
  7796.  However, the interface to instances of such classes can not be defined using 
  7797.  IDL. IDL specifically forbids the definition of interfaces in which method 
  7798.  names are overloaded.  Furthermore, within SOM itself, the use of such classes 
  7799.  can lead to anomalous behavior unless care is taken to avoid the use of 
  7800.  name-lookup method resolution (discussed in the following section), since, in 
  7801.  this case, a method name alone does not identify a unique method. For this 
  7802.  reason, (statically declared) multiple-inheritance classes in SOM are 
  7803.  currently restricted to those whose instance interfaces can be defined using 
  7804.  IDL. Thus, the above example cannot be constructed with the aid of the SOM 
  7805.  Compiler. 
  7806.  
  7807.  
  7808. ΓòÉΓòÉΓòÉ 6.3. Method Resolution ΓòÉΓòÉΓòÉ
  7809.  
  7810. Method resolution is the step of determining which procedure to execute in 
  7811. response to a method invocation. For example, consider this scenario: 
  7812.  
  7813.      Class "Dog" introduces a method "bark", and 
  7814.  
  7815.      A subclass of "Dog", called "BigDog", overrides "bark", and 
  7816.  
  7817.      A client program creates an instance of either "Dog" or "BigDog" 
  7818.       (depending on some run-time criteria) and invokes method "bark" on that 
  7819.       instance. 
  7820.  
  7821.  Method resolution is the process of determining, at run time, which method 
  7822.  procedure to execute in response to the method invocation (either the method 
  7823.  procedure for "bark" defined by "Dog", or the method procedure for "bark" 
  7824.  defined by "BigDog"). This determination depends on whether the receiver of 
  7825.  the method (the object on which it is invoked) is an instance of "Dog" or 
  7826.  "BigDog" (or perhaps depending on some other criteria). 
  7827.  
  7828.  SOM allows class implementors and client programs considerable flexibility in 
  7829.  deciding how SOM performs method resolution. In particular, SOM supports three 
  7830.  mechanisms for method resolution, described in order of increased flexibility 
  7831.  and increased computational cost: offset resolution, name-lookup resolution, 
  7832.  and dispatch-function resolution. 
  7833.  
  7834.  
  7835. ΓòÉΓòÉΓòÉ 6.3.1. Offset resolution ΓòÉΓòÉΓòÉ
  7836.  
  7837. When using SOM's C and C++ language bindings, offset resolution is the default 
  7838. way of resolving methods, because it is the fastest. For those familiar with 
  7839. C++, it is roughly equivalent to the C++ "virtual function" concept. 
  7840.  
  7841. Although offset resolution is the fastest technique for method resolution, it 
  7842. is also the most constrained. Specifically, using offset resolution requires 
  7843. these constraints: 
  7844.  
  7845.      The name of the method to be invoked must be known at compile time, 
  7846.  
  7847.      The name of the class that introduces the method must be known at compile 
  7848.       time (although not necessarily by the programmer), and 
  7849.  
  7850.      The method to be invoked must be part of the introducing class's static 
  7851.       (IDL) interface definition. 
  7852.  
  7853.  To perform offset method resolution, SOM first obtains a method token from a 
  7854.  global data structure associated with the class that introduced the method. 
  7855.  This data structure is called the ClassData structure. It includes a method 
  7856.  token for each method the class introduces. The method token is then used as 
  7857.  an "index" into the receiver's method table, to access the appropriate method 
  7858.  procedure. Because it is known at compile time which class introduces the 
  7859.  method and where in that class's ClassData structure the method's token is 
  7860.  stored, offset resolution is quite efficient. The cost of offset method 
  7861.  resolution is currently about twice the cost of calling a C function using a 
  7862.  pointer loaded with the function address. 
  7863.  
  7864.  An object's method table is a table of pointers to the procedures that 
  7865.  implement the methods that the object supports. This table is constructed by 
  7866.  the object's class and is shared among the class instances. The method table 
  7867.  built by class (for its instances) is referred to as the class's instance 
  7868.  method table. This is useful terminology, since, in SOM, a class is itself an 
  7869.  object with a method table (created by its metaclass) used to support method 
  7870.  calls on the class. 
  7871.  
  7872.  Usually, offset method resolution is sufficient; however, in some cases, the 
  7873.  more flexible name-lookup resolution is required. 
  7874.  
  7875.  
  7876. ΓòÉΓòÉΓòÉ 6.3.2. Name-lookup resolution ΓòÉΓòÉΓòÉ
  7877.  
  7878. Name-lookup resolution is similar to the method resolution techniques employed 
  7879. by Objective-C and Smalltalk. It is currently about five times slower than 
  7880. offset resolution. It is more flexible, however. In particular, name-lookup 
  7881. resolution, unlike offset resolution, can be used when: 
  7882.  
  7883.      The name of the method to be invoked isn't known until run time, or 
  7884.  
  7885.      The method is added to the class interface at run time, or 
  7886.  
  7887.      The name of the class introducing the method isn't known until run time. 
  7888.  
  7889.  For example, a client program may use two classes that define two different 
  7890.  methods of the same name, and it might not be known until run time which of 
  7891.  the two methods should be invoked (because, for example, it will not be known 
  7892.  until run time which class's instance the method will be applied to). 
  7893.  
  7894.  Name-lookup resolution is always performed by a class, so it requires a method 
  7895.  call. (Offset resolution, by contrast, requires no method calls.) To perform 
  7896.  name-lookup method resolution, the class of the intended receiver object 
  7897.  obtains a method procedure pointer for the desired method  that is appropriate 
  7898.  for its instances. In general, this will require a name-based search through 
  7899.  various data structures maintained by ancestor classes. 
  7900.  
  7901.  Offset and name-lookup resolution achieve the same net effect (that is, they 
  7902.  select the same method procedure); they just achieve it differently (via 
  7903.  different mechanisms for locating the method's method token). Offset 
  7904.  resolution is faster, because it does not require searching for the method 
  7905.  token, but name-lookup resolution is more flexible. 
  7906.  
  7907.  When defining (in SOM IDL) the interface to a class of objects, the class 
  7908.  implementor can decide, for each method, whether the SOM Compiler will 
  7909.  generate usage bindings that support name-lookup resolution for invoking the 
  7910.  method. Regardless of whether this is done, however, application programs 
  7911.  using the class can have SOM use either technique, on a per-method-call basis. 
  7912.  Chapter 3, "Using SOM Classes in Client Programs," describes how client 
  7913.  programs invoke methods. 
  7914.  
  7915.  
  7916. ΓòÉΓòÉΓòÉ 6.3.3. Dispatch-function resolution ΓòÉΓòÉΓòÉ
  7917.  
  7918. Dispatch-function resolution is the slowest, but most flexible, of the three 
  7919. method-resolution techniques. Dispatch functions permit method resolution to be 
  7920. based on arbitrary rules associated with the class of which the receiving 
  7921. object is an instance. Thus, a class implementor has complete freedom in 
  7922. determining how methods invoked on its instances are resolved. 
  7923.  
  7924. With both offset and name-lookup resolution, the net effect is the same-the 
  7925. method procedure that is ultimately selected is the one supported by the class 
  7926. of which the receiver is an instance. For example, if the receiver is an 
  7927. instance of class "Dog", then Dog's method procedure will be selected; but if 
  7928. the receiver is an instance of class "BigDog", then BigDog's method procedure 
  7929. will be selected. 
  7930.  
  7931. By contrast, dispatch-function resolution allows a class of instances to be 
  7932. defined such that the method procedure is selected using some other criteria. 
  7933. For example, the method procedure could be selected on the basis of the 
  7934. arguments to the method call, rather than on the receiver. For more information 
  7935. on dispatch-function resolution, see the description and examples for the 
  7936. somDispatch and somOverrideMTab methods in the SOMobjects Developer Toolkit: 
  7937. Programmers Reference Manual. 
  7938.  
  7939.  
  7940. ΓòÉΓòÉΓòÉ 6.3.4. Customizing Method Resolution ΓòÉΓòÉΓòÉ
  7941.  
  7942. Customizing method resolution requires the use of metaclasses that override 
  7943. SOMClass methods.  This is not recommended without use of the Cooperative 
  7944. Metaclass that guarantees correct operation of SOMobjects in conjunction with 
  7945. such metaclasses.  SOMobjects users who require this functionality should 
  7946. request access to the experimental Cooperative Metaclass used to implement the 
  7947. SOMobjects Metaclass Framework. Metaclasses implemented using the Cooperative 
  7948. Metaclass may have to be reprogrammed in the future when SOMobjects introduces 
  7949. an oficially supported Cooperative Metaclass. 
  7950.  
  7951.  
  7952. ΓòÉΓòÉΓòÉ 6.3.5. The four kinds of SOM methods ΓòÉΓòÉΓòÉ
  7953.  
  7954. SOM supports four different kinds of methods:  static methods, nonstatic 
  7955. methods, dynamic methods, and direct-call procedures. The following paragraphs 
  7956. explain these four method categories and the kinds of method resolution 
  7957. available for each. 
  7958.  
  7959.  
  7960. ΓòÉΓòÉΓòÉ 6.3.5.1. Static methods ΓòÉΓòÉΓòÉ
  7961.  
  7962. These are similar in concept to C++ virtual functions. Static methods are 
  7963. normally invoked using offset resolution via a method table, as described 
  7964. above, but all three kinds of method resolution are applicable to static 
  7965. methods. Each different static method available on an object is given a 
  7966. different slot in the object's method table. When SOMobjects Toolkit language 
  7967. bindings are used to implement a class, the SOM IDL method modifier can be 
  7968. specified to indicate that a given method is static; however, this modifier is 
  7969. rarely used since it is the default for SOM methods. 
  7970.  
  7971. Static methods introduced by a class can be overridden (redefined) by any 
  7972. descendant classes of the class. When SOMobjects language bindings are used to 
  7973. implement a class, the SOM IDL override modifier is specified to indicate that 
  7974. a class overrides a given inherited method. When a static method is resolved 
  7975. using offset resolution, it is not important which interface is accessing the 
  7976. method - the actual class of the object determines the method procedure that is 
  7977. selected. 
  7978.  
  7979. Note:  All SOM IDL modifiers are described in the topic "Modifier statements" 
  7980. in Chapter 4, "SOM IDL and the SOM Compiler." 
  7981.  
  7982.  
  7983. ΓòÉΓòÉΓòÉ 6.3.5.2. Nonstatic methods ΓòÉΓòÉΓòÉ
  7984.  
  7985. These methods are similar in concept to C++ nonstatic member functions (that 
  7986. is, C++ functions that are not virtual member functions and are not static 
  7987. member functions). Nonstatic methods are normally invoked using offset 
  7988. resolution, but all three kinds of method resolution are applicable  to 
  7989. nonstatic methods. When the SOMobjects language bindings are used to implement 
  7990. a class, the SOM IDL nonstatic modifier is used to indicate that a given method 
  7991. is nonstatic. 
  7992.  
  7993. Like static methods, nonstatic methods are given individual positions in method 
  7994. tables. However, nonstatic methods cannot be overridden. Instead, descendants 
  7995. of a class that introduces a nonstatic method can use the SOM IDL reintroduce 
  7996. modifier to "hide" the original nonstatic method with another (nonstatic or 
  7997. static) method of the same name. When a nonstatic method is resolved, selection 
  7998. of the specific method procedure is determined by the interface that is used to 
  7999. access the method. 
  8000.  
  8001.  
  8002. ΓòÉΓòÉΓòÉ 6.3.5.3. Dynamic methods ΓòÉΓòÉΓòÉ
  8003.  
  8004. These methods are not declared when specifying an object interface using IDL. 
  8005. Instead, they are registered with a class object at run time using the method 
  8006. somAddDynamicMethod. Because there is no way for SOM to know about dynamic 
  8007. methods before run time, offset resolution is not available for dynamic 
  8008. methods. Only name-lookup or dispatch-function resolution  can be used to 
  8009. invoke dynamic methods. Dynamic methods cannot be overridden. 
  8010.  
  8011.  
  8012. ΓòÉΓòÉΓòÉ 6.3.5.4. Direct-call procedures ΓòÉΓòÉΓòÉ
  8013.  
  8014. These are similar in concept to C++ static member functions. Direct-call 
  8015. procedures are not given positions in SOM method tables, but are accessed 
  8016. directly from a class's ClassData structure. Strictly speaking, none of the 
  8017. previous method-resolution approaches apply for invoking a direct-call 
  8018. procedure, although SOMobjects language bindings provide the same invocation 
  8019. syntax for direct-call procedures as for static or nonstatic methods. 
  8020. Direct-call procedures cannot be overridden, but they can be reintroduced. When 
  8021. SOMobjects language bindings are used to implement a class, the SOM IDL 
  8022. procedure modifier is used to indicate that a given method is a direct-call 
  8023. procedure. Note: Methods having the procedure modifier cannot be invoked 
  8024. remotely using DSOM. 
  8025.  
  8026.  
  8027. ΓòÉΓòÉΓòÉ 6.4. Implementing SOM Classes ΓòÉΓòÉΓòÉ
  8028.  
  8029. The interface to a class of objects contains the information that a client must 
  8030. know to use an object - namely, the signatures of its methods and the names of 
  8031. its attributes. The interface is described in a formal language independent of 
  8032. the programming language used to implement the object's methods. In SOM, the 
  8033. formal language used to define object interfaces is the Interface Definition 
  8034. Language (described in Chapter 4, "SOM IDL and the SOM Compiler"). 
  8035.  
  8036. The implementation of a class of objects  (that is, the procedures that 
  8037. implement the methods and the instance variables that store an object's state) 
  8038. is written in the implementor's preferred programming language. This language 
  8039. can be object-oriented (for instance, C++) or procedural (for instance, C). 
  8040.  
  8041. A completely implemented class definition, then, consists of two main files: 
  8042.  
  8043.      An IDL specification of the interface to instances of the class - the 
  8044.       interface definition file (or .idl file) and 
  8045.  
  8046.      Method procedures written in the implementor's language of choice - the 
  8047.       implementation file. 
  8048.  
  8049.  The SOM Compiler provides the link between those two files: To assist users in 
  8050.  implementing classes, the SOM Compiler produces a template implementation file 
  8051.  - a type-correct guide for how the implementation of a class should look. 
  8052.  Then, the class implementor modifies this template file to fully implement the 
  8053.  class's methods.  That process is the subject of the remainder of this 
  8054.  chapter. 
  8055.  
  8056.  The 
  8057.  SOMCompilercanalsoupdatetheimplementationfiletoreflectchangessubsequentlymadetoaclass 
  8058.  ' sinterfacedefinitionfile( the. idlfile ) 
  8059.  .Theseincrementalupdatesincludeaddingnewstubprocedures ,addingcomments 
  8060.  ,andchangingmethodprototypestoreflectchangesmadetothemethoddefinitionsintheIDLspecification 
  8061.  .Theseupdatestotheimplementationfile ,however 
  8062.  ,donotdisturbexistingcodeinthemethodprocedures 
  8063.  .Theseupdatesarediscussedfurtherin" 
  8064.  Runningincrementalupdatesoftheimplementationtemplatefile "laterinthissection .
  8065.  
  8066.  For C programmers, the SOM Compiler generates a <filestem>.c file. For C++ 
  8067.  programmers, the SOM Compiler generates a <filestem>.C  file (for AIX) or a 
  8068.  <filestem>.cpp file (for OS/2). To specify whether the SOM Compiler should 
  8069.  generate a C or C++ implementation template, set the value of the SMEMIT 
  8070.  environment variable, or use the -s option when running the SOM Compiler. (See 
  8071.  "The SOM Compiler" in Chapter 4, "SOM IDL and the SOM Compiler.") 
  8072.  
  8073.  Note:  As this chapter describes, a SOM class can be implemented by using C++ 
  8074.         to define the instance variables introduced by the class and to define 
  8075.         the procedures that implement the overridden and introduced methods of 
  8076.         the class. Be aware, however, that the C++ class defined by the C++ 
  8077.         usage bindings for a SOM class (described in Chapter 3) cannot be 
  8078.         subclassed in C++ to create new C++ or SOM classes. [The reason why the 
  8079.         C++ implementation of a SOM class involves the definition of C++ 
  8080.         procedures (not C++ methods) to support SOM methods is that there is no 
  8081.         language-neutral way to call a C++ method. Only C++  code can call C++ 
  8082.         methods, and this calling code must be generated by the same compiler 
  8083.         that generates the method code. In contrast, the method procedures that 
  8084.         implement SOM methods must be callable from any language, without 
  8085.         knowledge on the part of the object client as to which language is used 
  8086.         to implement the resolved method procedure] 
  8087.  
  8088.  
  8089. ΓòÉΓòÉΓòÉ 6.4.1. The implementation template ΓòÉΓòÉΓòÉ
  8090.  
  8091. Consider the following IDL description of the "Hello" class: 
  8092.  
  8093.    #include <somobj.idl>
  8094.  
  8095.    interface Hello : SOMObject
  8096.    {
  8097.        void sayHello();
  8098.        // This method outputs the string "Hello, World!".
  8099.    };
  8100.  
  8101. From this IDL description, the SOM Compiler generates the following C 
  8102. implementation template, hello.c (a C++ implementation template, hello.C or 
  8103. hello.cpp, is identical except that the #included file is <hello.xih> rather 
  8104. than <hello.ih>): 
  8105.  
  8106.    #define Hello_Class_Source
  8107.    #include <hello.ih>
  8108.  
  8109.    /*
  8110.     *  This method outputs the string "Hello, World!".
  8111.     */
  8112.  
  8113.    SOM_Scope void   SOMLINK sayHello(Hello somSelf, Environment *ev)
  8114.    {
  8115.        /* HelloData *somThis = HelloGetData(somSelf); */
  8116.        HelloMethodDebug("Hello","sayHello");
  8117.    }
  8118.  
  8119. The first line defines the "Hello_Class_Source" symbol, which is used in the 
  8120. SOM-generated implementation header files for C to determine when to define 
  8121. various functions, such as "HelloNewClass."  For interfaces defined within a 
  8122. module, the directive "#define <className>_Class_Source" is replaced by the 
  8123. directive "#define SOM_Module_<moduleName>_Source". 
  8124.  
  8125. The second line (#include <hello.ih> for C, or #include <hello.xih> for C++) 
  8126. includes the SOM-generated implementation header file. This file defines a 
  8127. struct holding the class's instance variables, macros for accessing instance 
  8128. variables, macros for invoking parent methods, and so forth. 
  8129.  
  8130.  
  8131. ΓòÉΓòÉΓòÉ 6.4.1.1. Stub procedures for methods ΓòÉΓòÉΓòÉ
  8132.  
  8133. For each method introduced or overridden by the class, the implementation 
  8134. template includes a stub procedure-a procedure that is empty except for an 
  8135. initialization statement, a debugging statement, and possibly a return 
  8136. statement. The stub procedure for a method is preceded by any comments that 
  8137. follow the method's declaration in the IDL specification. 
  8138.  
  8139. For method "sayHello" above, the SOM Compiler generates the following prototype 
  8140. of the stub procedure: 
  8141.  
  8142.    SOM_Scope void SOMLINK sayHello(Hello somSelf, Environment *ev)
  8143.  
  8144. The "SOM_Scope" symbol is defined in the implementation header file as either 
  8145. "extern" or "static," as appropriate. The term "void" signifies the return type 
  8146. of method "sayHello". The "SOMLINK" symbol is defined by SOM; it represents the 
  8147. keyword needed to link to the C or C++ compiler, and its value is 
  8148. system-specific. Using the "SOMLINK" symbol allows the code to work with a 
  8149. variety of compilers without modification. 
  8150.  
  8151. Following the "SOMLINK" symbol is the name of the procedure that implements the 
  8152. method. If no functionprefix modifier has been specified for the class, then 
  8153. the procedure name is the same as the method name. If a functionprefix modifier 
  8154. is in effect, then the procedure name is generated by prepending the specified 
  8155. prefix to the method name. For example, if the class definition contained the 
  8156. following statement: 
  8157.  
  8158.    functionprefix = xx_;
  8159.  
  8160. then the prototype of the stub procedure for method "sayHello" would be: 
  8161.  
  8162.    SOM_Scope void SOMLINK xx_sayHello(Hello somSelf, Environment *ev)
  8163.  
  8164. The functionprefix can not be 
  8165.  
  8166.    <classname>_
  8167.  
  8168. since this is used in method invocation macros defined by the C usage bindings. 
  8169.  
  8170. Following the procedure name is the formal parameter list for the method 
  8171. procedure. Because each SOM method always receives at least one argument (a 
  8172. pointer to the SOM object that responds to the method), the first parameter 
  8173. name in the prototype of each stub procedure is called somSelf. (The macros 
  8174. defined in the implementation header file rely on this convention.) The somSelf 
  8175. parameter is a pointer to an object that is an instance of the class being 
  8176. implemented (here, class "Hello") or an instance of a class derived from it. 
  8177.  
  8178. Unless the IDL specification of the class included the callstyle=oidl modifier, 
  8179. then the formal parameter list will include one or two additional parameters 
  8180. before the parameters declared in the IDL specification: an (Environment *ev) 
  8181. input/output parameter, which permits the return of exception information, and, 
  8182. if the IDL specification of the method includes a context specification, a 
  8183. (Context *ctx) input parameter. These parameters are prescribed by the CORBA 
  8184. standard.  For more information on using the Environment  and Context 
  8185. parameters, see the section entitled "Exceptions and error handling" in Chapter 
  8186. 3, "Using SOM Classes in Client Programs," and the book The Common Object 
  8187. Request Broker: Architecture and Specification, published by Object Management 
  8188. Group and X/Open. 
  8189.  
  8190. The first statement in the stub procedure for method "sayHello" is the 
  8191. statement: 
  8192.  
  8193.    /* HelloData *somThis = HelloGetData(somSelf); */
  8194.  
  8195. This statement is enclosed in comments only when the class does not introduce 
  8196. any instance variables. The purpose of this statement, for classes that do 
  8197. introduce instance variables, is to initialize a local variable (somThis) that 
  8198. points to a structure representing the instance variables introduced by the 
  8199. class. The somThis pointer is used by the macros defined in the "Hello" 
  8200. implementation header file to access those instance variables. (These macros 
  8201. are described below.)  In this example, the "Hello" class introduces no 
  8202. instance variables, so the statement is commented out. If instance variables 
  8203. are later added to a class that initially had none, then the comment characters 
  8204. can be removed if access to the variable is required. 
  8205.  
  8206. The "HelloData" type and the "HelloGetData" macro used to initialize the 
  8207. somThis pointer are defined in the implementation header file. Within a method 
  8208. procedure, class implementers can use the somThis pointer to access instance 
  8209. data, or they can use the convenience macros defined for accessing each 
  8210. instance variable, as described below. 
  8211.  
  8212. To implement a method so that it can modify a local copy of an object's 
  8213. instance data without affecting the object's real instance data, declare a 
  8214. variable of type <className>Data (for example, "HelloData") and assign to it 
  8215. the structure that somThis points to; then make the somThis pointer point to 
  8216. the copy. For example: 
  8217.  
  8218.    HelloData myCopy = *somThis;
  8219.    somThis = &myCopy;
  8220.  
  8221. Next in the stub procedure for method "sayHello" is the statement: 
  8222.  
  8223.    HelloMethodDebug("Hello", "sayHello");
  8224.  
  8225. This statement facilitates debugging. The "HelloMethodDebug" macro is defined 
  8226. in the implementation header file. It takes two arguments, a class name and a 
  8227. method name. If debugging is turned on (that is, if global variable 
  8228. SOM_TraceLevel is set to one in the calling program), the macro produces a 
  8229. message each time the method procedure is entered. (See the next Chapter 3, 
  8230. "Using SOM Classes in Client Programs," for information on debugging with SOM.) 
  8231.  
  8232. Debugging can be permanently disabled (regardless of the setting of the 
  8233. SOM_TraceLevel setting in the calling program) by redefining the 
  8234. <className>MethodDebug macro to be SOM_NoTrace(c,m) following the #include 
  8235. directive for the implementation header file. (This can yield a slight 
  8236. performance improvement.) For example, to permanently disable debugging for the 
  8237. "Hello" class, insert the following lines in the hello.c implementation file 
  8238. following the line "#include hello.ih" (or "#include hello.xih," for classes 
  8239. implemented in C++): 
  8240.  
  8241.    #undef HelloMethodDebug
  8242.    #define HelloMethodDebug(c,m) SOM_NoTrace(c,m)
  8243.  
  8244. The way in which the stub procedure ends is determined by whether the method is 
  8245. a new or an overriding method. 
  8246.  
  8247.      For non-overriding (new) methods, the stub procedure ends with a return 
  8248.       statement (unless the return type of the method is void). The class 
  8249.       implementer should customize this return statement. 
  8250.  
  8251.      For overriding methods, the stub procedure ends by making a "parent 
  8252.       method call" for each of the class's parent classes. If the method has a 
  8253.       return type that is not void, the last of these parent method calls is 
  8254.       returned as the result of the method procedure. The class implementer can 
  8255.       customize this return statement if needed (for example, if some other 
  8256.       value is to be returned, or if the parent method calls should be made 
  8257.       before the method procedure's own processing). See the next section for a 
  8258.       discussion of parent method calls. 
  8259.  
  8260.  If a classinit modifier was specified to designate a user-defined procedure 
  8261.  that will initialize the "Hello" class object, as in the statement: 
  8262.  
  8263.      classinit = HInit;
  8264.  
  8265.  then the implementation template file would include the following stub 
  8266.  procedure for "HInit", in addition to the stub procedures for Hello's methods: 
  8267.  
  8268.      void  SOMLINK HInit(SOMClass *cls)
  8269.      {
  8270.  
  8271.      }
  8272.  
  8273.  This stub procedure is then filled in by the class implementer. If the class 
  8274.  definition specifies a functionprefix modifier, the classinit procedure name 
  8275.  is generated by prepending the specified prefix to the specified classinit 
  8276.  name, as with other stub procedures. 
  8277.  
  8278.  
  8279. ΓòÉΓòÉΓòÉ 6.4.2. Extending the implementation template ΓòÉΓòÉΓòÉ
  8280.  
  8281. To implement a method, add code to the body of the stub procedure.  In addition 
  8282. to standard C or C++ code, class implementers can also use any of the 
  8283. functions, methods, and macros SOM provides for manipulating classes and 
  8284. objects. Chapter 3, "Using SOM Classes in Client Programs," discusses these 
  8285. functions, methods, and macros. 
  8286.  
  8287. In addition to the functions, methods, and macros SOM provides for both class 
  8288. clients and class implementers, SOM provides two facilities especially for 
  8289. class implementers. They are for (1) accessing instance variables of the object 
  8290. responding to the method and (2) making parent method calls, as follows. 
  8291.  
  8292.  
  8293. ΓòÉΓòÉΓòÉ 6.4.2.1. Accessing internal instance variables ΓòÉΓòÉΓòÉ
  8294.  
  8295. To access internal instance variables, class implementers can use either of the 
  8296. following forms: 
  8297.  
  8298.       _variableName 
  8299.  
  8300.       somThis->variableName 
  8301.  
  8302.  To access internal instance variables "a", "b", and "c", for example, the 
  8303.  class implementer could use either _a, _b, and _c, or somThis->a, somThis->b, 
  8304.  and somThis->c. These expressions can appear on either side of an assignment 
  8305.  statement. The somThis  pointer must be properly initialized in advance using 
  8306.  the <className>GetData  procedure, as shown above. 
  8307.  
  8308.  Instance variables can be accessed only within the implementation file of the 
  8309.  class that introduces the instance variable, and not within the implementation 
  8310.  of subclasses or within client programs. (To allow access to instance data 
  8311.  from a subclass or from client programs, use an attribute rather than an 
  8312.  instance variable to represent the instance data.) For C++ programmers, the 
  8313.  _variableName form is available only if the macro  VARIABLE_MACROS is defined 
  8314.  (that is, #define VARIABLE_MACROS) in the implementation file prior to 
  8315.  including the .xih file for the class. 
  8316.  
  8317.  
  8318. ΓòÉΓòÉΓòÉ 6.4.2.2. Making parent method calls ΓòÉΓòÉΓòÉ
  8319.  
  8320. In addition to macros for accessing instance variables, the implementation 
  8321. header file that the SOM Compiler generates also contains definitions of macros 
  8322. for making "parent method calls." When a class overrides a method defined by 
  8323. one or more of its parent classes, often the new implementation simply needs to 
  8324. augment the functionality of the existing implementation(s). Rather than 
  8325. completely re-implementing the method, the overriding method procedure can 
  8326. conveniently invoke the procedure that one or more of the parent classes uses 
  8327. to implement that method, then perform additional computation (redefinition) as 
  8328. needed. The parent method call can occur anywhere within the overriding method. 
  8329. (See Example 3 of the SOM IDL tutorial.) 
  8330.  
  8331. The SOM-generated implementation header file defines the following macros for 
  8332. making parent-method calls from within an overriding method: 
  8333.  
  8334. <className>_parent_<parentClassName>_<methodName> 
  8335.  
  8336.              (for each parent class of the class overriding
  8337. the method), and 
  8338.  
  8339. <className>_parents_<methodName>. 
  8340.  
  8341. For example, given class "Hello" with parents "File" and "Printer" and 
  8342. overriding method somInit (the SOM method that initializes each object), the 
  8343. SOM Compiler defines the following macros in the implementation header file for 
  8344. "Hello": 
  8345.  
  8346.    Hello_parent_Printer_somInit
  8347.    Hello_parent_File_somInit
  8348.    Hello_parents_somInit
  8349.  
  8350. Each macro takes the same number and type of arguments as <methodName>. The 
  8351. <className>_parent_<parentClassName>_<methodName> macro invokes the 
  8352. implementation of <methodName> inherited from <parentClassName>. Hence, using 
  8353. the macro "Hello_parent_File_somInit" invokes the File's implementation of 
  8354. somInit. 
  8355.  
  8356. The <className>_parents_<  methodName> macro invokes the parent method for each 
  8357. parent of the child class that supports <methodName>. That is, 
  8358. "Hello_parents_somInit" would invoke File's implementation of somInit, followed 
  8359. by Printer's implementation of somInit. The <className>_parents_<methodName> 
  8360. macro is redefined in the binding file each time the class interface is 
  8361. modified, so that if a parent class is added or removed from the class 
  8362. definition, or if <methodName> is added to one of the existing parents, the 
  8363. macro <className>_parents_<methodName > will be redefined appropriately. 
  8364.  
  8365.  
  8366. ΓòÉΓòÉΓòÉ 6.4.2.3. Converting C++ classes to SOM classes ΓòÉΓòÉΓòÉ
  8367.  
  8368. For C++ programmers implementing SOM classes, SOM provides a macro that 
  8369. simplifies the process of converting C++ classes to SOM classes. This macro 
  8370. allows the implementation of one method of a class to invoke another new or 
  8371. overriding method of the same class on the same receiving object by using the 
  8372. following shorthand syntax: 
  8373.  
  8374.    _methodName(arg1, arg2, ...)
  8375.  
  8376. For example, if class X introduces or overrides methods m1 and m2, then the C++ 
  8377. implementation of method m1 can invoke method m2 on its somSelf argument using 
  8378. _m2(arg, arg2, ...), rather than somSelf->m2(arg1, arg2, ...), as would 
  8379. otherwise be required. (The longer form is also available.) Before the 
  8380. shorthand form in the implementation file is used, the macro METHOD_MACROS must 
  8381. be defined (that is, use #define METHOD_MACROS) prior to including the xih file 
  8382. for the class. 
  8383.  
  8384.  
  8385. ΓòÉΓòÉΓòÉ 6.4.2.4. Running incremental updates of the implementation template file ΓòÉΓòÉΓòÉ
  8386.  
  8387. Refining the .idl file for a class is typically an iterative process. For 
  8388. example, after running the IDL source file through the SOM Compiler and writing 
  8389. some code in the implementation template file, the class implementer realizes 
  8390. that the IDL class interface needs another method or attribute, a method needs 
  8391. a different parameter, or any such changes. 
  8392.  
  8393. As mentioned earlier, the SOM Compiler (when run using the c or xc emitter) 
  8394. assists in this development by reprocessing the .idl file and making 
  8395. incremental updates to the current implementation file. This modify-and-update 
  8396. process may in fact be repeated several times before the class declaration 
  8397. becomes final. Importantly, these updates do not disturb existing code for the 
  8398. method procedures. Included in the incremental update are these changes: 
  8399.  
  8400.      Stub procedures are inserted into the implementation file for any new 
  8401.       methods added to the .idl file. 
  8402.  
  8403.      New comments in the .idl file are transferred to the implementation file, 
  8404.       reformatted appropriately. 
  8405.  
  8406.      If the interface to a method has changed, a new method procedure 
  8407.       prototype is placed in the implementation file. As a precaution, however, 
  8408.       the old prototype is also preserved within comments. The body of the 
  8409.       method procedure is left untouched (as are the method procedures for all 
  8410.       methods). 
  8411.  
  8412.      Similarly left intact are preprocessor directives, data declarations, 
  8413.       constant declarations, non-method functions, and additional comments-in 
  8414.       essence, everything else in the implementation file. 
  8415.  
  8416.  Some changes to the .idl file are not reflected automatically in the 
  8417.  implementation file after an incremental update. The class implementer must 
  8418.  manually edit the implementation file after changes such as these in the .idl 
  8419.  file: 
  8420.  
  8421.      Changing the name of a class or a method. 
  8422.  
  8423.      Changing the parents of a class (see also "If you change the parents of a 
  8424.       class..." later in this topic). 
  8425.  
  8426.      Changing a functionprefix class modifier statement. 
  8427.  
  8428.      Changing the content of a passthru statement directed to the 
  8429.       implementation (.c, .C, or cpp) file. As previously emphasized, however, 
  8430.       passthru statements are primarily recommended only for placing #include 
  8431.       statements in a binding file (.ih, xih, .h, or .xh file) used as a header 
  8432.       file in the implementation file or in a client program. 
  8433.  
  8434.      If the class implementer has placed "forward declarations" of the method 
  8435.       procedures in the implementation file, those are not updated. Updates 
  8436.       occur only for method prototypes that are part of the method procedures 
  8437.       themselves. 
  8438.  
  8439.  
  8440. ΓòÉΓòÉΓòÉ 6.4.2.5. Considerations to ensure that updates work ΓòÉΓòÉΓòÉ
  8441.  
  8442. To ensure that the SOM Compiler can properly update method procedure prototypes 
  8443. in the implementation file, class implementers should avoid editing changes 
  8444. such as the following: 
  8445.  
  8446.      A method procedure name should not be enclosed in parentheses in the 
  8447.       prototype. 
  8448.  
  8449.      A method procedure name must appear in the first line of the prototype, 
  8450.       excluding comments and white space. Thus, a new line must not be inserted 
  8451.       before the procedure name. 
  8452.  
  8453.  Error messages occur while updating an existing implementation file if it 
  8454.  contains syntax that is not ANSI C. For example, "old style" method 
  8455.  definitions such as the example on the left generate errors: 
  8456.  
  8457.  Invalid "old" syntax     Required  ANSI C 
  8458.  void foo(x)              void foo(short x) { 
  8459.  short x;                 ... 
  8460.  {                        } 
  8461.  ... 
  8462.  } 
  8463.  
  8464.  Similarly, error messages occur if anything in the .idl file would produce an 
  8465.  implementation file that is not syntactically valid for C/C++ (such as nested 
  8466.  comments). If update errors occur, either the .idl file or the implementation 
  8467.  file may be at fault. One way to track down the problem is to run the 
  8468.  implementation file through the C/C++ compiler. Or, move the existing 
  8469.  implementation file to another directory, generate a completely new one from 
  8470.  the .idl file, and then run it through the C/C++ compiler. One of these steps 
  8471.  should pinpoint the error, if the compiler is strict ANSI. 
  8472.  
  8473.  Conditional compilation (using #if and #ifdef directives) in the 
  8474.  implementation file can be another source of errors, because the SOM Compiler 
  8475.  does not invoke the preprocessor (it simply recognizes and ignores those 
  8476.  directives). The programmer should be careful when using conditional 
  8477.  compilation, to avoid a situation such as shown below; here, with apparently 
  8478.  two open braces and only one closing brace, the c or xc emitter would report 
  8479.  an unexpected end-of-file: 
  8480.  
  8481.  Invalid syntax           Required matching braces 
  8482.  
  8483.  #ifdef FOOBAR            #ifdef FOOBAR 
  8484.   {                        { 
  8485.  ...                      ... 
  8486.  #else                     } 
  8487.  {                        #else 
  8488.  ...                       { 
  8489.  #endif                   ... 
  8490.   }                        } 
  8491.                           #endif 
  8492.  
  8493.  
  8494. ΓòÉΓòÉΓòÉ 6.4.2.6. If you change the parents of a class... ΓòÉΓòÉΓòÉ
  8495.  
  8496. Because the implementation-file emitters never change any existing code within 
  8497. a previously generated implementation file, changing the parents of a class 
  8498. requires extremely careful attention by the programmer. For example, for 
  8499. overridden methods, changing a class's parents may invalidate previous 
  8500. parent-method calls provided by the template, and require the addition of new 
  8501. parent-method calls. Neither of these issues is addressed by the incremental 
  8502. update of previously generated method-procedure templates. 
  8503.  
  8504. The greatest danger from changing the parents of a class, however, concerns the 
  8505. ancestor-initializer calls provided in the stub procedures for initializer 
  8506. methods. (For further information on ancestor initializer calls, see 
  8507. "Initializing and Uninitializing Objects" later in this chapter.) Unlike 
  8508. parent-method calls, ancestor-initializer calls are not optional - they must be 
  8509. made t all classes specified in a directinitclasses modifier, and these calls 
  8510. should always include the parents of the class (the default when no 
  8511. directinitclasses modifier is given). When the parents of a class are changed, 
  8512. however, the ancestor-initializer calls (which must be made in a specific 
  8513. order) are not updated. 
  8514.  
  8515. The easiest way to deal with this problem is to change the method name of the 
  8516. previously generated initializer stub procedure in the implementation template 
  8517. file. Then, the SOM Compiler can correctly generate a completely new 
  8518. initializer stub procedure (while ignoring the renamed procedure). Once this is 
  8519. done, your customization code from the renamed initializer procedure can be 
  8520. "merged" into the newly generated one, after which the renamed initializer 
  8521. procedure can be deleted. 
  8522.  
  8523.  
  8524. ΓòÉΓòÉΓòÉ 6.4.3. Compiling and linking ΓòÉΓòÉΓòÉ
  8525.  
  8526. After you fill in the method stub procedures, the implementation template file 
  8527. can be compiled and linked with a client program as follows. (In these 
  8528. examples, the environment variable SOMBASE represents the directory in which 
  8529. SOM has been installed.) 
  8530.  
  8531. Note: If you are building an application that uses a combination of C and C++ 
  8532. compiled object modules, then the C++ linker must be used to link them. 
  8533.  
  8534. For AIX:  When the client program (main.c) and the implementation file 
  8535. (hello.c) are written in C: 
  8536.  
  8537.    > xlc -I. -I$SOMBASE/include -o hello main.c hello.c -L$SOMBASE/lib -lsomtk
  8538.  
  8539. When the client program and the implementation file are written in C++: 
  8540.  
  8541.    > xlC -I. -I$SOMBASE/include -o hello main.C hello.C -L$SOMBASE/lib -lsomtk
  8542.  
  8543. For OS/2:  When the client program (main.c) and the implementation file 
  8544. (hello.c) are in C: 
  8545.  
  8546.    > set LIB=%SOMBASE%\lib;%LIB%
  8547.    > icc -I. -I%SOMBASE%\include -Fe hello main.c hello.c somtk.lib
  8548.  
  8549. When the client program and the implementation file are written in C++: 
  8550.  
  8551.    > set LIB=%SOMBASE%\lib;%LIB%
  8552.    > icc -I. -I%SOMBASE%\include -Fe hello main.cpp hello.cpp somtk.lib
  8553.  
  8554. If the class definition (in the .idl file) changes, run the SOM Compiler again. 
  8555. This will generate new header files, and it will update the implementation file 
  8556. to include any: 
  8557.  
  8558.      New comments, 
  8559.  
  8560.      Stub procedures for any new methods, and 
  8561.  
  8562.      Revised method procedure prototypes for methods whose signatures have 
  8563.       been changed in the .idl file. 
  8564.  
  8565.  After rerunning the SOM Compiler, add to the implementation file the code for 
  8566.  any newly added method procedures, and recompile the implementation file with 
  8567.  the client program. 
  8568.  
  8569.  
  8570. ΓòÉΓòÉΓòÉ 6.5. Initializing and Uninitializing Objects ΓòÉΓòÉΓòÉ
  8571.  
  8572. This section discusses the initialization and uninitialization of SOM objects. 
  8573. Subsequent topics introduce the methods and capabilities that the SOMobjects 
  8574. Developer Toolkit provides to facilitate this. 
  8575.  
  8576. Object creation is the act that enables the execution of methods on an object. 
  8577. In SOM, this means storing a pointer to a method table into a word of memory. 
  8578. This single act converts raw memory into an (uninitialized) SOM object that 
  8579. starts at the location of the method table pointer. 
  8580.  
  8581. Object initialization, on the other hand, is a separate activity from object 
  8582. creation in SOM. Initialization is a capability supported by certain methods 
  8583. available on an object. An object's class determines the implementation of the 
  8584. methods available on the object, and thus determines its initialization 
  8585. behavior. 
  8586.  
  8587. The instance variables encapsulated by a newly created object must be brought 
  8588. into a consistent state before the object can be used. This is the purpose of 
  8589. initialization methods. Because, in general, every ancestor of an object's 
  8590. class contributes instance data to an object, it is appropriate that each of 
  8591. these ancestors contribute to the initialization of the object. 
  8592.  
  8593. SOM thus recognizes initializers as a special kind of method. One advantage of 
  8594. this approach is that special metaclasses are not required for defining 
  8595. constructors (class methods) that take arguments. Furthermore, a class can 
  8596. define multiple initializer methods, thus enabling its different objects to be 
  8597. initialized supporting different characteristics or capabilities. This results 
  8598. in simpler designs and more efficient programs. 
  8599.  
  8600. The SOMobjects Toolkit provides an overall framework that class designers can 
  8601. easily exploit in order to implement default or customized initialization of 
  8602. SOM objects. This framework is fully supported by the SOM Toolkit emitters that 
  8603. produce the implementation template file. The following sections describe the 
  8604. declaration, implementation, and use of initializer (and uninitializer) 
  8605. methods. 
  8606.  
  8607. Important: All code written prior to SOMobjects Release 2.1 using documented 
  8608. guidelines for the earlier initialization approach based on the somInit method 
  8609. (as well as all existing class binaries) continues to be fully supported and 
  8610. useful. 
  8611.  
  8612.  
  8613. ΓòÉΓòÉΓòÉ 6.5.1. Initializer methods ΓòÉΓòÉΓòÉ
  8614.  
  8615. As noted above, in the SOMobjects Toolkit each ancestor of an object 
  8616. contributes to the initialization of that object. Initialization of an object 
  8617. involves a chain of ancestor-method calls that, by default, are automatically 
  8618. determined by the SOM Compiler emitters. The SOMobjects framework for 
  8619. initialization of objects is based on the following approach: 
  8620.  
  8621.    1. SOMobjects recognizes initializers as a special kind of method, and 
  8622.       supports a special mechanism for ordering the execution of 
  8623.       ancestor-initializer method procedures. The SOMObject class introduces an 
  8624.       initializer method, somDefaultInit that uses this execution mechanism. 
  8625.  
  8626.    2. The SOM Compiler's emitters provide special support for methods that are 
  8627.       declared as initializers in the .idl file. To supplement the 
  8628.       somDefaultInit method, SOM class designers can also declare additional 
  8629.       initializers in their own classes. 
  8630.  
  8631.  Two SOM IDL modifiers are provided for declaring initializer methods and 
  8632.  controlling their execution, init and directinitclasses: 
  8633.  
  8634.      The init modifier is required in order to designate a given method is a 
  8635.       initializer; that is, to indicate that the method both uses and supports 
  8636.       the object-initialization protocol described here. 
  8637.  
  8638.      The  directinitclasses modifier can be used to control the order of 
  8639.       execution of initializer method procedures provided by the different 
  8640.       ancestors of the class of an object. 
  8641.  
  8642.      For full definitions of init and directinitclasses, see the topic 
  8643.       "Modifier statements" in Chapter 4,"SOM IDL and the SOM Compiler." 
  8644.  
  8645.  Every SOM class has a list that defines (in sequential order) the ancestor 
  8646.  classes whose initializer method procedures the class should invoke. If a 
  8647.  class's IDL does not specify an explicit directinitclasses modifier, the 
  8648.  default for this list is simply the class's parents - in left-to-right order. 
  8649.  
  8650.  Using the directinitclasses list and the actual run-time class hierarchy above 
  8651.  itself, each class inherits from SOMClass the ability to create a data 
  8652.  structure of type somInitCtrl. This structure is used to control the execution 
  8653.  of initializers. Moreover, it represents a particular visit-ordering that 
  8654.  reaches each class in the transitive closure of directinitclasses exactly 
  8655.  once. To initialize a given object, this visit-ordering occurs as follows: 
  8656.  While recursively visiting each ancestor class whose initializer method 
  8657.  procedure should be run, SOMobjects first runs the initializer method 
  8658.  procedures of all of that class's directinitclasses if they have not already 
  8659.  been run by another class's initializers, with ancestor classes always taken 
  8660.  in left-to-right order. 
  8661.  
  8662.  The code that deals with the somInitCtrl data structure is generated 
  8663.  automatically within the implementation bindings for a class, and need not 
  8664.  concern a class implementor. 
  8665.  
  8666.  When an instance of a given class (or some descendant class) is initialized, 
  8667.  only one of the given class's initializers will be executed, and this will 
  8668.  happen exactly once (under control of the ordering determined by the class of 
  8669.  the object being initialized). 
  8670.  
  8671.  The somInitCtrl structure solves a problem originally created by the add 
  8672.  ition of multiple inheritance to SOMobjects 2.0. With multiple inheritance, 
  8673.  any class can appear at the top of a multiple inheritance diamond. Previously, 
  8674.  whenever this happened, the class could easily receive multiple initialization 
  8675.  calls. In the current version of the SOMobjects Toolkit, however, the 
  8676.  somInitCtrl structure prevents this from happening. 
  8677.  
  8678.  
  8679. ΓòÉΓòÉΓòÉ 6.5.1.1. Declaring new initializers in SOM IDL ΓòÉΓòÉΓòÉ
  8680.  
  8681. When defining SOMobjects classes, programmers can easily declare and implement 
  8682. new initializers. Classes can have as many initializers as desired, and 
  8683. subclassers can invoke whichever of these they want. When introducing new 
  8684. initializers, developers must adhere to the following rules: 
  8685.  
  8686.      All initializer methods take a somInitCtrl data structure as an initial 
  8687.       inout parameter (its type is defined in the SOMobjects header file 
  8688.       somapi.h), and 
  8689.  
  8690.      All initializers return void. 
  8691.  
  8692.  Accordingly, the somDefaultInit initializer introduced by SOMObject takes a 
  8693.  somInitCtrl structure as its (only) argument, and returns void. Here is the 
  8694.  IDL syntax for this method, as declared in somobj.idl: 
  8695.  
  8696.   void  somDefaultInit (inout somInitCtrl ctrl);
  8697.  
  8698.  When introducing a new initializer, it is also necessary to specify the init 
  8699.  modifier in the implementation section. The init modifier is what tells 
  8700.  emitters that the new method is actually an initializer, so the method can be 
  8701.  properly supported from the language bindings. As described below, this 
  8702.  support includes the generation of special initializer stub procedures in the 
  8703.  implementation template file, as well as bindings containing 
  8704.  ancestor-initialization macros and object constructors that invoke the class 
  8705.  implementor's new initializers. 
  8706.  
  8707.  It is a good idea to begin the names of initializer methods with the name of 
  8708.  the class (or some other string that can be unique for the class). This is 
  8709.  important because all initializers available on a class must be newly 
  8710.  introduced by that class (that is, you cannot override initializers - except 
  8711.  for somDefaultInit). Using a class-unique name means that subclasses will not 
  8712.  be unnecessarily constrained in their choice of initializer names. 
  8713.  
  8714.  Here are two classes that introduce new initializers: 
  8715.  
  8716.   interface Example1 : SOMObject
  8717.   {
  8718.      void Example1_withName (inout somInitCtrl ctrl,in string name);
  8719.      void Example1_withSize (inout somInitCtrl ctrl,in long size);
  8720.      void Example1_withNandS(inout somInitCtrl ctrl,in string name,
  8721.                                                      in long size);
  8722.           implementation {
  8723.                   releaseorder: Example1_withName,
  8724.                                 Example1_withSize,
  8725.                                 Example1_withNandS;
  8726.                   somDefaultInit: override, init;
  8727.                   somDestruct: override;
  8728.                   Example1_withName: init;
  8729.                   Example1_withSize: init;
  8730.                   Example1_withNandS: init;
  8731.           };
  8732.   };
  8733.  
  8734.   interface Example2 : Example1
  8735.   {
  8736.      void Example2_withName(inout somInitCtrl ctrl, in string name);
  8737.      void Example2_withSize(inout somInitCtrl ctrl, in long size);
  8738.           implementation {
  8739.                   releaseorder: Example2_withName,
  8740.                                 Example2_withSize;
  8741.                   somDefaultInit: override, init;
  8742.                   somDestruct: override;
  8743.                   Example2_withName: init;
  8744.                   Example2_withSize: init;
  8745.           };
  8746.   };
  8747.  
  8748.  Here, interface "Example1" declares three new initializers. Notice the use of 
  8749.  inout somInitCtrl as the first argument of each initializer, and also note 
  8750.  that the init modifier is used in the implementation section. These two things 
  8751.  are required to declare initializers. Any number of initializers can be 
  8752.  declared by a class. "Example2" declares two initializers. 
  8753.  
  8754.  "Example1" and "Example2" both override the somDefaultInit initializerThis 
  8755.  initializer method is introduced by SOMObject and is special for two resons: 
  8756.  First, somDefaultInit is the only initializer that can be overridden And, 
  8757.  second, SOMobjects arranges that this initializer will always be available on 
  8758.  any class (as further explained below). 
  8759.  
  8760.  Historically in the SOMobjects Toolkit, object#initialization methods by 
  8761.  default have invoked the somInit method, which class implementors could 
  8762.  override to customize initialization as appropriate. SOMobjects continues to 
  8763.  support this approach, so that existing code (and class binaries) will execute 
  8764.  correctly. However, the somDefaultInit method is now the preferred form of 
  8765.  initialization because it offers greatly improved efficiency. 
  8766.  
  8767.  Even if no specialized initialization is needed for a class, you should still 
  8768.  override the somDefaultInit method in the interest of efficiency. If you do 
  8769.  not override somDefaultInit, then a generic (and therefore less efficient) 
  8770.  somDefaultInit method procedure will be used for your class. This generic 
  8771.  method procedure first invokes somDefaultInit on the appropriate ancestor 
  8772.  classes. Then (for consistency with earlier versions of SOMobjects), it checks 
  8773.  to determine if the class overrides somInit and, if so, calls any customized 
  8774.  somInit code provided by the class. 
  8775.  
  8776.  When you override somDefaultInit, the emitter's implementation template file 
  8777.  will include a stub procedure similar to those used for other initializers, 
  8778.  and you can fill it in as appropriate (or simply leave it as is). Default 
  8779.  initialization for your class will then run much faster than with the generic 
  8780.  method procedure. Examples of initializer stub procedures (and customizations) 
  8781.  are given below. 
  8782.  
  8783.  In summary, the initializers available for any class of objects are 
  8784.  somDefaultInit (which you should always override) plus any new initializers 
  8785.  explicitly declared by the class designer. Thus, "Example1" objects may be 
  8786.  initialized using any of four different initializers (the three that are 
  8787.  explicitly declared, plus somDefaultInit). Likewise, there are three 
  8788.  initializers for the "Example2" objects. Some examples of using initializers 
  8789.  are provided below. 
  8790.  
  8791.  
  8792. ΓòÉΓòÉΓòÉ 6.5.1.2. Considerations re: 'somInit' initialization from earlier SOM releases ΓòÉΓòÉΓòÉ
  8793.  
  8794. To re-emphasize: All code written prior to SOMobjects Release 2.1 using 
  8795. documented guidelines for the earlier initialization approach based on the 
  8796. somInit method (as well as all existing class binaries) continues to be fully 
  8797. supported and useful. 
  8798.  
  8799. Prior to SOMobjects 2.1, initialization was done with initializer methods that 
  8800. would simply "chain" parent-method calls upward, thereby allowing the execution 
  8801. of initializer method procedures contributed by all ancestors of an object's 
  8802. class. This chaining of initializer calls was not supported in any special way 
  8803. by the SOM API. Parent-method calls are simply one of the possible idioms 
  8804. available to users of OOP in SOM, easily available to a SOM class designer as a 
  8805. result of the support provided by the SOMobjects Toolkit emitters for 
  8806. parent-method calls. 
  8807.  
  8808. So, SOM did not constrain initialization to be done in any particular way or 
  8809. require the use of any particular ordering of the method procedures of ancestor 
  8810. classes.  But, SOM did provide an overall framework that class designers could 
  8811. easily utilize in order to implement default initialization of SOM objects. 
  8812. This framework is provided by the somInit object-initializatio method 
  8813. introduced by the SOMobject class and supported by the SOM Toolkit emitters. 
  8814. The emitters create an implementation template file with stub procedures for 
  8815. overridden methods that automatically chain parent-method calls upward through 
  8816. parent classes. Many of the class methods that perform object creation called 
  8817. somInit automatically. 
  8818.  
  8819. Note:  These will now call somDefaultInit, which in turn calls somInit for 
  8820.        legacy code, as described in the previous topic. 
  8821.  
  8822.  Because it takes no arguments, somInit best served the purpose of a default 
  8823.  initializer. SOM programmers also had the option of introducing additional 
  8824.  "non-default" initialization methods that took arguments. In addition, by 
  8825.  using metaclasses, they could introduce new class methods as object 
  8826.  constructors that first create an object (generally using somNewNoInit.) and 
  8827.  then invoke some non-default initializer on the new object. 
  8828.  
  8829.  For a number of reasons, the somInit framework has been augmented by 
  8830.  recognizing initializers special kind of method in SOMobjects. One advantage 
  8831.  of this approach is that special metaclasses are no longer required for 
  8832.  defining constructors that take arguments. Instead, because the init modifier 
  8833.  identifies initializers, usage-binding emitters can now provide these 
  8834.  constructors. This results in simpler designs and more efficient programs. 
  8835.  
  8836.  Although somDefaultInit replaces somInit  as the no-argument initializer used 
  8837.  for SOM objects, all previous use of somInit is still supported by the 
  8838.  SOMobjects Developers Toolkit on AIX, OS/2 and 16-bit Windows. You may 
  8839.  continue to use somInit on these systems if you like, although this is 
  8840.  somewhat less efficient than using somDefaultInit. 
  8841.  
  8842.  However, you cannot use both methods. In particular, if a class overrides both 
  8843.  somDefaultInit  and somInit, its somInit code will never be executed. It is 
  8844.  recommended that you always override  somDefaultInit for object 
  8845.  initialization. For one thing, it is likely that when SOMobjects is ported to 
  8846.  new systems, somInit (and somUninit) may not be supported on those systems. 
  8847.  Thus, code written using these (obsolete) methods will be less portable. 
  8848.  
  8849.  
  8850. ΓòÉΓòÉΓòÉ 6.5.1.3. Implementing initializers ΓòÉΓòÉΓòÉ
  8851.  
  8852. When new initializers are introduced by a class, as in the preceding examples, 
  8853. the implementation template file generated by the SOM Toolkit C and C++ 
  8854. emitters automatically contains an appropriate stub procedure for each 
  8855. initializer method, for the class implementor's use. The body of an initializer 
  8856. stub procedure consists of two main sections: 
  8857.  
  8858.      The first section performs calls to ancestors of the class to invoke 
  8859.       their initializers. 
  8860.  
  8861.      The second section is used by the programmer to perform any "local" 
  8862.       initializations appropriate to the instance data of the class being 
  8863.       defined. 
  8864.  
  8865.  In the first section, by default, the parents of the new class are the 
  8866.  ancestors whose initializers are called. When something else is desired, the 
  8867.  IDL directinitclasses modifier can be used to explicitly designate the 
  8868.  ancestors whose initializer methods should be invoked by a new class's 
  8869.  initializers. 
  8870.  
  8871.  Important:  Under no circumstances can the number or the ordering of ancestor 
  8872.  initializer calls in the first section of an initializer stub procedure be 
  8873.  changed. The control masks used by initializers are based on these orderings. 
  8874.  (If you want to change the number or ordering of ancestor initializer calls, 
  8875.  you must use the directinitclasses modifier.) The ancestor initializer calls 
  8876.  themselves can be modified as described below. 
  8877.  
  8878.  Each call to an ancestor initializer is made using a special macro (much like 
  8879.  a parent call) that is defined for this purpose within the implementation 
  8880.  bindings. These macros are defined for all possible ancestor initialization 
  8881.  calls. Initially, an initializer stub procedure invokes the default ancestor 
  8882.  initializers provided by somDefaultInit. However, a class implementor can 
  8883.  replace any of these calls with a different initializer call, as long as it 
  8884.  calls the same ancestor (see the example in the next topic). Non-default 
  8885.  initializer calls generally take other arguments in addition to the control 
  8886.  argument. 
  8887.  
  8888.  In the second section of an initializer stub procedure, the programmer 
  8889.  provides any class-specific code that may be needed for initialization. For 
  8890.  example, the "Example2_withName" stub procedure is shown below. As with all 
  8891.  stub procedures produced by the SOMobjects implementation-template emitters, 
  8892.  this code requires no modification to run correctly. 
  8893.  
  8894.   SOM_Scope void SOMLINK Example2_withName(Example2 *somSelf,
  8895.                                            Environment *ev,
  8896.                                            somInitCtrl* ctrl,
  8897.                                            string name)
  8898.   {
  8899.       Example2Data *somThis; /* set by BeginInitializer */
  8900.       somInitCtrl globalCtrl;
  8901.       somBooleanVector myMask;
  8902.       Example2MethodDebug("Example2","withName");
  8903.  
  8904.       /*
  8905.        * first section -- calls to ancestor initializers
  8906.        */
  8907.        Example2_BeginInitializer_Example2_withName;
  8908.        Example2_Init_Example1_somDefaultInit(somSelf, ctrl);
  8909.  
  8910.       /*
  8911.        * second section -- local Example2 initialization code
  8912.        */
  8913.   }
  8914.  
  8915.  In this example, notice that the "Example2_withName" initializer is an IDL 
  8916.  callstyle method, so it  receives an Environment argument. In contrast, 
  8917.  somDefaultInit is introduced by the SOMObject class (so it has an OIDL 
  8918.  callstyle initializer, without an environment). 
  8919.  
  8920.  Important: If a class is defined where multiple initializers have exactly the 
  8921.  same signature, then the C++ usage bindings will not be able to differentiate 
  8922.  among them. That is, if there are multiple initializers defined with 
  8923.  environment and long arguments, for example, then C++ clients would not be 
  8924.  able to make a call using only the class name and arguments, such as: 
  8925.  
  8926.  
  8927.   new Example2(env, 123);
  8928.  
  8929.  Rather, C++ users would be forced to first invoke the somNewNoInit method on 
  8930.  the class to create an uninitialized object, and then separately invoke the 
  8931.  desired initializer method on the object. This call would pass a zero for the 
  8932.  control argument, in addition to passing values for the other arguments. For 
  8933.  further discussion of client usage, see "Using initializers when creating new 
  8934.  objects" later in this chapter. 
  8935.  
  8936.  
  8937. ΓòÉΓòÉΓòÉ 6.5.1.4. Selecting non-default ancestor initializer calls ΓòÉΓòÉΓòÉ
  8938.  
  8939. Often, it will be appropriate (in the first section of an initializer stub 
  8940. procedure) to change the invocation of an ancestor's somDefaultInit initializer 
  8941. to some other initializer available on the same class. The rule for making this 
  8942. change is simple: Replace somDefaultInit with the name of the desired ancestor 
  8943. initializer, and add any new arguments that are required by the replacement 
  8944. initializer. Important: Under no circumstances can you change anything else in 
  8945. the first section. 
  8946.  
  8947. This example shows how to change an ancestor-initializer call correctly. Since 
  8948. there is a known "Example1_withName" initializer, the following default 
  8949. ancestor-initializer call (produced within the stub procedure for 
  8950. "Example2_withName") can be changed from 
  8951.  
  8952.  
  8953. Example2_Init_Example1_somDefaultInit(somSelf, ctrl);
  8954.  
  8955. to
  8956.  
  8957. Example2_Init_Example1_Example1_withName(somSelf, ev, ctrl, name)
  8958.  
  8959. Notice that the revised ancestor-initializer call includes arguments for an 
  8960. Environment and a name, as defined by the "Example1_withname" initializer. 
  8961.  
  8962.  
  8963. ΓòÉΓòÉΓòÉ 6.5.1.5. Using initializers when creating new objects ΓòÉΓòÉΓòÉ
  8964.  
  8965. There are several ways that client programs can take advantage of the 
  8966. somDefaultInit object initialization. If desired, clients can use the SOM API 
  8967. directly (rather than taking advantage of the usage bindings). Also, the 
  8968. general object constructor, somNew, can always be invoked on a class to create 
  8969. and initialize objects. This call creates a new object and then invokes 
  8970. somDefaultInit on it 
  8971.  
  8972. To use the SOM API directly, the client code should first invoke the 
  8973. somNewNoInit method on the desired class object to create a new, uninitialized 
  8974. object. Then, the desired initializer is invoked on the new object, passing a 
  8975. null (that is, 0) control argument in addition to whatever other arguments may 
  8976. be required by the initializer. For example: 
  8977.  
  8978.  
  8979. /* first make sure the Example2 class object exists */
  8980. Example2NewClass(Example2_MajorVersion, Example2_MinorVersion);
  8981.  
  8982.  
  8983. /* then create a new, uninitialized Example2 object */
  8984. myObject = _somNewNoInit(_Example2);
  8985.  
  8986. (null)
  8987. /* then initialize it with the desired initializer */
  8988. Example2_withName(myObject, env, 0, "MyName");
  8989.  
  8990. Usage bindings hide the details associated with initializer use in various ways 
  8991. and make calls more convenient for the client. For example, the C usage 
  8992. bindings for any given class already provide a convenience macro, 
  8993. <className>New, that first assures existence of the class object, and then 
  8994. calls somNew on it to create and initialize a new object. As explained above, 
  8995. somNew will use somDefaultInit to initialize the new object. 
  8996.  
  8997. Also, the C usage bindings provide object-construction macros that use 
  8998. somNewNoInit and then invoke non-default initializers. These  macros are named 
  8999. using the form <className>New_<initializerName>. For example, the C usage 
  9000. bindings for "Example2" allow using the following expression to create, 
  9001. initialize, and return a new "Example2" object: 
  9002.  
  9003.  
  9004. Example2New_Example2_withName(env, "AnyName");
  9005.  
  9006. In the C++ bindings, initializers are represented as overloaded C++ 
  9007. constructors. As a result, there is no need to specify the name of the 
  9008. initializer method. For example, using the C++ bindings, the following 
  9009. expressions could be used to create a new "Example2" object: 
  9010.  
  9011.  
  9012. new Example2;                   // will use somDefaultInit
  9013. new Example2();                 // will use somDefaultInit
  9014. new Example2(env,"A.B.Normal"); // will use Example2_withName
  9015. new Example2(env,123);          // will use Example2_withSize
  9016.  
  9017. Observe that if multiple initializers in a class have exactly the same 
  9018. signatures, the C++ usage bindings would be unable to differentiate among the 
  9019. calls, if made using the forms illustrated above. In this case, a client could 
  9020. use somNewNoInit first, and then invoke the specific initializer, as described 
  9021. in the preceding paragraphs. 
  9022.  
  9023.  
  9024. ΓòÉΓòÉΓòÉ 6.5.2. Uninitialization ΓòÉΓòÉΓòÉ
  9025.  
  9026. An object should always be uninitialized before its storage is freed. This is 
  9027. important because it also allows releasing resources and freeing storage not 
  9028. contained within the body of the object.  SOMobjects handles uninitialization 
  9029. in much the same way as for initializers: An uninitializer takes a control 
  9030. argument and is supported with stub procedures in the implementation template 
  9031. file in a manner similar to initializers. 
  9032.  
  9033. Only a single uninitialization method is needed, so SOMObject introduces the 
  9034. method that provides this function: somDestruct. As with the default 
  9035. initializer method, a class designer who requires nothing special in the way of 
  9036. uninitialization need not be concerned about modifying the default somDestruct 
  9037. method procedure. However, your code will execute faster if the .idl file 
  9038. overrides somDestruct so that a non-generic stub-procedure code can be provided 
  9039. for the class. Note that somDestruct was overridden by "Example1" and 
  9040. "Example2" above No specific IDL modifiers other than override are required for 
  9041. this. 
  9042.  
  9043. Like an initializer template, the stub procedure for somDestruct consists of 
  9044. two sections: The first section is used by the programmer for performing any 
  9045. "local" uninitialization that may be required. The second section (which 
  9046. consists of a single EndDestructor macro invocation) invokes somDestruct on 
  9047. ancestors The second section must not be modified or removed by the programmer. 
  9048. It must be the final statement executed in the destructor. 
  9049.  
  9050.  
  9051. ΓòÉΓòÉΓòÉ 6.5.2.1. Using 'somDestruct' ΓòÉΓòÉΓòÉ
  9052.  
  9053. It is rarely necessary to invoke the somDestruct method explicitly This is 
  9054. because object uninitialization is normally done just before freeing an 
  9055. object's storage, and the mechanisms provided by SOMobjects for this purpose 
  9056. will automatically invoke somDestruct. For example, if an object were created 
  9057. using somNew or somNewNoInit, or by using a convenience macro provided by the C 
  9058. languag bindings, then the somFree method can be invoked on the object to 
  9059. delete the object. This automatically calls somDestruct before freeing storage. 
  9060.  
  9061. C++ users can simply use the delete operator provided by the C++ bindings. This 
  9062. destructor calls somDestruct before the C++ delete  operator frees the object's 
  9063. storage. 
  9064.  
  9065. On the other hand, if an object is initially created by allocating memory in 
  9066. some special way and subsequently some somRenew methods are used, somFree (or 
  9067. C++ delete) is probably not appropriate. Thus, the somDestruct method should be 
  9068. explicitly called to uninitialize the object before freeing memory. 
  9069.  
  9070.  
  9071. ΓòÉΓòÉΓòÉ 6.5.3. A complete example ΓòÉΓòÉΓòÉ
  9072.  
  9073. The following example illustrates the implementation and use of initializers 
  9074. and destructors from the C++ bindings. The first part shows the IDL for three 
  9075. classes with initializers. For variety, some of the classes use callstyle OIDL 
  9076. and others use callstyle IDL. 
  9077.  
  9078. #include <somobj.idl>
  9079.  
  9080. interface A : SOMObject {
  9081.         readonly attribute long a;
  9082.         implementation {
  9083.                 releaseorder: _get_a;
  9084.                 functionprefix = A;
  9085.                 somDefaultInit: override, init;
  9086.                 somDestruct: override;
  9087.                 somPrintSelf: override;
  9088.         };
  9089. };
  9090.  
  9091.  
  9092. (null)
  9093. interface B : SOMObject {
  9094.         readonly attribute long b;
  9095.         void BwithInitialValue(inout somInitCtrl ctrl,
  9096.                                in long initialValue);
  9097.         implementation {
  9098.                 callstyle = oidl;
  9099.                 releaseorder: _get_b, BwithInitialValue;
  9100.                 functionprefix = B;
  9101.                 BwithInitialValue: init;
  9102.                 somDefaultInit: override, init;
  9103.                 somDestruct: override;
  9104.                 somPrintSelf: override;
  9105.         };
  9106. };
  9107.  
  9108.  
  9109. (null)
  9110. interface C : A, B      {
  9111.         readonly attribute long c;
  9112.         void CwithInitialValue(inout somInitCtrl ctrl,
  9113.                                in long initialValue);
  9114.         void CwithInitialString(inout somInitCtrl ctrl,
  9115.                                 in string initialString);
  9116.         implementation {
  9117.                 releaseorder: _get_c, CwithInitialString,
  9118.                               CwithInitialValue;
  9119.                 functionprefix = C;
  9120.                 CwithInitialString: init;
  9121.                 CwithInitialValue: init;
  9122.                 somDefaultInit: override;
  9123.                 somDestruct: override;
  9124.                 somPrintSelf: override;
  9125.         };
  9126. };
  9127.  
  9128.  
  9129. ΓòÉΓòÉΓòÉ 6.5.3.1. Implementation code ΓòÉΓòÉΓòÉ
  9130.  
  9131. Based on the foregoing class definitions, the next example illustrates several 
  9132. important aspects of initializers. The following code is a completed 
  9133. implementation template and an example client program for the preceding 
  9134. classes. Code added to the original template is given in bold. 
  9135.  
  9136. /*
  9137.  *  This file generated by the SOM Compiler and Emitter Framework.
  9138.  *  Generated using:
  9139.  *      SOM Emitter emitxtm.dll: 2.22
  9140.  */
  9141.  
  9142. #define SOM_Module_ctorfullexample_Source
  9143. #define VARIABLE_MACROS
  9144. #define METHOD_MACROS
  9145. #include <ctorFullExample.xih>
  9146. #include <stdio.h>
  9147.  
  9148. SOM_Scope void SOMLINK AsomDefaultInit(A *somSelf,
  9149.                                        somInitCtrl* ctrl)
  9150. {
  9151.     AData *somThis; /* set by BeginInitializer */
  9152.     somInitCtrl globalCtrl;
  9153.     somBooleanVector myMask;
  9154.     AMethodDebug("A","somDefaultInit");
  9155.  
  9156.     A_BeginInitializer_somDefaultInit;
  9157.     A_Init_SOMObject_somDefaultInit(somSelf, ctrl);
  9158.     /*
  9159.      * local A initialization code added by programmer
  9160.      */
  9161. _a = 1;
  9162. }
  9163.  
  9164. SOM_Scope void SOMLINK AsomDestruct(A *somSelf, octet doFree,
  9165.                                     somDestructCtrl* ctrl)
  9166. {
  9167.     AData *somThis; /* set by BeginDestructor */
  9168.     somDestructCtrl globalCtrl;
  9169.     somBooleanVector myMask;
  9170.     AMethodDebug("A","somDestruct");
  9171.     A_BeginDestructor;
  9172.  
  9173.     /*
  9174.      * local A deinitialization code added by programmer
  9175.      */
  9176.     A_EndDestructor;
  9177. }
  9178.  
  9179. SOM_Scope SOMObject*  SOMLINK AsomPrintSelf(A *somSelf)
  9180. {
  9181.     AData *somThis = AGetData(somSelf);
  9182.     AMethodDebug("A","somPrintSelf");
  9183.     somPrintf("{an instance of %s at location %X with (a=%d)}\n",
  9184.              _somGetClassName(),somSelf,__get_a((Environment*)0));
  9185.     return (SOMObject*)((void*)somSelf);
  9186. }
  9187.  
  9188. SOM_Scope void SOMLINK BBwithInitialValue(B *somSelf,
  9189.                                           somInitCtrl* ctrl,
  9190.                                           long initialValue)
  9191. {
  9192.     BData *somThis; /* set by BeginInitializer */
  9193.     somInitCtrl globalCtrl;
  9194.     somBooleanVector myMask;
  9195.     BMethodDebug("B","BwithInitialValue");
  9196.  
  9197.     B_BeginInitializer_withInitialValue;
  9198.     B_Init_SOMObject_somDefaultInit(somSelf, ctrl);
  9199.  
  9200.     /*
  9201.      * local B initialization code added by programmer
  9202.      */
  9203.  _b = initialValue;
  9204. }
  9205.  
  9206. SOM_Scope void SOMLINK BsomDefaultInit(B *somSelf,
  9207.                                        somInitCtrl* ctrl)
  9208. {
  9209.     BData *somThis; /* set by BeginInitializer */
  9210.     somInitCtrl globalCtrl;
  9211.     somBooleanVector myMask;
  9212.     BMethodDebug("B","somDefaultInit");
  9213.  
  9214.     B_BeginInitializer_somDefaultInit;
  9215.     B_Init_SOMObject_somDefaultInit(somSelf, ctrl);
  9216.  
  9217.     /*
  9218.      * local B initialization code added by programmer
  9219.      */
  9220.  _b = 2;
  9221. }
  9222.  
  9223. SOM_Scope void SOMLINK BsomDestruct(B *somSelf, octet doFree,
  9224.                                     somDestructCtrl* ctrl)
  9225. {
  9226.     BData *somThis; /* set by BeginDestructor */
  9227.     somDestructCtrl globalCtrl;
  9228.     somBooleanVector myMask;
  9229.     BMethodDebug("B","somDestruct");
  9230.     B_BeginDestructor;
  9231.  
  9232.     /*
  9233.      * local B deinitialization code added by programmer
  9234.      */
  9235.  
  9236.     B_EndDestructor;
  9237. }
  9238.  
  9239. SOM_Scope SOMObject*  SOMLINK BsomPrintSelf(B *somSelf)
  9240. {
  9241.     BData *somThis = BGetData(somSelf);
  9242.     BMethodDebug("B","somPrintSelf");
  9243.     printf("{an instance of %s at location %X with (b=%d)}\n",
  9244.            _somGetClassName(),somSelf,__get_b());
  9245.     return (SOMObject*)((void*)somSelf);
  9246. }
  9247.  
  9248. Note: The following initializer for a C object accepts a string as an argument, 
  9249. converts this to an integer, and uses this for ancestor initialization of "B." 
  9250. This illustrates how a default ancestor initializer call is replaced with a 
  9251. non-default ancestor initializer call. 
  9252.  
  9253. SOM_Scope void SOMLINK CCwithInitialString(C *somSelf,
  9254.                                            Environment *ev,
  9255.                                            somInitCtrl* ctrl,
  9256.                                            string initialString)
  9257. {
  9258.     CData *somThis; /* set by BeginInitializer */
  9259.     somInitCtrl globalCtrl;
  9260.     somBooleanVector myMask;
  9261.     CMethodDebug("C","CwithInitialString");
  9262.  
  9263.     C_BeginInitializer_withInitialString;
  9264.     C_Init_A_somDefaultInit(somSelf, ctrl);
  9265.     C_Init_B_BwithInitialValue(somSelf, ctrl,
  9266.                                atoi(initialString)-11);
  9267.  
  9268.     /*
  9269.      * local C initialization code added by programmer
  9270.      */
  9271.     _c = atoi(initialString);
  9272. }
  9273.  
  9274. SOM_Scope void SOMLINK CsomDefaultInit(C *somSelf,
  9275.                                        somInitCtrl* ctrl)
  9276. {
  9277.     CData *somThis; /* set by BeginInitializer */
  9278.     somInitCtrl globalCtrl;
  9279.     somBooleanVector myMask;
  9280.     CMethodDebug("C","somDefaultInit");
  9281.  
  9282.     C_BeginInitializer_somDefaultInit;
  9283.     C_Init_A_somDefaultInit(somSelf, ctrl);
  9284.     C_Init_B_somDefaultInit(somSelf, ctrl);
  9285.  
  9286.     /*
  9287.      * local C initialization code added by programmer
  9288.      */
  9289. _c = 3;
  9290. }
  9291.  
  9292. SOM_Scope void SOMLINK CsomDestruct(C *somSelf, octet doFree,
  9293.                                     somDestructCtrl* ctrl)
  9294. {
  9295.     CData *somThis; /* set by BeginDestructor */
  9296.     somDestructCtrl globalCtrl;
  9297.     somBooleanVector myMask;
  9298.     CMethodDebug("C","somDestruct");
  9299.     C_BeginDestructor;
  9300.  
  9301.     /*
  9302.      * local C deinitialization code added by programmer
  9303.      */
  9304.  
  9305.     C_EndDestructor;
  9306. }
  9307.  
  9308.  
  9309. SOM_Scope SOMObject*  SOMLINK CsomPrintSelf(C *somSelf)
  9310. {
  9311.     CData *somThis = CGetData(somSelf);
  9312.     CMethodDebug("C","somPrintSelf");
  9313.     printf("{an instance of %s at location %X with"
  9314.            " (a=%d, b=%d, c=%d)}\n",
  9315.         _somGetClassName(),somSelf,
  9316.         __get_a((Environment*)0),
  9317.         __get_b(),
  9318.         __get_c((Environment*)0));
  9319.     return (SOMObject*)((void*)somSelf);
  9320. }
  9321.  
  9322. SOM_Scope void SOMLINK CCwithInitialValue(  C *somSelf,
  9323.                                         Environment *ev,
  9324.                                         somInitCtrl* ctrl,
  9325.                                         long initialValue)
  9326. {
  9327.     CData *somThis; /* set by BeginInitializer */
  9328.     somInitCtrl globalCtrl;
  9329.     somBooleanVector myMask;
  9330.     CMethodDebug("C","CwithInitialValue");
  9331.  
  9332.     C_BeginInitializer_withInitialValue;
  9333.     C_Init_A_somDefaultInit(somSelf, ctrl);
  9334.     C_Init_B_BwithInitialValue(somSelf, ctrl, initialValue-11);
  9335.  
  9336.     /*
  9337.      * local C initialization code added by programmer
  9338.      */
  9339.     _c = initialValue;
  9340. }
  9341.  
  9342. Here is a C++ program that creates instances of "A", "B", and "C" using the 
  9343. initializers defined above. 
  9344.  
  9345. main()
  9346. {
  9347.     SOM_TraceLevel = 1;
  9348.  
  9349.     A *a = new A;
  9350.     a->somPrintSelf();
  9351.     delete a;
  9352.     printf("\n");
  9353.  
  9354.     B *b = new B();
  9355.     b->somPrintSelf();
  9356.     delete b;
  9357.     printf("\n");
  9358.  
  9359.     b = new B(22);
  9360.     b->somPrintSelf();
  9361.     delete b;
  9362.     printf("\n");
  9363.  
  9364.     C *c = new C;
  9365.     c->somPrintSelf();
  9366.     delete c;
  9367.     printf("\n");
  9368.  
  9369.     c = new C((Environment*)0, 44);
  9370.     c->somPrintSelf();
  9371.     delete c;
  9372.     printf("\n");
  9373.  
  9374.     c = new C((Environment*)0, "66");
  9375.     c->somPrintSelf();
  9376.     delete c;
  9377. }
  9378.  
  9379. The output from the preceding program is as follows: 
  9380.  
  9381. "ctorFullExample.C": 18:        In A:somDefaultInit
  9382. "ctorFullExample.C": 48:        In A:somPrintSelf
  9383. "./ctorFullExample.xih": 292:     In A:A_get_a
  9384. {an instance of A at location 20063C38 with (a=1)}
  9385. "ctorFullExample.C": 35:        In A:somDestruct
  9386.  
  9387. "ctorFullExample.C": 79:        In B:somDefaultInit
  9388. "ctorFullExample.C": 110: In B:somPrintSelf
  9389. "./ctorFullExample.xih": 655:     In B:B_get_b
  9390. {an instance of B at location 20064578 with (b=2)}
  9391. "ctorFullExample.C": 97:        In B:somDestruct
  9392.  
  9393. "ctorFullExample.C": 62:        In B:BwithInitialValue
  9394. "ctorFullExample.C": 110: In B:somPrintSelf
  9395. "./ctorFullExample.xih": 655:     In B:B_get_b
  9396. {an instance of B at location 20064578 with (b=22)}
  9397. "ctorFullExample.C": 97:        In B:somDestruct
  9398.  
  9399. "ctorFullExample.C": 150: In C:somDefaultInit
  9400. "ctorFullExample.C": 18:        In A:somDefaultInit
  9401. "ctorFullExample.C": 79:        In B:somDefaultInit
  9402. "ctorFullExample.C": 182: In C:somPrintSelf
  9403. "./ctorFullExample.xih": 292:     In A:A_get_a
  9404. "./ctorFullExample.xih": 655:     In B:B_get_b
  9405. "./ctorFullExample.xih": 1104:    In C:C_get_c
  9406. {an instance of C at location 20065448 with (a=1, b=2, c=3)}
  9407. "ctorFullExample.C": 169: In C:somDestruct
  9408. "ctorFullExample.C": 35:        In A:somDestruct
  9409. "ctorFullExample.C": 97:        In B:somDestruct
  9410.  
  9411. "ctorFullExample.C": 196: In C:CwithInitialValue
  9412. "ctorFullExample.C": 18:        In A:somDefaultInit
  9413. "ctorFullExample.C": 62:        In B:BwithInitialValue
  9414. "ctorFullExample.C": 182: In C:somPrintSelf
  9415. "./ctorFullExample.xih": 292:     In A:A_get_a
  9416. "./ctorFullExample.xih": 655:     In B:B_get_b
  9417. "./ctorFullExample.xih": 1104:      In C:C_get_c
  9418. {an instance of C at location 20065448 with (a=1, b=33, c=44)}
  9419. "ctorFullExample.C": 169: In C:somDestruct
  9420. "ctorFullExample.C": 35:        In A:somDestruct
  9421. "ctorFullExample.C": 97:        In B:somDestruct
  9422.  
  9423.  
  9424.  
  9425. "ctorFullExample.C": 132: In C:CwithInitialString
  9426. "ctorFullExample.C": 18:        In A:somDefaultInit
  9427. "ctorFullExample.C": 62:        In B:BwithInitialValue
  9428. "ctorFullExample.C": 182: In C:somPrintSelf
  9429. "./ctorFullExample.xih": 292:     In A:A_get_a
  9430. "./ctorFullExample.xih": 655:     In B:B_get_b
  9431. "./ctorFullExample.xih": 1104:      In C:C_get_c
  9432. {an instance of C at location 20065448 with (a=1, b=55, c=66)}
  9433. "ctorFullExample.C": 169: In C:somDestruct
  9434. "ctorFullExample.C": 35:        In A:somDestruct
  9435. "ctorFullExample.C": 97:        In B:somDestruct
  9436.  
  9437.  
  9438. ΓòÉΓòÉΓòÉ 6.5.4. Customizing the initialization of class objects ΓòÉΓòÉΓòÉ
  9439.  
  9440. As described previously, the somDefaultInit method can be overridden to 
  9441. customize the initialization of objects. Because classes are objects, 
  9442. somDefaultInit is also invoked on classes when they are first created 
  9443. (generally by invoking the somNew method on a metaclass). For a class object, 
  9444. however, somDefaultInit normally just sets the name of the class to "unknown," 
  9445. after which the somInitMIClass method must be used for the major portion of 
  9446. class initialization. Of course, metaclasses can override somDefaultInit to 
  9447. initialize introduced class variables that require no arguments for their 
  9448. initialization. 
  9449.  
  9450. Note: Because somNew does not call somInitMIClass, class objects returned from 
  9451. invocations of somNew on a metaclass are not yet useful class objects. 
  9452.  
  9453. The somInitMIClass method (introduced by SOMClass) is invoked on a new class 
  9454. object using arguments to indicate the class name and the parent classes from 
  9455. which inheritance is desired (among other arguments). This invocation is made 
  9456. by whatever routine is used to initialize the class. (For SOM classes using the 
  9457. C or C++ implementation bindings, this is handled by the somBuildClass 
  9458. procedure, which is called by the implementation bindings automatically.) The 
  9459. somInitMIClass method is often overridden by a metaclass to influence 
  9460. initialization of new classes in some way. Typically, the overriding procedure 
  9461. begins by making parent method calls, and then performs additional actions 
  9462. thereafter. 
  9463.  
  9464. However, without use of the Cooperative Metaclass to guarantee correct 
  9465. operation of SOMobjects in general, none of the methods introduced by SOMClass 
  9466. should be overridden. As a result, customizing the initialization of class 
  9467. objects (other than through overriding somDefaultInit for initialization of 
  9468. class variables) is not recommended in SOMobjects 2.1.  Users whose 
  9469. applications require this should request access to the experimental Cooperative 
  9470. Metaclass used to implement the SOMobjects Metaclass Framework.  But, 
  9471. metaclasses implemented using the experimental Cooperative Metaclass may 
  9472. require reprogramming when SOMobjects introduces an officially supported 
  9473. Cooperative Metaclass. 
  9474.  
  9475.  
  9476. ΓòÉΓòÉΓòÉ 6.6. Creating a SOM Class Library ΓòÉΓòÉΓòÉ
  9477.  
  9478. One of the principal advantages of SOM is that it makes "black box" (or binary) 
  9479. reusability possible. Consequently, SOM classes are frequently packaged and 
  9480. distributed as class libraries. A class library  holds the actual 
  9481. implementation of one or more classes and can be dynamically loaded and 
  9482. unloaded as needed by applications. Importantly, class libraries can also be 
  9483. replaced independently of the applications  that use them and, provided that 
  9484. the class implementor observes simple SOM guidelines for preserving binary 
  9485. compatibility, can evolve and expand over time. 
  9486.  
  9487.  
  9488. ΓòÉΓòÉΓòÉ 6.6.1. General guidelines for class library designers ΓòÉΓòÉΓòÉ
  9489.  
  9490. One of the most important features of SOM is that it allows you to build and 
  9491. distribute class libraries in binary form. Because there is no "fragile base 
  9492. class" problem in SOM, client programs that use your libraries (by subclassing 
  9493. your classes or by invoking the methods in your classes) will not need to be 
  9494. recompiled if you later produce a subsequent version of the library, provided 
  9495. you adhere to some simple restrictions. 
  9496.  
  9497.    1. You should always maintain the syntax and the semantics of your existing 
  9498.       interfaces. This means that you cannot take away any exposed 
  9499.       capabilities, nor add or remove arguments for any of your public methods. 
  9500.  
  9501.    2. Always maintain the releaseorder list, so that it never changes except 
  9502.       for additions to the end. The releaseorder should contain all of your 
  9503.       public methods, the one or two methods that correspond to each public 
  9504.       attribute, and a placeholder for each private method (or private 
  9505.       attribute method). 
  9506.  
  9507.    3. Assign a higher minorversion number for each subsequent release of a 
  9508.       class, so that client programmers can determine whether a new feature is 
  9509.       present or not. Change the majorversion number only when you deliberately 
  9510.       wish to break binary compatibility. (See the topic "Modifier statements" 
  9511.       in Chapter 4, "SOM IDL and the SOM Compiler" for explanations of the 
  9512.       releaseorder, minorversion and majorversion modifiers.) 
  9513.  
  9514.    4. Under Windows, you should avoid the use of methods or attributes that 
  9515.       return structures. In the DOS/Windows environment, there is no 
  9516.       universally agreed upon calling convention for returning structures that 
  9517.       is observed by all popular language compilers. Instead, define attributes 
  9518.       that return pointers to structures, or define methods that take an out 
  9519.       parameter for passing a structure back to the caller. 
  9520.  
  9521.       Note that you can always avoid this problem in classes of your own 
  9522.       design. However, some of the attributes and methods in the frameworks 
  9523.       that come with the SOMobjects Toolkit do  return structures. Many of 
  9524.       these are dictated by the OMG CORBA standard, and could not be avoided. 
  9525.       For each of these methods two common calling conventions have been 
  9526.       implemented: 
  9527.  
  9528.           Microsoft convention, where the address of the structure is returned 
  9529.            in AX:DX, and 
  9530.  
  9531.           Borland convention, where the caller provides a hidden first 
  9532.            argument to receive a copy of the returned structure. 
  9533.  
  9534.       No action is needed on your part to use the Microsoft convention. To use 
  9535.       the Borland convention, you should include the file BCCSTRUC.H following 
  9536.       any other "includes" of SOM headers. 
  9537.  
  9538.    5. With each new release of your class library, you have significant degrees 
  9539.       of freedom to change much of the implementation detail. You can add to or 
  9540.       reorganize your instance variables, add new public or private methods, 
  9541.       inject new base classes into your class hierarchies, change metaclasses 
  9542.       to more derived ones, and relocate the implementation of methods upward 
  9543.       in your class hierarchies. Provided you always retain the same 
  9544.       capabilities and semantics that were present in your first release, none 
  9545.       of these changes will break the client programs that use your libraries. 
  9546.  
  9547.  
  9548. ΓòÉΓòÉΓòÉ 6.6.2. Types of class libraries ΓòÉΓòÉΓòÉ
  9549.  
  9550. Since class libraries are not programs, users cannot execute them directly. To 
  9551. enable users to make direct use of your classes, you must also provide one or 
  9552. more programs that create the classes and objects that the user will need. This 
  9553. section describes how to package your classes in a SOM class library and what 
  9554. you must do to make the contents of the library accessible to other programs. 
  9555.  
  9556. On AIX, class libraries are actually produced as AIX shared libraries, whereas 
  9557. on OS/2 or Windows they appear as dynamically-linked libraries (or DLLs). The 
  9558. term "DLL" is sometimes used to refer to either an AIX, an OS/2, or a Windows 
  9559. class library, and (by convention only) the file suffix ".dll" is used for SOM 
  9560. class libraries on all platforms. 
  9561.  
  9562. A program can use a class library containing a given class or classes in one of 
  9563. two ways: 
  9564.  
  9565.    1. If the programmer employs the SOM bindings to instantiate the class and 
  9566.       invoke its methods, the resulting client program contains static 
  9567.       references to the class. The operating system will automatically resolve 
  9568.       those references when the program is loaded, by also loading the 
  9569.       appropriate class library. 
  9570.  
  9571.    2. If the programmer uses only the dynamic SOM mechanisms for finding the 
  9572.       class and invoking its methods (for example, by invoking somFindClass, 
  9573.       somFindMethod, somLookupMethod, somDispatch, somResolveByName,and so 
  9574.       forth), the resulting client program does not contain any static 
  9575.       references to the class library. Thus, SOM will load the class library 
  9576.       dynamically during execution of the program. Note: For SOM to be able to 
  9577.       load the class library, the dllname modifier must be set in the .idl 
  9578.       file. (See the topic "Modifier statements" in Chapter 4, "SOM IDL and the 
  9579.       SOM Compiler.") 
  9580.  
  9581.  Because the provider of a class library cannot predict which of these ways a 
  9582.  class will be used, SOM class libraries must be built such that either usage 
  9583.  is possible. The first case above requires the class library to export the 
  9584.  entry points needed by the SOM bindings, whereas the second case requires the 
  9585.  library to provide an initialization function to create the classes it 
  9586.  contains. The following topics discuss each case. 
  9587.  
  9588.  
  9589. ΓòÉΓòÉΓòÉ 6.6.3. Building export files ΓòÉΓòÉΓòÉ
  9590.  
  9591. The SOM Compiler provides an "exp" emitter for AIX and a "def" emitter for OS/2 
  9592. to produce the necessary exported symbols for each class. For example, to 
  9593. generate the necessary exports for a class "A", issue the sc or somc command 
  9594. with one of the following -s options. (For a discussion of the sc or somc 
  9595. command and options, see "Running the SOM Compiler" in Chapter 4, "SOM IDL and 
  9596. the SOM Compiler.") 
  9597.  
  9598. For AIX, this command generates an "a.exp" file: 
  9599.  
  9600.    sc -sexp a.idl
  9601.  
  9602. For OS/2, this command generates an "a.def" file: 
  9603.  
  9604.    sc -sdef a.idl
  9605.  
  9606. Typically, a class library contains multiple classes. To produce an appropriate 
  9607. export file for each class that the library will contain, you can create a new 
  9608. export file for the library itself by combining the exports from each "exp" or 
  9609. "def" file into a single file. Following are examples of a combined export 
  9610. "exp" file for AIX and a combined "def" file for OS/2. Each example illustrates 
  9611. a class library composed of three classes, "A", "B", and "C". 
  9612.  
  9613. AIX "exp" file: 
  9614.  
  9615.    #! abc.dll
  9616.    ACClassData
  9617.    AClassData
  9618.    ANewClass
  9619.    BCClassData
  9620.    BClassData
  9621.    BNewClass
  9622.    CCClassData
  9623.    CClassData
  9624.    CNewClass
  9625.  
  9626. OS/2 "def" file: 
  9627.  
  9628.    LIBRARY abc INITINSTANCE
  9629.    DESCRIPTION 'abc example class library'
  9630.    PROTMODE
  9631.    DATA MULTIPLE NONSHARED LOADONCALL
  9632.    EXPORTS
  9633.      ACClassData
  9634.      AClassData
  9635.      ANewClass
  9636.      BCClassData
  9637.      BClassData
  9638.      BNewClass
  9639.      CCClassData
  9640.      CClassData
  9641.      CNewClass
  9642.  
  9643. Other symbols in addition to those generated by the "def" or "exp" emitter can 
  9644. be included if needed, but this is not required by SOM. One feature of SOM is 
  9645. that a class library needs no more than three exports per class (by contrast, 
  9646. many OOP systems require externals for every method as well). One required 
  9647. export is the name of a procedure to create the class (<className>NewClass), 
  9648. and the others are two external data structures that are referenced by the SOM 
  9649. bindings. 
  9650.  
  9651.  
  9652. ΓòÉΓòÉΓòÉ 6.6.4. Specifying the initialization function ΓòÉΓòÉΓòÉ
  9653.  
  9654. An initialization function for the class library must be provided to support 
  9655. dynamic loading of the library by the SOM Class Manager. The SOM Class Manager 
  9656. expects that, whenever it loads a class library, the initialization function 
  9657. will create and register class objects for all of the classes contained in the 
  9658. library. 
  9659.  
  9660. These classes are then managed as a group (called an affinity group). One class 
  9661. in the affinity group has a privileged position-namely, the class that was 
  9662. specifically requested when the library was loaded. If that class (that is, the 
  9663. class that caused loading to occur) is subsequently unregistered, the SOM Class 
  9664. Manager will automatically unregister all of the other classes in the affinity 
  9665. group as well, and will unload the class library. Similarly, if the SOM Class 
  9666. Manager is explicitly asked to unload the class library, it will also 
  9667. automatically unregister and free all of the classes in the affinity group. 
  9668.  
  9669. It is the responsibility of the class-library creator to supply the 
  9670. initialization function. The interface to the initialization function is given 
  9671. by the following C/C++ prototype: 
  9672.  
  9673. #ifdef __IBMC__
  9674.   #pragma linkage (SOMInitModule, system)
  9675. #endif
  9676.  
  9677. SOMEXTERN void  SOMLINK SOMInitModule ( long majorVersion,
  9678.                                         long minorVersion,
  9679.                                         string className);
  9680.  
  9681. The parameters provided to this function are the className and the major/minor 
  9682. version numbers of the class that was requested when the library was loaded 
  9683. (that is, the class that caused loading). The initialization function is free 
  9684. to use or to disregard this information; nevertheless, if it fails to create a 
  9685. class object with the required name, the SOM Class Manager considers the load 
  9686. to have failed. As a rule of thumb, however, if the initialization function 
  9687. invokes a <className>NewClass procedure for each class in the class library, 
  9688. this condition will always be met. Consequently, the parameters supplied to the 
  9689. initialization function are not needed in most cases. 
  9690.  
  9691. Here is a typical class-library initialization function, written in C, for a 
  9692. library with three classes ("A", "B", and "C"): 
  9693.  
  9694.    #include "a.h"
  9695.    #include "b.h"
  9696.    #include "c.h"
  9697.    #ifdef __IBMC__
  9698.      #pragma linkage (SOMInitModule, system)
  9699.    #endif
  9700.  
  9701.    SOMEXTERN void  SOMLINK SOMInitModule (long majorVersion,
  9702.                              long minorVersion, string className)
  9703.    {
  9704.        SOM_IgnoreWarning (majorVersion);  /* This function makes */
  9705.        SOM_IgnoreWarning (minorVersion);  /* no use of the passed */
  9706.        SOM_IgnoreWarning (className);     /* arguments.   */
  9707.        ANewClass (A_MajorVersion, A_MinorVersion);
  9708.        BNewClass (B_MajorVersion, B_MinorVersion);
  9709.        CNewClass (C_MajorVersion, C_MinorVersion);
  9710.    }
  9711.  
  9712. The source code for the initialization function can be added to one of the 
  9713. implementation files for the classes in the library, or you can put it in a 
  9714. separate file and compile it independently. 
  9715.  
  9716.  
  9717. ΓòÉΓòÉΓòÉ 6.6.4.1. Using Windows class libraries ΓòÉΓòÉΓòÉ
  9718.  
  9719. Some additional considerations apply for Windows class libraries: Each class 
  9720. library must also supply a Windows LibMain function. The LibMain function is 
  9721. invoked automatically whenever a Windows DLL is loaded, and is responsible for 
  9722. identifying the library and its SOMInitModule function to the SOM Kernel. Here 
  9723. is an example of a typical Windows LibMain function for a SOM class library as 
  9724. it would appear in a C or C++ program: 
  9725.  
  9726.     #include <som.h>
  9727.     SOMEXTERN void SOMLINK SOMInitModule (long majorVersion,
  9728.                                           long minorVersion,
  9729.                                           string className);
  9730.  
  9731.     #include <windows.h>
  9732.     int CALLBACK LibMain (HINSTANCE inst,
  9733.                           WORD ds,
  9734.                           WORD Heapsize,
  9735.                           LPSTR cmdLine)
  9736.     {
  9737.         SOM_IgnoreWarning (inst);
  9738.         SOM_ignoreWarning (ds);
  9739.         SOM_IgnoreWarning (heapSize);
  9740.         SOM_IgnoreWarning (cmdLine);
  9741.  
  9742.         SOM_ClassLibrary ("xyz.dll");
  9743.         return 1;  /* Indicate success to loader */
  9744.     }
  9745.  
  9746. The only operative statement in the LibMain function is the macro 
  9747. SOM_ClassLibrary, which identifies the actual file name of the library as it 
  9748. would appear in a Windows LoadLibrary call, and internally generates a 
  9749. reference to the library's SOMInitModule function. This information is passed 
  9750. to the SOM Kernel, which in turn registers the library and schedules the 
  9751. execution of the SOMInitModule function. 
  9752.  
  9753. Typically, the SOM Kernel invokes the SOMInitModule function of each statically 
  9754. loaded class library during execution of the SOM_MainProgram macro within the 
  9755. using application; otherwise, SOMInitModule is invoked immediately upon 
  9756. completio of the dynamic loading of a class library by an already executing 
  9757. application. Regardless of the loading mechanism, the SOM Kernel guarantees 
  9758. that the SOMInitModule function executes exactly once for each class library. 
  9759.  
  9760.  
  9761. ΓòÉΓòÉΓòÉ 6.6.5. Creating the import library ΓòÉΓòÉΓòÉ
  9762.  
  9763. Finally, for each of your class libraries, you should create an import library 
  9764. that can be used by client programs (or by other class libraries that use your 
  9765. classes) to resolve the references to your classes. 
  9766.  
  9767. Here is an example illustrating all of the steps required to create a class 
  9768. library ("abc.dll") that contains the three classes "A", "B", and "C". 
  9769.  
  9770.    1. Compile all of the implementation files for the classes that will be 
  9771.       included in the library. Include the initialization function also. 
  9772.  
  9773.       For AIX written in C: 
  9774.  
  9775.               xlc -I. -I$SOMBASE/include -c a.c
  9776.               xlc -I. -I$SOMBASE/include -c b.c
  9777.               xlc -I. -I$SOMBASE/include -c c.c
  9778.               xlc -I. -I$SOMBASE/include -c initfunc.c
  9779.  
  9780.       For AIX written in C++: 
  9781.  
  9782.               xlC -I. -I$SOMBASE/include -c a.C
  9783.               xlC -I. -I$SOMBASE/include -c b.C
  9784.               xlC -I. -I$SOMBASE/include -c c.C
  9785.               xlC -I. -I$SOMBASE/include -c initfunc.C
  9786.  
  9787.       For OS/2 written in C: 
  9788.  
  9789.                icc -I. -I%SOMBASE%\include -Ge- -c a.c
  9790.                icc -I. -I%SOMBASE%\include -Ge- -c b.c
  9791.                icc -I. -I%SOMBASE%\include -Ge- -c c.c
  9792.                icc -I. -I%SOMBASE%\include -Ge- -c initfunc.c
  9793.  
  9794.       Note:  The "-GE" option is used only with the IBM compiler.  It indicates 
  9795.              that the object files will go into a DLL. 
  9796.  
  9797.       For OS/2 written in C++: 
  9798.  
  9799.                icc -I. -I%SOMBASE%\include -Ge- -c a.cpp
  9800.                icc -I. -I%SOMBASE%\include -Ge- -c b.cpp
  9801.                icc -I. -I%SOMBASE%\include -Ge- -c c.cpp
  9802.                icc -I. -I%SOMBASE%\include -Ge- -c initfunc.cpp
  9803.  
  9804.       Note:  The "-Ge" option is used only with the IBM compiler.  It indicates 
  9805.              that the object files will go into a DLL. 
  9806.  
  9807.    2. Produce an export file for each class. 
  9808.  
  9809.       For AIX: 
  9810.  
  9811.                sc -sexp a.idl b.idl c.idl
  9812.  
  9813.       For OS/2: 
  9814.  
  9815.                sc -sdef a.idl b.idl c.idl
  9816.  
  9817.    3. Manually combine the exported symbols into a single file. 
  9818.  
  9819.       For AIX, create a file "abc.exp" from "a.exp", "b.exp", and "c.exp". Do 
  9820.       not include the initialization function (SOMInitModule) in the export 
  9821.       list. 
  9822.  
  9823.       For OS/2, create a file "abc.def" from "a.def", "b.def", and  c.def". 
  9824.       Include the initialization function (SOMInitModule) in the export list, 
  9825.       so that all classes will be initialized automatically, unless your 
  9826.       initialization function does not need arguments and you explicitly invoke 
  9827.       it yourself from an OS/2 DLL initialization routine. 
  9828.  
  9829.    4. Using the object files and the export file, produce a binary class 
  9830.       library. 
  9831.  
  9832.       For AIX: 
  9833.  
  9834.                ld -o abc.dll -bE:abc.exp -e SOMInitModule -H512 -T512 \
  9835.                   a.o b.o c.o initfunc.o -lc -L$SOMBASE/lib -lsomtk
  9836.  
  9837.       The -o option assigns a name to the class library ("abc.dll"). The -bE: 
  9838.       option designates the file with the appropriate export list. The -e 
  9839.       option designates SOMInitModule as the initialization function. The -H 
  9840.       and -T options must be supplied as shown; they specify the necessary 
  9841.       alignment information for the text and data portions of your code. The -l 
  9842.       options name the specific libraries needed by your classes. If your 
  9843.       classes make use of classes in other class libraries, include a -l option 
  9844.       for each of these also. The ld command looks for a library named 
  9845.       "lib<x>.a", where <x> is the name provided with each -l option. The -L 
  9846.       option specifies the directory where the "somtk" library resides. 
  9847.  
  9848.       For OS/2: 
  9849.  
  9850.                set LIB=%SOMBASE%\lib;%LIB%
  9851.                link386 /noi /packd /packc /align:16 /exepack \
  9852.                    a.obj b.obj c.obj initfunc.obj, abc.dll,,os2386 somtk, \
  9853.                    abc.def
  9854.  
  9855.       If your classes make use of classes in other class libraries, include the 
  9856.       names of their import libraries immediately after "somtk" (before the 
  9857.       next comma). 
  9858.  
  9859.    5. Create an import library that corresponds to the class library, so that 
  9860.       programs and other class libraries can use (import) your classes. 
  9861.  
  9862.  For AIX: 
  9863.  
  9864.      ar ruv libabc.a abc.exp   Note the use of the  ".exp" file, not a ".o" file
  9865.  
  9866.  The first filename ("libabc.a") specifies the name to give to the import 
  9867.  library. It should be of the form "lib<x>.a", where <x> represents your class 
  9868.  library. The second filename ("abc.exp") specifies the exported symbols to 
  9869.  include in the import library. 
  9870.  
  9871.  Caution: Although AIX shared libraries can be placed directly into an archive 
  9872.  file ("lib<x>.a"), this is not recommended! A SOM class library should have a 
  9873.  corresponding import library constructed directly from the combined export 
  9874.  file. 
  9875.  
  9876.  For OS/2: 
  9877.  
  9878.      implib /noi abc.lib abc.def
  9879.  
  9880.  The first filename ("abc.lib") specifies the name for the import library and 
  9881.  should always have a suffix of ".lib". The second filename ("abc.def") 
  9882.  specifies the exported symbols to include in the import library. 
  9883.  
  9884.  Note:  SOMInitModule should be included in the <x>.dll but not in <x>.lib.  If 
  9885.         you are using an export file that contains the symbol SOMInitModule, 
  9886.         delete it first; SOMInitModule should not appear in your import library 
  9887.         because it need not be exported. SOMInitModule should be included when 
  9888.         creating your file <x>.dll because all classes in the <x>.dll will be 
  9889.         initialized. 
  9890.  
  9891.  
  9892. ΓòÉΓòÉΓòÉ 6.7. Customizing Memory Management ΓòÉΓòÉΓòÉ
  9893.  
  9894. SOM is designed to be policy free and highly adaptable. Most of the SOM 
  9895. behavior can be customized by subclassing the built-in classes and overriding 
  9896. their methods, or by replacing selected functions in the SOM run-time library 
  9897. with application code. This chapter contains more advanced topics describing 
  9898. how to customize the following aspects of SOM behavior: memory management, 
  9899. dynamic class loading and unloading, character output, error handling, and 
  9900. method resolution. Information on customizing Distributed SOM is provided in 
  9901. Chapter 6. 
  9902.  
  9903. The memory management functions used by the SOM run-time environment are a 
  9904. subset of those supplied in the ANSI C standard library. They have the same 
  9905. calling interface and return the equivalent types of results as their ANSI C 
  9906. counterparts, but include some supplemental error checking. Errors detected in 
  9907. these functions result in the invocation of the error-handling function to 
  9908. which SOMError points. 
  9909.  
  9910. The correspondence between the SOM memory-management function variables and 
  9911. their ANSI standard library equivalents is given in the table below. 
  9912.  
  9913. Memory-Management Functions 
  9914.  
  9915. ΓöîΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÉ
  9916. ΓöéSOM FUNCTION   ΓöéANSI STANDARD CΓöéRETURN TYPE ΓöéARGUMENT TYPES    Γöé
  9917. ΓöéVARIABLE       ΓöéLIBRARY        Γöé            Γöé                  Γöé
  9918. Γöé               ΓöéFUNCTION       Γöé            Γöé                  Γöé
  9919. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  9920. ΓöéSOMCalloc      Γöécalloc( )      ΓöésomToken    Γöésize_t, size_t    Γöé
  9921. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  9922. ΓöéSOMFree        Γöéfree( )        Γöévoid        ΓöésomToken          Γöé
  9923. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  9924. ΓöéSOMMalloc      Γöémalloc( )      ΓöésomToken    Γöésize_t            Γöé
  9925. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  9926. ΓöéSOMRealloc     Γöérealloc( )     ΓöésomToken    ΓöésomToken, size_t  Γöé
  9927. ΓööΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÿ
  9928.  
  9929. An application program can replace SOM's memory management functions with its 
  9930. own memory management functions to change the way SOM allocates memory (for 
  9931. example, to perform all memory allocations as suballocations in a shared memory 
  9932. heap). This replacement is possible because SOMCalloc, SOMMalloc, SOMRealloc, 
  9933. and SOMFree are actually global variables that point to SOM's default memory 
  9934. management functions, rather than being the names of the functions themselves. 
  9935. Thus, an application program can replace SOM's default memory management 
  9936. functions by assigning the entry-point address of the user-defined memory 
  9937. management function to the appropriate global variable. For example, to replace 
  9938. the default free procedure with the user-defined function MyFree (which must 
  9939. have the same signature as the ANSI C free function), an application program 
  9940. would require the following code: 
  9941.  
  9942. #include <som.h>
  9943. /* Define a replacement routine: */
  9944.  
  9945. #ifdef __OS2__                  /* not for SOM 3.0 */
  9946. #pragma linkage(myFree, system) /* not for SOM 3.0 */
  9947. #endif                          /* not for SOM 3.0 */
  9948.  
  9949. void SOMLINK myFree (somToken memPtr)
  9950. {
  9951.      (Customized code goes here)
  9952. }
  9953. ...
  9954. SOMFree = myFree;
  9955.  
  9956. Note:  In general, all of these routines should be replaced as a group. For 
  9957.        instance, if an application supplies a customized version of SOMMalloc, 
  9958.        it should also supply correponding SOMCalloc, SOMFree, and SOMRealloc 
  9959.        functions that conform to this same style of memory management. 
  9960.  
  9961.  
  9962. ΓòÉΓòÉΓòÉ 6.8. Customizing Class Loading and Unloading ΓòÉΓòÉΓòÉ
  9963.  
  9964. SOM uses three routines that manage the loading and unloading of class 
  9965. libraries (referred to here as DLLs). These routines are called by the 
  9966. SOMClassMgrObject  as it dynamically loads and registers classes. If 
  9967. appropriate, the rules that govern the loading and unloading of DLLs can be 
  9968. modified, by replacing these functions with alternative implementations. 
  9969.  
  9970.  
  9971. ΓòÉΓòÉΓòÉ 6.8.1. Customizing class initialization ΓòÉΓòÉΓòÉ
  9972.  
  9973. The SOMClassInitFuncName function has the following signature: 
  9974.  
  9975. string  (*SOMClassInitFuncName) ( ); 
  9976.  
  9977. This function returns the name of the function that will initialize (create 
  9978. class objects for) all of the classes that are packaged together in a single 
  9979. class library. (This function name applies to all class libraries loaded by the 
  9980. SOMClassMgrObject.) The SOM-supplied version of SOMClassInitFuncName returns 
  9981. the string " SOMInitModule".  The interface to the library initialization 
  9982. function is described under the topic "Creating a SOM Class Library" earlier in 
  9983. this chapter. 
  9984.  
  9985.  
  9986. ΓòÉΓòÉΓòÉ 6.8.2. Customizing DLL loading ΓòÉΓòÉΓòÉ
  9987.  
  9988. To dynamically load a SOM class, the SOMClassMgrObject  calls the function 
  9989. pointed to by the global variable SOMLoadModule to load the DLL containing the 
  9990. class. The reason for making public the SOMLoadModule function (and the 
  9991. following SOMDeleteModule function) is to reveal the boundary where SOM touches 
  9992. the operating system. Explicit invocation of these functions is never required. 
  9993. However, they are provided to allow class implementors to insert their own code 
  9994. between the operating system and SOM, if desired. The  SOMLoadModule function 
  9995. has the following signature: 
  9996.  
  9997.  long  (*SOMLoadModule)   ( string className, 
  9998.  
  9999.                                                       string fileName,
  10000.  
  10001.                                                      string functionName,
  10002.  
  10003.                                                      long majorVersion,
  10004.  
  10005.                                                      long minorVersion,
  10006.  
  10007.                                                      somToken *modHandle);
  10008.  
  10009.  This function is responsible for loading the DLL containing the SOM class 
  10010.  className and returning either the value zero (for success) or a nonzero 
  10011.  system-specific error code. The output argument modHandle is used to return a 
  10012.  token that can subsequently be used by the DLL-un loading routine (described 
  10013.  below) to unload the DLL. The default DLL-loading routine returns the DLL's 
  10014.  module handle in this argument. The remaining arguments are used as follows: 
  10015.  
  10016.  Argument                 Usage 
  10017.  
  10018.  fileName                 The file name of the DLL to be loaded, which can be 
  10019.                           either a simple name or a full path name. 
  10020.  
  10021.  functionName             The name of the routine to be called after the DLL is 
  10022.                           successfully loaded by the SOMClassMgrObject. This 
  10023.                           routine is responsible for creating the class objects 
  10024.                           for the class(es) contained in the DLL. Typically, 
  10025.                           this argument has the value "SOMInitModule", which is 
  10026.                           obtained from the function SOMClassInitFuncName 
  10027.                           described above. If no SOMInitModule entry exists in 
  10028.                           the DLL, the default DLL-loading routine looks in the 
  10029.                           DLL for a procedure with the name <className>NewClass 
  10030.                           instead. If neither entry point can be found, the 
  10031.                           default DLL-loading routine fails. 
  10032.  
  10033.  majorVersion             The major version number to be passed to the class 
  10034.                           initialization function in the DLL (specified by the 
  10035.                           functionName argument). 
  10036.  
  10037.  minorVersion             The minor version number to be passed to the class 
  10038.                           initialization function in the DLL (specified by the 
  10039.                           FunctionName argument). 
  10040.  
  10041.  An application program can replace the default DLL-loading routine by 
  10042.  assigning the entry point address of the new DLL-loading function (such as 
  10043.  MyLoadModule) to the global variable SOMLoadModule, as follows: 
  10044.  
  10045.   #include <som.h>
  10046.   /* Define a replacement routine: */
  10047.   long myLoadModule (string className, string fileName,
  10048.                      string functionName, long majorVersion,
  10049.                      long minorVersion, somToken *modHandle)
  10050.   {
  10051.        (Customized code goes here)
  10052.   }
  10053.   ...
  10054.   SOMLoadModule = MyLoadModule;
  10055.  
  10056.  
  10057. ΓòÉΓòÉΓòÉ 6.8.3. Customizing DLL unloading ΓòÉΓòÉΓòÉ
  10058.  
  10059. To unload a SOM class, the SOMClassMgrObject calls the function pointed to by 
  10060. the global variable SOMDeleteModule. The SOMDeleteModule function has the 
  10061. following signature: 
  10062.  
  10063. long  (*SOMDeleteModule)  (in somToken modHandle); 
  10064.  
  10065. This function is responsible for unloading the DLL designated by the modHandle 
  10066. parameter and returning either zero (for success) or a nonzero system-specific 
  10067. error code. The parameter modHandle contains the value returned by the DLL 
  10068. loading routine (described above) when the DLL was loaded. 
  10069.  
  10070. An application program can replace the default DLL-unloading routine by 
  10071. assigning the entry point address of the new DLL-unloading function (such as, 
  10072. MyDeleteModule) to the global variable SOMDeleteModule, as follows: 
  10073.  
  10074. #include <som.h>
  10075. /* Define a replacement routine: */
  10076. long myDeleteModule (somToken modHandle)
  10077. {
  10078.      (Customized code goes here)
  10079. }
  10080. ...
  10081. SOMDeleteModule = MyDeleteModule;
  10082.  
  10083.  
  10084. ΓòÉΓòÉΓòÉ 6.9. Customizing Character Output ΓòÉΓòÉΓòÉ
  10085.  
  10086. The SOM character-output function is invoked by all of the SOM error-handling 
  10087. and debugging macros whenever a character must be generated (see "Debugging" 
  10088. and "Exceptions and error handling" in Using SOM Classes in Client Programs, 
  10089. "Using SOM Classes in Client Programs"). The default character-output routine, 
  10090. pointed to by the global variable SOMOutCharRoutine, simply writes the 
  10091. character to "stdout", then returns 1 if successful, or 0 otherwise. 
  10092.  
  10093. For convenience, SOMOutCharRoutine is supplemented by the somSetOutChar 
  10094. function.  The somSetOutChar function enables each task to have a customized 
  10095. character output routine, thus it is often preferred for changing the output 
  10096. routine called by somPrintf (because SOMOutChrRoutine would remain in effect 
  10097. for subsequent tasks).  On Windows, the somSetOutChar function is required 
  10098. (rather than SOMOutCharRoutine); it is optional on other operating systems. 
  10099.  
  10100. An application programmer might wish to supply a customized replacement routine 
  10101. to: 
  10102.  
  10103.      Direct the output to stderr, 
  10104.  
  10105.      Record the output in a log file, 
  10106.  
  10107.      Collect characters and handle them in larger chunks, 
  10108.  
  10109.      Send the output to a window to display it, 
  10110.  
  10111.      Place the output in a clipboard, or 
  10112.  
  10113.      Some combination of these. 
  10114.  
  10115.  With SOMOutCharRoutine, an application program would use code similar to the 
  10116.  following to install the replacement routine: 
  10117.  
  10118.   #include <som.h>
  10119.   #pragma linkage(myCharacterOutputRoutine, system)
  10120.   /* Define a replacement routine: */
  10121.   int SOMLINK myCharacterOutputRoutine (char c)
  10122.   {
  10123.        (Customized code goes here)
  10124.   }
  10125.  
  10126.   /* After the next stmt all output */
  10127.   /* will be sent to the new routine   */
  10128.   SOMOutCharRoutine = myCharacterOutputRoutine;
  10129.  
  10130.  With somSetOutChar, an application program would use code similar to the 
  10131.  following to install the replacement routine: 
  10132.  
  10133.   #include <som.h>
  10134.   static int irOutChar(char c);
  10135.  
  10136.   static int irOutChar(char c)
  10137.   {
  10138.       (Customized code goes here)
  10139.   }
  10140.  
  10141.   main (...)
  10142.   {
  10143.       ...
  10144.   somSetOutChar((somTD_SOMOutCharRoutine *) irOutChar);
  10145.   }
  10146.  
  10147.  
  10148. ΓòÉΓòÉΓòÉ 6.10. Customizing Error Handling ΓòÉΓòÉΓòÉ
  10149.  
  10150. When an error occurs within any of the SOM-supplied methods or functions, an 
  10151. error-handling procedure is invoked. The default error-handling procedure 
  10152. supplied by SOM, pointed to by the global variable SOMError, has the following 
  10153. signature: 
  10154.  
  10155. void  (*SOMError) (int errorCode ,  string fileName,  int lineNum ); 
  10156.  
  10157. The default error-handling procedure inspects the  errorCode  argument and 
  10158. takes appropriate action, depending on the last decimal digit of errorCode (see 
  10159. "Exceptions and error handling" in Using SOM Classes in Client Programs for a 
  10160. discussion of error classifications). In the default error handler, fatal 
  10161. errors terminate the current process. The remaining two arguments (fileName and 
  10162. lineNum), which indicate the name of the file and the line number within the 
  10163. file where the error occurred, are used to produce an error message. 
  10164.  
  10165. An application programmer might wish to replace the default error handler with 
  10166. a customized error-handling routine to: 
  10167.  
  10168.      Record errors in a way appropriate to the particular application, 
  10169.  
  10170.      Inform the user through the application's user interface, 
  10171.  
  10172.      Attempt application-level recovery by restarting at a known point, or 
  10173.  
  10174.      Shut down the application. 
  10175.  
  10176.  An application program would use code similar to the following to install the 
  10177.  replacement routine: 
  10178.  
  10179.   #include <som.h>
  10180.   /* Define a replacement routine: */
  10181.   void myErrorHandler (int errorCode, string fileName, int lineNum)
  10182.   {
  10183.        (Customized code goes here)
  10184.   }
  10185.   ...
  10186.   /* After the next stmt all errors */
  10187.   /* will be handled by the new routine   */
  10188.   SOMError = myErrorHandler;
  10189.  
  10190.  When any error condition originates within the classes supplied with SOM, SOM 
  10191.  is left in an internally consistent state. If appropriate, an application 
  10192.  program can trap errors with a customized error-handling procedure and then 
  10193.  resume with other processing. Application programmers should be aware, 
  10194.  however, that all methods within the SOM run-time library behave atomically. 
  10195.  That is, they either succeed or fail; but if they fail, partial effects are 
  10196.  undone wherever possible. This is done so that all SOM methods remain usable 
  10197.  and can be re-executed following an error. 
  10198.  
  10199.  
  10200. ΓòÉΓòÉΓòÉ 6.11. Customizing Mutual Exclusion Services (Thread Safety) ΓòÉΓòÉΓòÉ
  10201.  
  10202. The SOM kernel and the other SOMobjects frameworks (DSOM, Persistence, 
  10203. Replication, and so on), have been made thread safe with respect to 
  10204. multi-threaded processes. As used here, "thread safe" means that the SOMobjects 
  10205. run time has been implemented using mutual exclusion semaphores to protect 
  10206. sections of the code which must only be executed by a single thread in a 
  10207. multi-threaded application process at one time. 
  10208.  
  10209. Some operating systems provide native multi-threading (for example, OS/2.) On 
  10210. other operating systems that do not support native multi-threading (such as, 
  10211. AIX 3.2), thread support may be provided as part of particular programming 
  10212. environments (like DCE) or libraries. 
  10213.  
  10214. It is vital that SOM employ the mutex services that are provided by the thread 
  10215. package used by the application. Consequently, SOM provides a mechanism for 
  10216. defining and customizing mutex services. 
  10217.  
  10218. Five mutex service functions are used to implement mutual exclusion in SOM. 
  10219. These functions are called indirectly via the global pointer variables defined 
  10220. below. A somToken parameter (called "sem" below) is used as a generic "handle 
  10221. to refer to a mutex semaphore - usually it is a pointer to a mutex semaphore 
  10222. variable or data structure. The actual representation of the mutex semaphore is 
  10223. hidden by the functions. 
  10224.  
  10225. unsigned long (*SOMCreateMutexSem)(somToken *sem);
  10226.  
  10227.       The referenced function creates a mutex semaphore, whose handle is 
  10228.       returned as an output parameter in the somToken variable identified by 
  10229.  
  10230.              "sem".
  10231.  
  10232.       If the call succeeds, a 0 is returned.  Otherwise, a non-zero error code 
  10233.       is returned. 
  10234.  
  10235.   unsigned long (*SOMRequestMutexSem)(somToken sem);
  10236.  
  10237.       The referenced function requests ownership of the mutex semaphore 
  10238.       identified by the parameter, sem. If the semaphore is not currently owned 
  10239.       by another thread, ownership is assigned to the calling thread. 
  10240.       Otherwise, the calling thread is blocked until the semaphore is released 
  10241.       by the current owner. 
  10242.  
  10243.       Important: If the same thread calls SOMRequestMutexSem multiple times, a 
  10244.       reference count must be kept, so that the semaphore is released only 
  10245.       after the same number of calls to SOMReleaseMutexSem. Some, but not all, 
  10246.       thread packages provide reference counting automatically, via "counting 
  10247.       semaphores." 
  10248.  
  10249.       If the call succeeds, a 0 is returned. Otherwise,  a non-zero error code 
  10250.       is returned. 
  10251.  
  10252.   unsigned long(*SOMReleaseMutexSem)(somToken sem);
  10253.  
  10254.       The referenced function releases ownership of the mutex semaphore 
  10255.       identified by the parameter, sem. 
  10256.  
  10257.       Important: If the same thread calls SOMRequestMutexSem multiple times, a 
  10258.       reference count must be kept, so that the semaphore is released only 
  10259.       after the same number of calls to SOMReleaseMutexSem. Some, but not all, 
  10260.       thread packages provide reference counting automatically, via "counting 
  10261.       semaphores." 
  10262.  
  10263.       If the call succeeds, a 0 is returned.  Otherwise, a non-zero error code 
  10264.       is returned. 
  10265.  
  10266.   unsigned long (*SOMDestroyMutexSem)(somToken sem);
  10267.  
  10268.       The referenced function destroys the a mutex semaphore identified by the 
  10269.       parameter, sem. 
  10270.  
  10271.       If the call succeeds, a 0 is returned. Otherwise, a non-zero error code 
  10272.       is returned. 
  10273.  
  10274.   unsigned long (*SOMGetThreadId)();
  10275.  
  10276.       The referenced function returns a small integer identifier for the 
  10277.       calling thread. The ID cannot be associated with any other thread in the 
  10278.       process. The ID is used as an index for table lookups. 
  10279.  
  10280.       If threads are not supported, the function must return 0. 
  10281.  
  10282.  The actual mutex service function prototypes and global variable declarations 
  10283.  are found in file "somapi.h". 
  10284.  
  10285.  If the underlying operating system supports native multi-threading (currently, 
  10286.  only OS/2), SOM provides appropriate default mutex service function 
  10287.  implementations. On those operating systems that do not support native 
  10288.  multi-threading, the default mutex service functions have null 
  10289.  implementations. 
  10290.  
  10291.  An application may want to use threading services different from those 
  10292.  provided by the underlying operating system (if any); for example, DCE 
  10293.  applications will want to use DCE threads. In that case, the default mutex 
  10294.  service functions can be replaced by application-defined functions. 
  10295.  
  10296.  An application program would use code similar to the following to install the 
  10297.  replacement routines: 
  10298.  
  10299.   #include <som.h>
  10300.   /* Define a replacement routine: */
  10301.   unsigned long myCreateMutexSem (somToken *sem)
  10302.   {
  10303.       (Customized code goes here)
  10304.   }
  10305.   ...
  10306.   SOMCreateMutexSem= myCreateMutexSem;
  10307.  
  10308.  It is important to install custom mutex service functions before any SOM calls 
  10309.  are made. 
  10310.  
  10311.  
  10312. ΓòÉΓòÉΓòÉ 6.12. Customizing Multi-threading Services ΓòÉΓòÉΓòÉ
  10313.  
  10314. Although the SOM kernel and the other SOMobjects frameworks allow applications 
  10315. to be multi-threaded, the kernel and frameworks generally do not require or 
  10316. exploit threads themselves. But there are some exceptions: for example, 
  10317. application servers in DSOM can be configured so that each incoming request is 
  10318. executed on a separate thread. 
  10319.  
  10320. An application may choose to employ "native" multi-threading services provided 
  10321. by the underlying operating system (for example, OS/2). On other operating 
  10322. systems that do not support native multi-threading (such as, AIX 3.2), thread 
  10323. support may be provided as part of particular programming environments (like 
  10324. DCE) or libraries.  SOM provides a mechanism that allows an application to 
  10325. define and customize the multi-threading services used by SOMobjects 
  10326. frameworks. 
  10327.  
  10328. Four thread service functions are defined for use by SOMobjects frameworks. 
  10329. These functions may be called indirectly via the global pointer variables 
  10330. defined below. A somToken parameter (called "thrd" below) is used as a generic 
  10331. "handle" to refer to a thread # usually it is a pointer to a thread id or 
  10332. descriptor. The actual representation of the thread handle is hidden by the 
  10333. functions. 
  10334.  
  10335. typedef void somTD_SOMThreadProc(void * data);
  10336.  
  10337. unsigned long (*SOMStartThread)(somToken *thrd,
  10338.                                 somTD_SOMThreadProc proc,
  10339.                                 void *data,
  10340.                                 unsigned long datasz,
  10341.                                 unsigned long stacksz);
  10342.  
  10343.       The referenced function starts a thread, and returns a thread handle in 
  10344.       the somToken variable identified by "thrd".  The thread executes the 
  10345.       procedure whose address is specified by the  proc parameter; the thread 
  10346.       procedure takes a single void* argument and returns void. The data 
  10347.       parameter passed to SOMStartThread is passed on to the thread procedure; 
  10348.       the size of the data parameter, in bytes, is given by datasz.  A stack of 
  10349.       stacksz bytes will be allocated for the thread. 
  10350.  
  10351.       Note: On OS/2, the thread procedure must be compiled with _Optlink 
  10352.       linkage.) 
  10353.  
  10354.       If the call succeeds, a 0 is returned.  Otherwise, a non-zero error code 
  10355.       is returned. 
  10356.  
  10357.   unsigned long (*SOMEndThread)(void);
  10358.  
  10359.       The referenced function terminates the calling thread. 
  10360.  
  10361.       If the call succeeds, a 0 is returned. Otherwise,  a non-zero error code 
  10362.       is returned. 
  10363.  
  10364.   unsigned long (*SOMKillThread)(somToken thrd);
  10365.  
  10366.       The referenced function terminates the thread identified by the input 
  10367.       parameter thrd. 
  10368.  
  10369.       If the call succeeds, a 0 is returned.  Otherwise, a non-zero error code 
  10370.       is returned. 
  10371.  
  10372.   unsigned long (*SOMGetThreadHandle)(somToken * thrd);
  10373.  
  10374.       The referenced function returns a handle that can be used to identify the 
  10375.       calling thread. The handle is returned in the somToken variable pointed 
  10376.       to by thrd. 
  10377.  
  10378.       If the call succeeds, a 0 is returned. Otherwise, a non-zero error code 
  10379.       is returned. 
  10380.  
  10381.  The actual mutex service function prototypes and global variable declarations 
  10382.  are found in file "somthrd.h". 
  10383.  
  10384.  If the underlying operating system supports native multi-threading (currently, 
  10385.  only OS/2), SOM provides appropriate default multi-threading service function 
  10386.  implementations. On those operating systems that do not support native 
  10387.  multi-threading, the default multi-threading service functions have null 
  10388.  implementations. 
  10389.  
  10390.  An application may want to use threading services different from those 
  10391.  provided by the underlying operating system (if any); for example, DCE 
  10392.  applications will want to use DCE threads. In that case, the default 
  10393.  multi-threading service functions can be replaced by application#defined 
  10394.  functions. 
  10395.  
  10396.  An application program would use code similar to the following to install the 
  10397.  replacement routines: 
  10398.  
  10399.   #include <somthrd.h>
  10400.   /* Define a replacement routine: */
  10401.   unsigned long myStartThread (somToken *thrd,
  10402.                                somTD_SOMThreadProc proc,
  10403.                                void *data,
  10404.                                unsigned long datasz,
  10405.                                unsigned long stacksz)
  10406.   {
  10407.       (Customized code goes here)
  10408.   }
  10409.   ...
  10410.   SOMStartThread =myStartThread;
  10411.  
  10412.  It is important to install custom multi-threading service functions before any 
  10413.  SOM calls are made. 
  10414.  
  10415.  
  10416. ΓòÉΓòÉΓòÉ 7. Distributed SOM (DSOM) ΓòÉΓòÉΓòÉ
  10417.  
  10418. Note:  The SOMobject Base Toolkit provides the capability for implementing 
  10419.        Workstation Distributed System Object Module (DSOM) (distribution among 
  10420.        processes on a single machine). Implementing an application that is 
  10421.        distributed across a network of machines requires Workgroup DSOM, which 
  10422.        is available only in the full-capability SOMobjects Developer Toolkit. 
  10423.  
  10424.  The following subjects are discussed in this section: 
  10425.  
  10426.      A Simple DSOM Example 
  10427.      Basic Client Programming 
  10428.      Basic Server Programming 
  10429.      Implementing Classes 
  10430.      Configuring DSOM Applications 
  10431.      Running DSOM Applications 
  10432.      DSOM as a CORBA-compliant Object Request Broker 
  10433.      Advanced Topics 
  10434.      Error Reporting and Troubleshooting 
  10435.      Limitations 
  10436.  
  10437.  
  10438. ΓòÉΓòÉΓòÉ 7.1. What is Distributed SOM? ΓòÉΓòÉΓòÉ
  10439.  
  10440. Whereas the power of SOM technology comes from the fact that SOM insulates the 
  10441. client of an object from the object's implementation, the power of DSOM lies in 
  10442. the fact that DSOM insulates the client of an object from the object's 
  10443. location. 
  10444.  
  10445. Distributed SOM (or DSOM) provides a framework that allows application programs 
  10446. to access objects across address spaces. That is, application programs can 
  10447. access objects in other processes, even on different machines. Both the 
  10448. location and implementation of an object are hidden from a client, and the 
  10449. client accesses the object (by way of method calls) in the same manner 
  10450. regardless of its location. 
  10451.  
  10452. DSOM currently supports two types of distribution: 
  10453.  
  10454.    1. distribution among processes on the same machine (referred to as 
  10455.       Workstation DSOM) 
  10456.  
  10457.    2. and distribution among a network of machines (referred to as Workgroup 
  10458.       DSOM). 
  10459.  DSOM runs on the AIX (Release 3.2.5 and above) and OS/2 (Release 2.0 and 
  10460.  above) operating systems. A Workstation DSOM application can run on a machine 
  10461.  in either environment using core capabilities of the SOMobjects system. Under 
  10462.  the full capability SOMobjects Developer Toolkit, Workgroup DSOM supports 
  10463.  distribution across local area networks comprised of both OS/2 and AIX 
  10464.  systems. Future releases of DSOM may support large, enterprise-wide networks. 
  10465.  
  10466.  Support for TCP/IP and NewWare IPX/SPX is provided on AIX, OS/2, and Windows. 
  10467.  NetBIOS support is provided for OS/2 and Windows. DSOM communications is 
  10468.  extensible in that an application can provide its own transport (see Appendix 
  10469.  C of the SOMobjects Base Toolkit Users Guide). 
  10470.  
  10471.  DSOM can be viewed in two ways: 
  10472.  
  10473.    1. As a System Object Model extension that allows a program to invoke 
  10474.       methods on SOM objects in other processes. 
  10475.  
  10476.    2. As an Object Request Broker (ORB); that is, a standardized "transport" 
  10477.       for distributed object interaction. In this respect, DSOM complies with 
  10478.       the Common Object Request Broker Architecture (CORBA) specification, 
  10479.       published by the Object Management Group (OMG) and x/Open. 
  10480.  
  10481.  This chapter describes DSOM from both perspectives. 
  10482.  
  10483.  
  10484. ΓòÉΓòÉΓòÉ 7.2. DSOM features ΓòÉΓòÉΓòÉ
  10485.  
  10486. Here is a quick summary of some of DSOM's more important features: 
  10487.  
  10488.      Uses the standard SOM Compiler, Interface Repository, language bindings, 
  10489.       and class libraries.  Thus, DSOM provides a growth path for 
  10490.       non-distributed SOM applications. 
  10491.  
  10492.      Allows an application program to access a mix of local and remote 
  10493.       objects. The fact that an object is remote is transparent to the program. 
  10494.  
  10495.      Provides run-time services for creating, destroying, identifying, 
  10496.       locating, and dispatching methods on remote objects. These services can 
  10497.       be overridden or augmented to suit the application. 
  10498.  
  10499.      Uses existing interprocess communication (IPC) facilities for Workstation 
  10500.       communication, and common local area network (LAN) transport facilities 
  10501.       for Workgroup communications. Support for TCP/IP, Netware IPX/SPX, and 
  10502.       NetBios is provided. DSOM communications is extensible in that an 
  10503.       application can provide its own transport. 
  10504.  
  10505.      Provides support for writing multi-threaded servers and event-driven 
  10506.       programs. 
  10507.  
  10508.      Provides a default object server program, which can be easily used to 
  10509.       create SOM objects and make those objects accessible to one or more 
  10510.       client programs. If the default server program is used, SOM class 
  10511.       libraries are loaded upon demand, so no server programming or compiling 
  10512.       is necessary. 
  10513.  
  10514.      Complies with the CORBA 1.1 specification, which is important for 
  10515.       application portability. 
  10516.  
  10517.  
  10518. ΓòÉΓòÉΓòÉ 7.3. When to use DSOM ΓòÉΓòÉΓòÉ
  10519.  
  10520. DSOM should be used for those applications that require sharing of objects 
  10521. among multiple programs. The object actually exists in only one process (this 
  10522. process is known as the object's server); the other processes (known as 
  10523. clients) access the object through remote method invocations, made transparent 
  10524. by DSOM. 
  10525.  
  10526. DSOM should also be used for applications that require objects to be isolated 
  10527. from the main program. This is usually done in cases where reliability is a 
  10528. concern, either to protect the object from failures in other parts of the 
  10529. application, or to protect the application from an object. 
  10530.  
  10531. Some distributed applications may have special performance, reliability,or 
  10532. cooperative processing requirements, to which the SOM Replication framework is 
  10533. better suited. The Replication framework is oriented toward "groupware" 
  10534. (multi-party cooperative processing) applications, and has facilities for fault 
  10535. tolerance and recovery. The Replication framework is distinct from DSOM in that 
  10536. it maintains a complete replica of an object in each participant's address 
  10537. space, while DSOM establishes remote connections to shared objects. The 
  10538. Replication Framework is available only in the full-capability SOM objects 
  10539. Developer Toolkit. 
  10540.  
  10541.  
  10542. ΓòÉΓòÉΓòÉ 7.4. Chapter Outline ΓòÉΓòÉΓòÉ
  10543.  
  10544. Briefly, this section covers the following subjects: 
  10545.  
  10546.      Tutorial example 
  10547.      Programming DSOM applications 
  10548.      Configuring DSOM applications 
  10549.      Running DSOM applications 
  10550.      DSOM and CORBA 
  10551.      Advanced topics 
  10552.      Error reporting and troubleshooting 
  10553.  
  10554.  
  10555. ΓòÉΓòÉΓòÉ 7.5. Tutorial example ΓòÉΓòÉΓòÉ
  10556.  
  10557. First, a complete example shows how an existing SOM class implementation (a 
  10558. "stack") can be used with DSOM to create a distributed "Stack" application. 
  10559. Using the "Stack" example as a backdrop, the basic DSOM interfaces are 
  10560. introduced. 
  10561.  
  10562.  
  10563. ΓòÉΓòÉΓòÉ 7.6. Programming DSOM applications ΓòÉΓòÉΓòÉ
  10564.  
  10565. All DSOM applications involve three kinds of programming: 
  10566.  
  10567.      Client programming:  writing code that uses objects; 
  10568.  
  10569.      Server programming:  writing code that implements and manages objects. 
  10570.  
  10571.      Implementing classes:  writing code that implements objects. 
  10572.  
  10573.  Three sections ("Basic Client Programming", "Basic Server Programming", and 
  10574.  Implementing Classes") describe how to create DSOM applications from these 
  10575.  three points of view. In turn, the structure and services of the relevant DSOM 
  10576.  run-time environment are explained. 
  10577.  
  10578.  Note:  The three sections are presented in the order above to aid in their 
  10579.  explanation. However, the actual programming tasks are likely to be performed 
  10580.  in the opposite order. 
  10581.  
  10582.  Additional examples are provided in these sections to illustrate DSOM 
  10583.  services. 
  10584.  
  10585.  
  10586. ΓòÉΓòÉΓòÉ 7.7. Configuring DSOM applications ΓòÉΓòÉΓòÉ
  10587.  
  10588. The section "Configuring DSOM Applications" explains what is necessary to set 
  10589. up a DSOM application, once the application has been built. 
  10590.  
  10591.  
  10592. ΓòÉΓòÉΓòÉ 7.8. Running DSOM applications ΓòÉΓòÉΓòÉ
  10593.  
  10594. The section "Running DSOM Applications" explains what is necessary to run a 
  10595. DSOM application, once it has been built and configured. 
  10596.  
  10597.  
  10598. ΓòÉΓòÉΓòÉ 7.9. DSOM and CORBA ΓòÉΓòÉΓòÉ
  10599.  
  10600. Those readers interested in using DSOM as a CORBA-compliant ORB should read the 
  10601. section entitled "DSOM as a CORBA compliant Object Broker." That section 
  10602. answers the question: How are CORBA concepts implemented in DSOM? 
  10603.  
  10604.  
  10605. ΓòÉΓòÉΓòÉ 7.10. Advanced topics ΓòÉΓòÉΓòÉ
  10606.  
  10607. The section on "Advanced Topics" covers the following: 
  10608.  
  10609.    1. "Peer versus client/server processes" demonstrates how peer-to-peer 
  10610.       object interactions are supported in DSOM. 
  10611.  
  10612.    2. "Dynamic Invocation Interface" details DSOM support for the CORBA dynamic 
  10613.       invocation interface to dynamically build and invoke methods on remote 
  10614.       objects. 
  10615.  
  10616.    3. "Creating user-supplied proxy classes" describes how to override proxy 
  10617.       generation by the DSOM run time and, instead, install a proxy object 
  10618.       supplied by the user. 
  10619.  
  10620.    4. "Customizing the default base proxy class"discusses how the 
  10621.       SOMDClientProxy class can be subclassed to define a customized base class 
  10622.       that DSOM will use during dynamic proxy-class generation. 
  10623.  
  10624.    5. "Sockets class" describes how DSOM uses Sockets subclasses. 
  10625.  
  10626.  
  10627. ΓòÉΓòÉΓòÉ 7.11. Error reporting and troubleshooting ΓòÉΓòÉΓòÉ
  10628.  
  10629. The section on "Error Reporting and Troubleshooting" discusses facilities to 
  10630. aid in problem diagnosis. 
  10631.  
  10632.  
  10633. ΓòÉΓòÉΓòÉ 7.12. A Simple DSOM Example ΓòÉΓòÉΓòÉ
  10634.  
  10635. A sample "Stack" application is presented in this section as a tutorial 
  10636. introduction to DSOM. It demonstrates that, for simple examples like a "Stack", 
  10637. after very little work, the class can be used to implement distributed objects 
  10638. that are accessed remotely. The example first presents the "Stack" application 
  10639. components and the steps that the implementer must perform before the 
  10640. application can be run, and then describes the run time activity that results 
  10641. from executing the application. This run-time scenario introduces several of 
  10642. the key architectural components of the DSOM run-time environment. 
  10643.  
  10644. The source code for this example is provided with the DSOM samples in the 
  10645. SOMobjects Developer Toolkit. 
  10646.  
  10647.  
  10648. ΓòÉΓòÉΓòÉ 7.12.1. The "Stack" interface ΓòÉΓòÉΓòÉ
  10649.  
  10650. The example starts with the assumption that the class implementer has 
  10651. successfully built a SOM class library DLL, called "stack.dll", in the manner 
  10652. described in Section 5.6, "Creating a SOM Class Library," of Chapter 5, 
  10653. "Implementing Classes in SOM." The DLL implements the following IDL interface. 
  10654.  
  10655. #include <somobj.idl>
  10656.  
  10657. interface Stack: SOMObject
  10658. {
  10659.     const long stackSize = 10;
  10660.     exception STACK_OVERFLOW{};
  10661.     exception STACK_UNDERFLOW{};
  10662.     boolean full();
  10663.     boolean empty();
  10664.     long top() raises(STACK_UNDERFLOW);
  10665.     long pop() raises(STACK_UNDERFLOW);
  10666.     void push(in long element) raises(STACK_OVERFLOW);
  10667.  
  10668.     #ifdef __SOMIDL__
  10669.     implementation
  10670.     {
  10671.       releaseorder: full, empty, top, pop, push;
  10672.       somDefaultInit: override;
  10673.       long stackTop;                  // top of stack index
  10674.       long stackValues[stackSize];    // stack elements
  10675.       dllname = "stack.dll";
  10676.     };
  10677.     #endif
  10678. };
  10679.  
  10680. This DLL could have been built without the knowledge that it would ever be 
  10681. accessed remotely (that is, built following the procedures in Chapter 5). Note, 
  10682. however, that some DLLs may require changes in the way their classes pass 
  10683. arguments and manage memory, in order to be used by remote clients (see the 
  10684. topic "Implementation Constraints" in section 6.5, "Implementing Classes"). 
  10685.  
  10686.  
  10687. ΓòÉΓòÉΓòÉ 7.12.2. The "Stack" class implementation ΓòÉΓòÉΓòÉ
  10688.  
  10689. #define Stack_Class_Source
  10690. #include <stack.ih>
  10691.  
  10692. SOM_Scope boolean  SOMLINK full(Stack somSelf, Environment *ev)
  10693. {
  10694.     StackData *somThis = StackGetData(somSelf);
  10695.     StackMethodDebug("Stack","full");
  10696.  
  10697.     /* Return TRUE if stack is full. */
  10698.     return (_stackTop == stackSize);
  10699. }
  10700.  
  10701. SOM_Scope boolean  SOMLINK empty(Stack somSelf, Environment *ev)
  10702. {
  10703.     StackData *somThis = StackGetData(somSelf);
  10704.     StackMethodDebug("Stack","empty");
  10705.  
  10706.     /* Return TRUE if stack is empty.*/
  10707.     return (_stackTop == 0);
  10708. }
  10709.  
  10710. SOM_Scope long  SOMLINK top(Stack somSelf, Environment *ev)
  10711. {
  10712.     StackData *somThis = StackGetData(somSelf);
  10713.     StackMethodDebug("Stack","top");
  10714.  
  10715.     if (_stackTop > 0)
  10716.     {
  10717.        /* Return top element in stack without removing it from
  10718.         * the stack.
  10719.         */
  10720.        return (_stackValues[_stackTop-1]);
  10721.     }
  10722.     else
  10723.     {
  10724.        somSetException(ev, USER_EXCEPTION,
  10725.                        ex_STACK_UNDERFLOW, NULL);
  10726.        return (-1L);
  10727.     }
  10728. }
  10729.  
  10730. SOM_Scope long  SOMLINK pop(Stack somSelf, Environment *ev)
  10731. {
  10732.     StackData *somThis = StackGetData(somSelf);
  10733.     StackMethodDebug("Stack","pop");
  10734.  
  10735.     if (_stackTop > 0)
  10736.     {
  10737.        /* Return top element in stack and remove it from the
  10738.         * stack.
  10739.         */
  10740.        _stackTop--;
  10741.        return (_stackValues[_stackTop]);
  10742.     }
  10743.     else
  10744.     {
  10745.        somSetException(ev, USER_EXCEPTION,
  10746.                        ex_STACK_UNDERFLOW, NULL);
  10747.        return (-1L);
  10748.     }
  10749. }
  10750.  
  10751. SOM_Scope void  SOMLINK push(Stack somSelf,
  10752.                              Environment *ev, long el)
  10753. {
  10754.     StackData *somThis = StackGetData(somSelf);
  10755.     StackMethodDebug("Stack","push");
  10756.  
  10757.     if (_stackTop < stackSize)
  10758.     {
  10759.       /* Add element to top of the stack. */
  10760.       _stackValues[_stackTop] = el;
  10761.       _stackTop++;
  10762.     }
  10763.     else
  10764.     {
  10765.        somSetException(ev, USER_EXCEPTION,
  10766.                        ex_STACK_OVERFLOW, NULL);
  10767.     }
  10768. }
  10769.  
  10770. SOM_Scope void  SOMLINK somDefaultInit(Stack somSelf,
  10771.                                        somInitCtrl* ctrl)
  10772. {
  10773.     StackData *somThis;
  10774.     somInitCtrl globalCtrl;
  10775.     somBooleanVector myMask;
  10776.     StackMethodDebug("Stack","somDefaultInit");
  10777.     Stack_BeginInitializer_somDefaultInit;
  10778.  
  10779.     Stack_Init_SOMObject_somDefaultInit(somSelf, ctrl);
  10780.  
  10781.     /* stackTop is index into stackValues for next pushed
  10782.      * stack element.
  10783.      * stackValues[0..(stackSize-1)] holds stack elements.
  10784.      */
  10785.     _stackTop = 0;
  10786. }
  10787.  
  10788.  
  10789. ΓòÉΓòÉΓòÉ 7.12.3. Client program using a local stack ΓòÉΓòÉΓòÉ
  10790.  
  10791. A simple client program written to use a local "Stack" object is displayed 
  10792. below. This C program is shown so that the differences between a local and 
  10793. remote client program can be highlighted. 
  10794.  
  10795. #include <stack.h>
  10796.  
  10797. boolean OperationOK(Environment *ev);
  10798.  
  10799. int main(int argc, char *argv[])
  10800. {
  10801.   Environment ev;
  10802.   Stack stk;
  10803.   long num = 100;
  10804.  
  10805.   SOM_InitEnvironment(&ev);
  10806.  
  10807.   /* The StackNewClass invocation is optional and unnecessary
  10808.    * in the client program when the class object is created in
  10809.    * the SOMInitModule function that is invoked during DLL
  10810.    * initialization.
  10811.    */
  10812.   StackNewClass(Stack_MajorVersion, Stack_MinorVersion);
  10813.   stk = StackNew();
  10814.  
  10815.   /* Verify successful object creation */
  10816.   if ( stk != NULL )
  10817.   {
  10818.      while ( !_full(stk, &ev) )
  10819.      {
  10820.         _push(stk, &ev, num);
  10821.         somPrintf("Top: %d\n", _top(stk, &ev));
  10822.         num += 100;
  10823.      }
  10824.  
  10825.      /* Test stack overflow exception */
  10826.      _push(stk, &ev, num);
  10827.      OperationOK(&ev);
  10828.  
  10829.      while ( !_empty(stk, &ev) )
  10830.      {
  10831.         somPrintf("Pop: %d\n", _pop(stk, &ev));
  10832.      }
  10833.  
  10834.      /* Test stack underflow exception */
  10835.      somPrintf("Top Underflow: %d\n", _top(stk, &ev));
  10836.      OperationOK(&ev);
  10837.      somPrintf("Pop Underflow: %d\n", _pop(stk, &ev));
  10838.      OperationOK(&ev);
  10839.  
  10840.      _push(stk, &ev, -10000);
  10841.      somPrintf("Top: %d\n", _top(stk, &ev));
  10842.      somPrintf("Pop: %d\n", _top(stk, &ev));
  10843.  
  10844.      _somFree(stk);
  10845.   }
  10846.  
  10847.   SOM_UninitEnvironment(&ev);
  10848.  
  10849.   return(0);
  10850. }
  10851.  
  10852. boolean OperationOK(Environment *ev)
  10853. {
  10854.    char *exID;
  10855.  
  10856.    switch (ev->_major)
  10857.    {
  10858.      case SYSTEM_EXCEPTION:
  10859.        exID = somExceptionId(ev);
  10860.        somPrintf("System exception: %s\n", exID);
  10861.        somdExceptionFree(ev);
  10862.        return (FALSE);
  10863.  
  10864.      case USER_EXCEPTION:
  10865.        exID = somExceptionId(ev);
  10866.        somPrintf("User exception: %s\n", exID);
  10867.        somdExceptionFree(ev);
  10868.        return (FALSE);
  10869.  
  10870.      case NO_EXCEPTION:
  10871.        return (TRUE);
  10872.  
  10873.      default:
  10874.        somPrintf("Invalid exception type in Environment.\n");
  10875.        somdExceptionFree(ev);
  10876.        return (FALSE);
  10877.    }
  10878. }
  10879.  
  10880.  
  10881. ΓòÉΓòÉΓòÉ 7.12.4. Client program using a remote stack ΓòÉΓòÉΓòÉ
  10882.  
  10883. The preceding program has been rewritten below showing how DSOM can be used to 
  10884. create and access a "Stack" object somewhere in the system. The exact location 
  10885. of the object does not matter to the application; it just wants a "Stack" 
  10886. object. Note that the stack operations of the two programs are identical. The 
  10887. main differences lie in stack creation and destruction, as highlighted below. 
  10888. (Also see "Memory management" later for more information on allocating and 
  10889. freeing memory.) 
  10890.  
  10891. #include <somd.h>
  10892. #include <stack.h>
  10893.  
  10894. int main(int argc, char *argv])
  10895. {
  10896.   Environment ev;
  10897.   Stack stk;
  10898.   long num = 100;
  10899.  
  10900.   SOM_InitEnvironment(&ev);
  10901.   SOMD_Init(&ev);
  10902.  
  10903.   /* The StackNewClass invocation is optional and unnecessary
  10904.    * in the client program when the class object is created in
  10905.    * the SOMInitModule function that is invoked during DLL
  10906.    * initialization.
  10907.    */
  10908.   StackNewClass (Stack_MajorVersion, Stack_MinorVersion);
  10909.   stk = _somdNewObject(SOMD_ObjectMgr, &ev, "Stack", "");
  10910.  
  10911.   /* Verify successful object creation */
  10912.   if ( OperationOK(&ev) )
  10913.   {
  10914.      while ( !_full(stk, &ev) )
  10915.      {
  10916.         _push(stk, &ev, num);
  10917.         somPrintf("Top: %d\n", _top(stk, &ev));
  10918.         num += 100;
  10919.      }
  10920.  
  10921.      /* Test stack overflow exception */
  10922.      _push(stk, &ev, num);
  10923.      OperationOK(&ev);
  10924.  
  10925.      while ( !_empty(stk, &ev) )
  10926.      {
  10927.         somPrintf("Pop: %d\n", _pop(stk, &ev));
  10928.      }
  10929.  
  10930.      /* Test stack underflow exception */
  10931.      somPrintf("Top Underflow: %d\n", _top(stk, &ev));
  10932.      OperationOK(&ev);
  10933.      somPrintf("Pop Underflow: %d\n", _pop(stk, &ev));
  10934.      OperationOK(&ev);
  10935.  
  10936.      _push(stk, &ev, -10000);
  10937.      somPrintf("Top: %d\n", _top(stk, &ev));
  10938.      somPrintf("Pop: %d\n", _top(stk, &ev));
  10939.  
  10940.      _somdDestroyObject(SOMD_ObjectMgr, &ev, stk);
  10941.  
  10942.      if ( OperationOK(&ev) )
  10943.      {
  10944.         somPrintf("Stack test successfully completed.\n");
  10945.      }
  10946.   }
  10947.   SOMD_Uninit(&ev);
  10948.   SOM_UninitEnvironment(&ev);
  10949.  
  10950.   return(0);
  10951. }
  10952.  
  10953. boolean OperationOK(Environment *ev)
  10954. {
  10955.    char *exID;
  10956.  
  10957.    switch (ev->_major)
  10958.    {
  10959.      case SYSTEM_EXCEPTION:
  10960.        exID = somExceptionId(ev);
  10961.        somPrintf("System exception: %s\n", exID);
  10962.        somdExceptionFree(ev);
  10963.        return (FALSE);
  10964.  
  10965.      case USER_EXCEPTION:
  10966.        exID = somExceptionId(ev);
  10967.        somPrintf("User exception: %s\n", exID);
  10968.        somdExceptionFree(ev);
  10969.        return (FALSE);
  10970.  
  10971.      case NO_EXCEPTION:
  10972.        return (TRUE);
  10973.  
  10974.      default:
  10975.        somPrintf("Invalid exception type in Environment.\n");
  10976.        somdExceptionFree(ev);
  10977.        return (FALSE);
  10978.    }
  10979. }
  10980.  
  10981. Let's step through the differences. 
  10982.  
  10983. First, every DSOM program must include the file <somd.h> (when using C ++, 
  10984. <somd.xh>). This file defines constants, global variables, and run-time 
  10985. interfaces used by DSOM. Usually, this file is sufficient to establish all 
  10986. necessary DSOM definitions. 
  10987.  
  10988. Next, DSOM requires its own initialization call. 
  10989.  
  10990.         SOMD_Init(&ev);
  10991.  
  10992. The call to SOMD_Init initializes the DSOM run-time environment SOMD_Init must 
  10993. be called before any DSOM run-time calls are made. A side effect of calling 
  10994. SOMD_Init is that a run-time object, called the DSOM Object Manager, is 
  10995. created, and a pointer to it is stored in the global variable, SOMD_ObjectMgr, 
  10996. for programming convenience. The DSOM Object Manager provides basic run-time 
  10997. support for clients to find, create, destroy, and identify objects. The Object 
  10998. Manager is discussed in detail in the section entitled "Basic Client 
  10999. Programming." 
  11000.  
  11001. Next, the local stack creation statement, 
  11002.  
  11003.         stk = StackNew();
  11004. was replaced by 
  11005.  
  11006.  
  11007.         stk = _somdNewObject(SOMD_ObjectMgr, &ev, "Stack", "");
  11008.  
  11009. The call to somdNewObject asks the DSOM Object Manager (SOMD_ObjectMgr) to 
  11010. create a "Stack" object, wherever it can find an implementation of "Stack". 
  11011. (There are other methods with which one can request specific servers.) If no 
  11012. object could be created, NULL is returned, and an exception is raised. 
  11013. Otherwise, the object returned is a "Stack" proxy. 
  11014.  
  11015. Note:  On AIX, the following call may be needed before the somdNewObject call, 
  11016.        if the "Stack" class implementation has been linked directly with the 
  11017.        program executable (vs. using a dynamic link library, or DLL). This call 
  11018.        will properly initialize the class for use by DSOM (this initialization 
  11019.        is done in SOMInitModulefor DLLs):
  11020.  
  11021.              StackNewClass(Stack_MajorVersion, Stack_MinorVersion);
  11022.  
  11023.  A proxy is an object that is a local representative for a remote target 
  11024.  object. A proxy inherits the target object's interface, so it responds to the 
  11025.  same methods. Operations invoked on the proxy are not executed locally, but 
  11026.  are forwarded to the "real" target object for execution. The client program 
  11027.  always has a proxy for each remote target object on which it operates. 
  11028.  
  11029.  From this point on, the client program treats the "Stack" proxy exactly as it 
  11030.  would treat a local "Stack". The "Stack" proxy takes responsibility for 
  11031.  forwarding requests to, and yielding results from, the remote "Stack". For 
  11032.  example, 
  11033.  
  11034.           _push(stk,&ev,num);
  11035.  
  11036.  causes a message representing the method call to be sent to the server process 
  11037.  containing the remote object. The DSOM run-time in the server process decodes 
  11038.  the message and invokes the method on the target object. The result (in this 
  11039.  case, just an indication of completion) is then returned to the client process 
  11040.  in a message. The DSOM run time in the client process decodes the result 
  11041.  message and returns any result data to the caller. 
  11042.  
  11043.  At the end of the original client program, the local "Stack" was destroyed by 
  11044.  the statement, 
  11045.  
  11046.           _somFree(stk);
  11047.  
  11048.  whereas, in the client program above, the "Stack" proxy and the remote "Stack" 
  11049.  are destroyed by the statement, 
  11050.  
  11051.           _somdDestroyObject(SOMD_ObjectMgr, &ev, stk);
  11052.  
  11053.  If the client only wants to release its use of the remote object (freeing the 
  11054.  proxy) without destroying the remote object, it can call the somdReleaseObject 
  11055.  method instead of somdDestroyObject. 
  11056.  
  11057.  Finally, the client must shut down DSOM, so that any operating system 
  11058.  resources acquired by DSOM for communications or process management can be 
  11059.  returned: 
  11060.  
  11061.           SOMD_Uninit(&ev);
  11062.  This call must be made at the end of every DSOM program. 
  11063.  
  11064.  
  11065. ΓòÉΓòÉΓòÉ 7.12.4.1. Using specific servers ΓòÉΓòÉΓòÉ
  11066.  
  11067. In DSOM, the process that manages a target object is called the object's 
  11068. server. Servers are implemented as programs that use SOM classes.  Server 
  11069. implementations are registered with DSOM in an Implementation Repository. The 
  11070. Implementation Repository is a database queried by clients in order to find 
  11071. desired servers, and queried by DSOM in order to activate those servers upon 
  11072. demand. 
  11073.  
  11074. The example above placed no constraints on the DSOM Object Manager as to where 
  11075. the remote "Stack" object should be created. The somdNewObject call creates a 
  11076. remote object of a specified class in an arbitrary server that implements that 
  11077. class. However, the DSOM Object Manager provides methods for finding specific 
  11078. servers. 
  11079.  
  11080. For example, the client program above can be modified slightly to find a 
  11081. specific server named "StackServer", which has already been registered in 
  11082. DSOM's Implementation Repository.  (Note that the programmer knew or discovered 
  11083. that the "StackServer" server implementation supports the "Stack" class.)  The 
  11084. highlighted lines below show the changes that were made: 
  11085.  
  11086. #include <somd.h>
  11087. #include <stack.h>
  11088.  
  11089. int main(int argc, char *argv[]) {
  11090.         Stack stk;
  11091.         Environment e;
  11092.         SOMDServer server;
  11093.  
  11094.         SOM_InitEnvironment(&e);
  11095.         SOMD_Init(&e);
  11096.  
  11097.         server =
  11098.           _somdFindServerByName(SOMD_ObjectMgr, &e, "StackServer");
  11099.         stk = _somdCreateObj(server, &e, "Stack", "");
  11100.  
  11101.         _push(stk,&e,100);
  11102.         _push(stk,&e,200);
  11103.         _pop(stk,&e);
  11104.         if (!_empty(stk,&e)) somPrintf("Top: %d\n", _top(stk,&e));
  11105.  
  11106.         _somdDeleteObj(server, &e, stk);
  11107.         _somdReleaseObject(SOMD_ObjectMgr, &e, stk);
  11108.         _somdReleaseObject(SOMD_ObjectMgr, &e, server);
  11109.         SOMD_Uninit(&e);
  11110.         SOM_UninitEnvironment(&e);
  11111.  
  11112.         return(0);
  11113. }
  11114.  
  11115. This version of the program replaces the somdNewObject operation with calls to 
  11116. somdFindServerByName and somdCreateObj. The somdFindServerByName method 
  11117. consults the Implementation Repository to find the DSOM server implementation 
  11118. whose name is "StackServer", and creates a server proxy, which provides a 
  11119. connection to that server. Every DSOM server process has a server object that 
  11120. defines methods to assist in the creation and management of objects in that 
  11121. server. Server objects must be instances of SOMDServer or one of its 
  11122. subclasses. The somdFindServerByName returns a proxy to the SOMDServer object 
  11123. in the named server. 
  11124.  
  11125. Once the client has the server proxy, it can create and destroy objects in that 
  11126. server. The somdCreateObj call creates an object of the class "Stack" in the 
  11127. server named "StackServer". 
  11128.  
  11129. To free the remote "Stack" object, the example shows a somdDeleteObj request on 
  11130. the stack object's server. Next, somdReleaseObject requests are made on the 
  11131. DSOM Object Manager, to free the stack proxy and the server proxy in the 
  11132. client. (Note that these three calls are equivalent to the somdDestroyObject 
  11133. call in the previous example.) 
  11134.  
  11135.  
  11136. ΓòÉΓòÉΓòÉ 7.12.5. A note on finding existing objects ΓòÉΓòÉΓòÉ
  11137.  
  11138. The two examples above show how clients can create a remote, transient object 
  11139. for their exclusive use. Clients may want to find and use objects that already 
  11140. exist. In that case, the calls to somdNewObject or somdCreateObj would be 
  11141. replaced with other "lookup" calls on some directory object that would take an 
  11142. object name or identifier and return a proxy to the remote object. 
  11143.  
  11144. Such a directory object could be implemented by the application as a persistent 
  11145. SOM object, using DSOM to share it among processes. 
  11146.  
  11147. The basic mechanisms that DSOM provides for naming and locating objects will be 
  11148. discussed in section  "Basic Client Programming." 
  11149.  
  11150.  
  11151. ΓòÉΓòÉΓòÉ 7.12.6. "Stack" server implementation ΓòÉΓòÉΓòÉ
  11152.  
  11153. A server consists of three parts. First, a "main" program, when run, provides 
  11154. an address space for the objects it manages, and one or more process "threads" 
  11155. that can execute method calls. (Windows and AIX currently do not have 
  11156. multi-thread support, while OS/2 and AIX 4.1 do.) Second, a server object, 
  11157. derived from the SOMDServer class, provides methods used to manage objects in 
  11158. the server process. Third, one or more class libraries provide object 
  11159. implementations. Usually these libraries are constructed as dynamically linked 
  11160. libraries (DLLs), so they can be loaded and linked by a server program 
  11161. dynamically. 
  11162.  
  11163. In this simple example, we can use the default DSOM server program, which is 
  11164. already compiled and linked. The default server behaves as a simple server, in 
  11165. that it simply receives and executes requests continuously. The default server 
  11166. creates its server object from the class, SOMDServer. The default server will 
  11167. load any class libraries it needs upon demand. 
  11168.  
  11169. The "Stack" class library, "stack.dll", can be used without modification in the 
  11170. distributed application. This is possible because the "Stack" class is "well 
  11171. formed"; in other words, there are no methods that implicitly assume the client 
  11172. and the object are in the same address space. 
  11173.  
  11174. Thus, by using the default server and the existing class library, a simple 
  11175. "Stack" server can be provided without any additional programming! 
  11176.  
  11177. An application may require more functionality in the server program or the 
  11178. server object than the default implementations provide. A discussion on how to 
  11179. implement server programs and server objects is found later in this chapter, in 
  11180. section 6.4, "Basic Server Programming". 
  11181.  
  11182.  
  11183. ΓòÉΓòÉΓòÉ 7.12.7. Compiling the application ΓòÉΓòÉΓòÉ
  11184.  
  11185. DSOM programs and class libraries are compiled and linked like any other SOM 
  11186. program or library. The header file "somd.h" (or for C++, "somd.xh") should be 
  11187. included in any source program that uses DSOM services. DSOM run-time calls can 
  11188. be resolved by linking with the SOMobjects Toolkit library: "libsomtk.a" on AIX 
  11189. and "somtk.lib" on OS/2 or Windows. (The DSOM DLL(s)  - "somd.dll", for AIX or 
  11190. OS/2, or "somd1.dll" and "somd1.dll" for Windows - will be loaded at run time.) 
  11191. For more information, see "Compiling and linking" in Chapter 3, "Using SOM 
  11192. classes in Client Programs," and the same topic in Chapter 5, "Implementing 
  11193. Classes in SOM." 
  11194.  
  11195.  
  11196. ΓòÉΓòÉΓòÉ 7.12.8. Installing the implementation ΓòÉΓòÉΓòÉ
  11197.  
  11198. Before the application can be run, certain environment variables must be set 
  11199. and the stack class and server implementations must be registered in the SOM 
  11200. Interface Repository and DSOM Implementation Repository. 
  11201.  
  11202.  
  11203. ΓòÉΓòÉΓòÉ 7.12.8.1. Setting environment variables ΓòÉΓòÉΓòÉ
  11204.  
  11205. Several environment variables are used by SOM and DSOM. These variables need to 
  11206. be set before registering the DSOM application in the Interface and 
  11207. Implementation Repositories. 
  11208.  
  11209. For this example, the following environment variables could be set as shown. A 
  11210. full description of the environment variables and how to set them is given in 
  11211. section 6.6, "Configuring DSOM." 
  11212.  
  11213. On AIX (in the syntax of the default shell, /bin/ksh): 
  11214.  
  11215. export HOSTNAME=machine3
  11216. export SOMIR=$SOMBASE/etc/som.ir:/u/myuserid/my.ir
  11217. export SOMDDIR=/u/myuserid/somddir
  11218. export LIBPATH=$LIBPATH:$SOMBASE/lib:/u/myuserid/lib
  11219.  
  11220. On OS/2: 
  11221.  
  11222. set USER=pat
  11223. set HOSTNAME=machine3
  11224. set SOMDDIR=c:\somddir
  11225.  
  11226. rem *** The following variables are set in CONFIG.SYS by
  11227. rem *** the install program on OS/2, assuming "c:\som" is the
  11228. rem *** value of %SOMBASE% supplied by the user.
  11229. set SOMIR=c:\som\etc\som.ir;som.ir
  11230. set LIBPATH=.;c:\som\lib;<previous LIBPATH>
  11231.  
  11232. On Windows: 
  11233.  
  11234. set USER=pat
  11235. set HOSTNAME=machine3
  11236. set SOMDDIR=c:\somddir
  11237. rem *** The following variables are usually set in AUTOEXEC.BAT
  11238. rem *** by the install program on Windows, assuming "c:\som"
  11239. rem *** is the value of %SOMBASE% supplied by the user.
  11240. set SOMIR=c:\som\etc\som.ir:som.ir
  11241. set PATH=.;c:\som\lib;<previous PATH>
  11242.  
  11243. USER identifies the user of a DSOM client application. DSOM sends the USER ID 
  11244. with every remote method call, in case the remote object wishes to perform any 
  11245. access control checking. This is discussed later in the section "Basic Server 
  11246. Programming." (Note that USER is usually set automatically by AIX when a user 
  11247. logs in.) 
  11248.  
  11249. HOSTNAME identifies the name of each machine running DSOM. 
  11250.  
  11251. SOMIR gives a list of files that together constitute the Interface Repository. 
  11252. The IR is used by DSOM to guide the construction and interpretation of request 
  11253. messages. For DSOM, it is preferable to use full pathnames in the list of IR 
  11254. files, since the IR will be shared by several programs that may not all reside 
  11255. in the same directory. 
  11256.  
  11257. SOMDDIR gives the name of a directory used to store DSOM configuration files, 
  11258. including the Implementation Repository. 
  11259.  
  11260. LIBPATH (on AIX and OS/2) or PATH (on Windows) gives a list of directories 
  11261. where DLLs can be found. 
  11262.  
  11263.  
  11264. ΓòÉΓòÉΓòÉ 7.12.8.2. Registering the class in the Interface Repository ΓòÉΓòÉΓòÉ
  11265.  
  11266. Before an object can be accessed remotely by DSOM, it is necessary to register 
  11267. the class's interface and implementation in the Interface Repository (IR). DSOM 
  11268. uses the interface information when transforming local method calls on proxies 
  11269. into request messages transmitted to remote objects. 
  11270.  
  11271. DSOM servers also consult the IR to find the name of the DLL for a dynamically 
  11272. loaded class. The DLL name for the "Stack" class must be specified using the 
  11273. dllname="stack.dll" modifier in the implementation statement of the "Stack" 
  11274. IDL. The Interface Repository is described in detail in Chapter 7, "The 
  11275. Interface Repository Framework." 
  11276.  
  11277. The IDL specification of "Stack" is compiled into the Interface Repository 
  11278. using the following command: 
  11279.  
  11280.         sc -u -sir stack.idl               (on AIX or OS/2)
  11281.         somc -u -sir stack.idl             (on Windows)
  11282.  
  11283. When a class has not been compiled into the Interface Repository, DSOM will 
  11284. generate a run-time error when an attempt is made to invoke a method from that 
  11285. class. The error indicates that the method's descriptor was not found in the 
  11286. IR. 
  11287.  
  11288.  
  11289. ΓòÉΓòÉΓòÉ 7.12.8.3. Registering the server in the Implementation Repository ΓòÉΓòÉΓòÉ
  11290.  
  11291. It is necessary to register a description of a server's implementation in the 
  11292. Implementation Repository. DSOM uses this information to assist clients in 
  11293. finding servers, and in activating server processes upon demand. 
  11294.  
  11295. For this example, where the default server is used, we need only to identify 
  11296. the server's name, and the class that the server implements. This is 
  11297. accomplished using the regimpl utility discussed in section 6.6, "Configuring 
  11298. DSOM Applications". The following commands define a default server, named 
  11299. "StackServer", which supports the Stack class: 
  11300.  
  11301.         regimpl -A -i StackServer
  11302.         regimpl -a -i StackServer -c Stack
  11303.  
  11304.  
  11305. ΓòÉΓòÉΓòÉ 7.12.9. Running the application ΓòÉΓòÉΓòÉ
  11306.  
  11307. This section discusses: 
  11308.  
  11309.      Starting the DSOM daemon 
  11310.      Running the client 
  11311.  
  11312.  Starting the DSOM daemon 
  11313.  
  11314.  Before running a DSOM application, the DSOM daemon, somdd, must be started. 
  11315.  
  11316.      On AIX or OS/2, the daemon can be started manually from the command line, 
  11317.       or it could be started automatically from a start-up script run at boot 
  11318.       time. It may be run in the background with the commands somdd& on AIX and 
  11319.       start somdd on OS/2. (The somdd program requires no parameters. An 
  11320.       optional -q parameter can be used to set "quiet" mode, to suppress 
  11321.       messages.) 
  11322.  
  11323.      On Windows, the daemon can be started with the DSOM Daemon icon in the 
  11324.       SOM icon group or started in Windows from the Run option of the file 
  11325.       menu.  The DSOM Daemon icon will change colors to indicate the daemon is 
  11326.       ready,  after which client and server programs can be started. 
  11327.  
  11328.       The somdd daemon is responsible for establishing a "binding" (that is, a 
  11329.       connection) between a client process and a server.  It will activate the 
  11330.       desired server automatically, if necessary. The server can also be 
  11331.       started manually prior to starting the client program, using the command 
  11332.       dsom start stackServer. 
  11333.  
  11334.  Running the client 
  11335.  
  11336.  Once the DSOM daemon is running, the application may be started. This is 
  11337.  accomplished by running the client program. If the StackServer is not running, 
  11338.  it will be started automatically by the DSOM daemon when the client attempts 
  11339.  to invoke a method on one of its objects. After the client program ends, the 
  11340.  server will continue to run, accepting connections from new clients. To 
  11341.  terminate the server, use the command dsom stop stackServer. 
  11342.  
  11343.  
  11344. ΓòÉΓòÉΓòÉ 7.12.10. "Stack" example run-time scenario ΓòÉΓòÉΓòÉ
  11345.  
  11346. The following scenario steps through the actions taken by the DSOM run time in 
  11347. response to each line of code in the second "Stack" client program presented 
  11348. above. The illustration following the scenario shows the processes, and the 
  11349. objects within them, that participate in these actions. 
  11350.  
  11351.      Initialize an environment for error passing: 
  11352.  
  11353.             SOM_InitEnvironment(&e);
  11354.  
  11355.      Initialize DSOM: 
  11356.  
  11357.             SOMD_Init(&e);
  11358.  
  11359.  This causes the creation of the DSOM Object Manager (with SOMDObjectMgr 
  11360.  interface). The global variable SOMD_ObjectMgr points to this object. 
  11361.  
  11362.      Initialize "Stack" class object: 
  11363.  
  11364.             StackNewClass(Stack_MajorVersion, Stack_MinorVersion);
  11365.  
  11366.      Find the "StackServer" implementation and assign its proxy to the 
  11367.       variable server: 
  11368.  
  11369.             server = _somdFindServerByName(SOMD_ObjectMgr, &e, "StackServer");
  11370.  
  11371.  This causes the creation of the server proxy object in the client process. 
  11372.  Proxy objects are shown as shaded circles. Note that the "real" server object 
  11373.  in the server process is not created at this time. In fact, the server process 
  11374.  has not yet been started. 
  11375.  
  11376.      Ask the server object to create a "Stack" and assign "Stack" proxy to 
  11377.       variable stack. 
  11378.  
  11379.             stk = _somdCreateObj(server, &e, "Stack", "");
  11380.  
  11381.  This causes somdd, the DSOM daemon (which is already running) to activate the 
  11382.  stack server process (by starting the "generic" server program). The stack 
  11383.  server process, upon activation, creates the "real" SOMDServer object in the 
  11384.  server process. The SOMDServer object works with the DSOM run time to create a 
  11385.  local "Stack" object and return a "Stack" proxy to the client. (The details of 
  11386.  this procedure are deferred until section 6.4, "Basic Server Programming".) 
  11387.  
  11388.      Ask the "Stack" proxy to push 100 onto the remote stack: 
  11389.  
  11390.             _push(stk,&e,100);
  11391.  
  11392.  This causes a message representing the method call to be marshalled and sent 
  11393.  to the server process. In the server process, DSOM demarshals the message and, 
  11394.  with the help of the SOMDServer, locates the target "Stack" object upon which 
  11395.  it invokes the method ("push"). The result (which is void in this case) is 
  11396.  then passed back to the client process in a message. 
  11397.  
  11398.      Invoke more "Stack" operations on the remote stack, via the proxy: 
  11399.  
  11400.             _push(stk,&e,200);
  11401.  
  11402.             _pop(stk,&e);
  11403.  
  11404.             if (!_empty(stk,&e)) t = _top(stk,&e);
  11405.  
  11406.      Explicitly destroy both the remote stack, the stack proxy, and the server 
  11407.       proxy: 
  11408.  
  11409.             _somdDeleteObj(server, &e, stk);
  11410.  
  11411.             _somdReleaseObject(SOMD_ObjectMgr, &e, stk);
  11412.  
  11413.             _somdReleaseObject(SOMD_ObjectMgr, &e, server);
  11414.  
  11415.      Free the error-passing environment: 
  11416.  
  11417.             SOM_UninitEnvironment(&e);
  11418.  
  11419.  This scenario has introduced the key processes in a DSOM application: client, 
  11420.  server, and somdd. Also introduced are the key objects that comprise the DSOM 
  11421.  run-time environment: the SOMD_ObjectMgr in the client process and the 
  11422.  SOMD_ServerObject in the server process. 
  11423.  
  11424.  
  11425. ΓòÉΓòÉΓòÉ 7.12.11. Summary ΓòÉΓòÉΓòÉ
  11426.  
  11427. This example has introduced the key concepts of building, installing, and 
  11428. running a DSOM application. It has also introduced some of the key components 
  11429. that comprise the DSOM application run-time environment. 
  11430.  
  11431. The following sections, "Basic Client Programming," "Basic Server Programming," 
  11432. and "Implementing Classes," provide more detail on how to use, manage, and 
  11433. implement remote objects, respectively. 
  11434.  
  11435.  
  11436. ΓòÉΓòÉΓòÉ 7.13. Basic Client Programming ΓòÉΓòÉΓòÉ
  11437.  
  11438. For the most part, client programming in DSOM is exactly the same as client 
  11439. programming in SOM, since DSOM transparently hides the fact that an object is 
  11440. remote when the client accesses the object. 
  11441.  
  11442. However, a client application writer also needs to know how to create, locate, 
  11443. use, save, and destroy remote objects. (This is not done using the usual SOM 
  11444. bindings.) The DSOM run-time environment provides these services to client 
  11445. programs primarily through the DSOM Object Manager. These run-time services 
  11446. will be detailed in this section. Examples of how an application developer uses 
  11447. these services are provided throughout the section. 
  11448.  
  11449.  
  11450. ΓòÉΓòÉΓòÉ 7.13.1. DSOM Object Manager ΓòÉΓòÉΓòÉ
  11451.  
  11452. DSOM defines a DSOM Object Manager, which provides services needed by clients 
  11453. to create, find and use objects in the DSOM run-time environment. 
  11454.  
  11455. The DSOM Object Manager is derived from an abstract, generic "object manager" 
  11456. class, called ObjectMgr. This abstract ObjectMgr class defines a basic set of 
  11457. methods that support object creation, location (with implicit activation), and 
  11458. destruction. 
  11459.  
  11460. As an abstract class, ObjectMgr defines only an interface; there is no 
  11461. implementation associated with ObjectMgr. Consequently, an application should 
  11462. not create instances of the ObjectMgr class. 
  11463.  
  11464.  An abstract Object Manager class was defined under the expectation that 
  11465. applications will often need simultaneous access to objects implemented and 
  11466. controlled by a variety of object systems. Such object systems may include 
  11467. other ORBs (in addition to DSOM), persistent object managers, object-oriented 
  11468. databases, and so forth. It is likely that each object system will provide the 
  11469. same sort of basic services for object creation, location, and activation, but 
  11470. each using a different interface. 
  11471.  
  11472. Thus, the ObjectMgr abstract class defines a simple and "universal" interface 
  11473. that can be mapped to any object system. The application would only have to 
  11474. understand a single, common ObjectMgr interface. Under this scheme, specific 
  11475. object managers are defined by subclassing the ObjectMgr class and overriding 
  11476. the ObjectMgr methods to map them into the object system-specific programming 
  11477. interfaces. 
  11478.  
  11479. DSOM's Object Manager, SOMDObjectMgr, is defined as a specific class of 
  11480. ObjectMgr. It defines methods for: 
  11481.  
  11482.      Finding servers that implement particular kinds of objects 
  11483.  
  11484.      Creating objects in servers 
  11485.  
  11486.      Obtaining object identifiers (string IDs) 
  11487.  
  11488.      Finding objects, given their identifiers 
  11489.  
  11490.      Releasing and destroying objects 
  11491.  
  11492.  These functions will be discussed in the remainder of this section. 
  11493.  
  11494.  Note:  The OMG has standardized an "object lifecycle" service, which includes 
  11495.         support for creating and destroying distributed objects.  The DSOM 
  11496.         Object Manager may be augmented in the future with an OMG-compliant 
  11497.         lifecycle service. 
  11498.  
  11499.  
  11500. ΓòÉΓòÉΓòÉ 7.13.2. Initializing a client program ΓòÉΓòÉΓòÉ
  11501.  
  11502. A client application must declare and initialize the DSOM run time before 
  11503. attempting to create or access a remote object. The SOMD_Init procedure 
  11504. initializes all of the DSOM run time, including the  SOMDObjectMgr object. The 
  11505. global variable, SOMD_ObjectMgr is initialized to point to the local DSOM 
  11506. Object Manager. 
  11507.  
  11508. A client application must also initialize all application classes used by the 
  11509. program. For each class, the corresponding <className>NewClass call should be 
  11510. made. 
  11511.  
  11512. Note:  In non-distributed SOM programs, the <className>New macro (and the new 
  11513.        operator provided for each class by the SOM C++ bindings) implicitly 
  11514.        calls the procedure <className>NewClass when creating a new object. This 
  11515.        is not currently possible in DSOM because, when creating remote objects, 
  11516.        DSOM uses a generic method that is not class-specific. 
  11517.  
  11518.  This was shown in the "Stack" example in section 6.2. In a similar example of 
  11519.  an application that uses "Car" and "Driver" objects, the initialization code 
  11520.  might look like this: 
  11521.  
  11522.   #include <somd.h>    /* needed by all clients */
  11523.   #include <Car.h>     /* needed to access remote Car */
  11524.   #include <Driver.h>  /* needed to access remote Driver */
  11525.  
  11526.   main()
  11527.   {
  11528.       Environment ev; /* ev used for error passing */
  11529.       SOM_InitEnvironment(&ev);
  11530.  
  11531.       /* Do DSOM initialization */
  11532.       SOMD_Init(&ev);
  11533.  
  11534.       /* Initialize application classes */
  11535.       CarNewClass(Car_MajorVersion, Car_MinorVersion);
  11536.       DriverNewClass(Driver_MajorVersion, Driver_MinorVersion);
  11537.       ...
  11538.   }
  11539.  
  11540.  As shown, client programs should include the "somd.h" file (or, for C++ 
  11541.  programs, the "somd.xh" file) in order to define the DSOM run#time interfaces. 
  11542.  
  11543.  Note also that, since Environments are used for passing error results between 
  11544.  a method and its caller, an Environment variable (ev) must be declared and 
  11545.  initialized for this purpose. 
  11546.  
  11547.  The calls to "CarNewClass" and "DriverNewClass" are required if the client 
  11548.  will be creating or accessing Cars and Drivers. The procedures "CarNewClass" 
  11549.  and "DriverNewClass" create class objects for the classes "Car" and "Driver". 
  11550.  When a DSOM Object Manager method like somdNewObject is invoked to create a 
  11551.  "Car", it expects the "Car" class object to exist. If the class does not yet 
  11552.  exist, the "ClassNotFound" exception will be returned. 
  11553.  
  11554.  
  11555. ΓòÉΓòÉΓòÉ 7.13.3. Exiting a client program ΓòÉΓòÉΓòÉ
  11556.  
  11557. At the end of a client program, the SOMD_Uninit procedure must be called to 
  11558. free DSOM run-time objects, and to release system resources such as semaphores, 
  11559. shared memory segments, and so on. SOMD_Uninit should be called even if the 
  11560. client program terminates unsuccessfully; otherwise, system resources will not 
  11561. be released. 
  11562.  
  11563. For example, the exit code in the client program might look like this: 
  11564.  
  11565.     ...
  11566.     SOMD_Uninit(&e);
  11567.     SOM_UninitEnvironment(&e);
  11568. }
  11569.  
  11570. Note also the SOM_UninitEnvironment call, which frees any memory associated 
  11571. with the specified Environment structure. 
  11572.  
  11573. Note:  When a Windows DSOM client receives a WM-QUIT message while processing a 
  11574.        remote method invocation, DSOM will clean up and terminate the client 
  11575.        without returning to the client's WinProc or WinMain. 
  11576.  
  11577.  
  11578. ΓòÉΓòÉΓòÉ 7.13.4. Creating remote objects ΓòÉΓòÉΓòÉ
  11579.  
  11580. Distributed objects can be created in several different ways in DSOM. 
  11581.  
  11582.      The client can create an object on any server that implements that class 
  11583.       of object. 
  11584.  
  11585.      The client can find a specific server upon which to create an object. 
  11586.  
  11587.      A server can create an object and register a reference to the object in 
  11588.       some well-known directory. (An object reference contains information that 
  11589.       reliably identifies a particular object.) 
  11590.  
  11591.  The first two cases are discussed immediately below. The last case is 
  11592.  discussed near the end of this section. 
  11593.  
  11594.  
  11595. ΓòÉΓòÉΓòÉ 7.13.4.1. Creating an object in an arbitrary server ΓòÉΓòÉΓòÉ
  11596.  
  11597. Following is an example of how to create a new remote object in the case where 
  11598. the client does not care in which server the object is created. In this 
  11599. situation, the client defers these decisions to the DSOM Object Manager 
  11600. (SOMD_ObjectMgr) by using the somdNewObject method call, which has this IDL 
  11601. definition: 
  11602.  
  11603.  
  11604.   // (from file om.idl)
  11605.  
  11606.  
  11607.   SOMObject somdNewObject(in Identifier objclass, in string hints);
  11608.  
  11609.   // Returns a new object of the named class.  This is a "basic"
  11610.   // creation method, where the decisions about where and how to
  11611.   // create the object are mostly left up to the Object Manager.
  11612.   // However, the Object Manager may optionally define creation
  11613.   // "hints" which the client may specify in this call.
  11614.  
  11615. Here is the example of how a remote "Car" would be created using somdNewObject: 
  11616.  
  11617. #include <somd.h>
  11618. #include <Car.h>
  11619.  
  11620. main()
  11621. {
  11622.     Environment ev;
  11623.     Car car;
  11624.  
  11625.     SOM_InitEnvironment(&ev);
  11626.     SOMD_Init(&ev);
  11627.  
  11628.     /* create the class object */
  11629.     CarNewClass(Car_MajorVersion, Car_MinorVersion);
  11630.  
  11631.     /* create a Car object on some server, let the
  11632.        Object Manager choose which one */
  11633.     car = _somdNewObject(SOMD_ObjectMgr, &ev, "Car", "");
  11634.     ...
  11635. }
  11636.  
  11637. The main argument to the somdNewObject method call is a string specifying the 
  11638. name of the class of the desired object. The last argument is a string that may 
  11639. contain "hints" for the Object Manager when choosing a server. In this example, 
  11640. the client is providing no hints. (Currently, the DSOM Object Manager simply 
  11641. passes the hints to the server object in a somdCreateObj call.) 
  11642.  
  11643.  
  11644. ΓòÉΓòÉΓòÉ 7.13.4.2. Proxy objects ΓòÉΓòÉΓòÉ
  11645.  
  11646. As far as the client program is concerned, when a remote object is created, a 
  11647. pointer to the object is returned. However, what is actually returned is a 
  11648. pointer to a proxy object, which is a local representative for the remote 
  11649. target object. 
  11650.  
  11651. Proxies are responsible for ensuring that operations invoked on it get 
  11652. forwarded to the "real" target object that it represents. The DSOM run time 
  11653. creates proxy objects automatically, wherever an object is returned as a result 
  11654. of some remote operation. The client program will always have a proxy for each 
  11655. remote target object on which it operates. Proxies are described further in the 
  11656. sections entitled "DSOM as a CORBA-compliant Object Request Broker" and 
  11657. "Advanced Topics". 
  11658.  
  11659. In the example above, a pointer to a "Car" proxy is returned and put in the 
  11660. variable "car". Any subsequent methods invoked on "car" will be forwarded and 
  11661. executed on the corresponding remote "Car" object. 
  11662.  
  11663. Proxy objects inherit behavior from the SOMDClientProxy class. 
  11664.  
  11665.  
  11666. ΓòÉΓòÉΓòÉ 7.13.4.3. Servers and server objects ΓòÉΓòÉΓòÉ
  11667.  
  11668. In DSOM, the process that manages a target object is called the object's 
  11669. server. Servers are implemented as programs that use SOM classes. The example 
  11670. above placed no constraints on the DSOM Object Manager as to which server 
  11671. should create the remote "Car" object. However, if the client desires more 
  11672. control over distribution of objects, the DSOM Object Manager provides methods 
  11673. for finding specific servers. 
  11674.  
  11675. Server implementations are registered with DSOM in an Implementation 
  11676. Repository. Server implementations are described by a unique ID, a unique 
  11677. (user-friendly) name, the program name that implements the server, the classes 
  11678. that are implemented by the server, the machine on which the server is located, 
  11679. whether the server is multi-threaded, and so forth. (See section 6.6 for more 
  11680. information on registering server implementations.) A client can ask the DSOM 
  11681. Object Manager to find a particular server: 
  11682.  
  11683.      By name 
  11684.  
  11685.      By ID 
  11686.  
  11687.      By a class it supports 
  11688.  
  11689.  When a client asks for a "server", it is given (a proxy to) a server object 
  11690.  that provides interfaces for managing the objects in the server. There is one 
  11691.  server object per server process. All server objects are instances of the 
  11692.  SOMDServer class, or its subclasses. The default method provided by SOMDServer 
  11693.  for creating objects is: 
  11694.  
  11695.     // (from file somdserv.idl)
  11696.  
  11697.     SOMObject somdCreateObj(in Identifier objclass, in string hints);
  11698.  
  11699.     // Creates an object of the specified class.  This method
  11700.     // may optionally define creation "hints" which the client
  11701.     // may specify in this call.  (Hints are ignored by default.)
  11702.  
  11703.  Section 6.4 explains how to create application-specific server objects, 
  11704.  derived from SOMDServer, which override SOMDServer methods and introduce their 
  11705.  own methods for object management. 
  11706.  
  11707.  
  11708. ΓòÉΓòÉΓòÉ 7.13.4.4. Creating an object in a specific server ΓòÉΓòÉΓòÉ
  11709.  
  11710. The following example demonstrates how a client application creates a new 
  11711. object in a remote server chosen by the client. The DSOM Object Manager method 
  11712. somdFindServerByName is used to find and create a proxy to the server object 
  11713. for the server implementation named "myCarServer". The method somdCreateObj is 
  11714. then invoked on the server object to create the remote "Car". A proxy to the 
  11715. remote "Car" is returned. (The "Stack" client presented in the previous section 
  11716. used the same methods to create a remote "Stack".) 
  11717.  
  11718.  /* find a specific Car server */
  11719.     server =
  11720.       _somdFindServerByName(SOMD_ObjectMgr, &ev, "myCarSe           rver");
  11721.  
  11722.  /* create a remote Car object on that server */
  11723.     car = _somdCreateObj(server, &ev, "Car", "");
  11724.     ...
  11725. }
  11726.  
  11727. Note:  If the specified server does not provide any implementation of the 
  11728.        desired class, a NULL pointer will be returned and a "ClassNotFound" 
  11729.        exception will be raised. 
  11730.  
  11731.  Three other methods can be invoked on the DSOM Object Manager to find server 
  11732.  implementations: somdFindServer, somdFindServersByClass, and 
  11733.  somdFindAnyServerByClass. The IDL declarations of these methods follow: 
  11734.  
  11735.  
  11736.   SOMDServer somdFindServer(in ImplId serverid);
  11737.  
  11738.   sequence<SOMDServer> somdFindServersByClass(in Identifier objclass);
  11739.  
  11740.   SOMDServer somdFindAnyServerByClass(in Identifier objclass);
  11741.  
  11742.  The somdFindServer method is similar to the somdFindServerByName method, 
  11743.  except that the server's implementation ID (of type ImplId) is used to 
  11744.  identify the server instead of the server's user-friendly name (or "alias"). 
  11745.  The implementation ID is a unique string generated by the Implementation 
  11746.  Repository during server registration. (See section 6.6 for more details.) 
  11747.  
  11748.  The somdFindServersByClass method, given a class name, returns a sequence of 
  11749.  all servers that support the given class. The client program may then choose 
  11750.  which server to use, based on the server's name, program, or other 
  11751.  implementation attributes (e.g., the server is multi-threaded). (See the topic 
  11752.  below, "Inquiring about a remote object's implementation.") 
  11753.  
  11754.  Finally, the somdFindAnyServerByClass method simply selects any one of the 
  11755.  server implementations registered in the Implementation Repository that 
  11756.  supports the given class, and returns a server proxy for that server. 
  11757.  
  11758.  Once the server proxy is obtained, methods like somdCreateObj, shown in the 
  11759.  example above, can be invoked upon it to create new objects. 
  11760.  
  11761.  
  11762. ΓòÉΓòÉΓòÉ 7.13.4.5. Inquiring about a remote object's implementation ΓòÉΓòÉΓòÉ
  11763.  
  11764. A client may wish to inquire about the (server) implementation of a remote 
  11765. object. All objects in a server, including the "server object", share the same 
  11766. implementation definition. This is common when using the somdFindServersByClass 
  11767. call, where a sequence of server proxies is returned, and some choice must be 
  11768. made about which to use. 
  11769.  
  11770. When a proxy is obtained by a client, the client can inquire about the 
  11771. underlying server implementation by obtaining its corresponding 
  11772. ImplementationDef. An ImplementationDef object  contains a set of attributes 
  11773. that describe a server implementation. To get the ImplementationDef associated 
  11774. with a remote object, the get_implementation method (implemented on SOMDObject 
  11775. and inherited by SOMDClientProxy) can be called. 
  11776.  
  11777. For example, if a program has a proxy for a remote server object, it can get 
  11778. the ImplementationDef for the server with method calls similar to the 
  11779. following: 
  11780.  
  11781.  
  11782.     ImplementationDef implDef;
  11783.     SOMDServer server;
  11784.  
  11785.     ...
  11786.     implDef = _get_implementation(server, &ev);
  11787.  
  11788. Once the ImplementationDef has been obtained, the application can access its 
  11789. attributes using the _get_impl_xxx methods. 
  11790.  
  11791. The ImplementationDef class is discussed further in section 6.6, "Configuring 
  11792. DSOM." 
  11793.  
  11794.  
  11795. ΓòÉΓòÉΓòÉ 7.13.5. Destroying remote objects ΓòÉΓòÉΓòÉ
  11796.  
  11797. There are several ways of destroying objects or their proxies in DSOM, just as 
  11798. there are several ways to create objects. Remote objects can be asked to 
  11799. destroy themselves, or, the SOMDObjectMgr and the SOMDServer can participate in 
  11800. the deletion. 
  11801.  
  11802.  
  11803. ΓòÉΓòÉΓòÉ 7.13.5.1. Destroying objects via a proxy ΓòÉΓòÉΓòÉ
  11804.  
  11805. DSOM provides means for deleting remote objects via their proxies. For example, 
  11806. if somFree is invoked on a proxy, the somFree call gets forwarded directly to 
  11807. the target object, just like any other target method call. For example, 
  11808.  
  11809.  
  11810. _somFree(car);
  11811.  
  11812. frees the remote car.  Note that, by default, invoking somFree on the proxy 
  11813. does not free the proxy, only the remote object.  However, the following call 
  11814. can be issued as part of a client-program initialization, so that invoking 
  11815. somFree on a proxy frees both the remote object and the proxy: 
  11816.  
  11817.    __set_somd21somFree(SOMD_ObjectMgr, ev, TRUE);
  11818.  
  11819. All subsequent invocations of somFree on a proxy object will result in both the 
  11820. remote object and the proxy being freed. 
  11821.  
  11822. To be explicit about whether the proxy or the remote object is being deleted, 
  11823. the methods somdTargetFree and somdProxyFree, defined on proxies, can be used: 
  11824.  
  11825. _somdTargetFree(car, &ev);
  11826. frees the remote "Car" (but not the proxy) and 
  11827.  
  11828. _somdProxyFree(car, &ev);
  11829.  
  11830. frees the proxy (but not the remote "Car"). 
  11831.  
  11832. Note:  CORBA specifies a third method for deleting object references. (Proxies 
  11833.        are a specialized type of object reference.) The method 
  11834.  
  11835.  
  11836.                       _release(car, &ev);
  11837.  
  11838.  
  11839.                deletes the proxy (but not the target object).
  11840.  
  11841.  
  11842. ΓòÉΓòÉΓòÉ 7.13.5.2. Destroying objects via the DSOM Object Manager ΓòÉΓòÉΓòÉ
  11843.  
  11844. Having created a remote object with somdNewObject or somdCreateObj, the remote 
  11845. object and its local proxy may be destroyed by invoking the method 
  11846. somdDestroyObject on the DSOM Object Manager using the proxy as an argument. 
  11847. For example, 
  11848.  
  11849.  
  11850. /* create the car */
  11851. car = _somdNewObject(SOMD_ObjectMgr, &ev, "Car", "");
  11852. ...
  11853. /* destroy the car (and its proxy) */
  11854. _somdDestroyObject(SOMD_ObjectMgr, &ev, car);
  11855.  
  11856. If the client does not want to destroy the remote object, but is finished 
  11857. working with it, the somdReleaseObject method should be used instead, e.g., 
  11858.  
  11859. _somdReleaseObject(SOMD_ObjectMgr, &ev, car);
  11860.  
  11861. This deletes the local proxy, but not the remote object. 
  11862.  
  11863. Both somdDestroyObject and somdReleaseObject are defined on the ObjectMgr, so 
  11864. that the Object Manager is aware of the client's actions, in case it wants to 
  11865. do any bookkeeping. 
  11866.  
  11867. The object passed to either the somdDestroyObject method or the 
  11868. somdReleaseObject method can be either a local SOM object or a DSOM proxy 
  11869. object.  When a local SOM object is passed, somdDestroyObject has the same 
  11870. behavior as somFree. If a local SOM object is passed to somdReleaseObject, 
  11871. however, this has no effect. 
  11872.  
  11873.  
  11874. ΓòÉΓòÉΓòÉ 7.13.5.3. Destroying objects via a server object ΓòÉΓòÉΓòÉ
  11875.  
  11876. The somdDestroyObject method described above sends a request to delete a remote 
  11877. object to the object's server. It does so to ensure that the server has an 
  11878. opportunity to participate in, if not perform, the deletion. The method defined 
  11879. on the SOMDServer class for destroying objects is somdDeleteObj. If the client 
  11880. has a proxy for the server object, it can also invoke somdDeleteObj directly, 
  11881. instead of calling somdDestroyObject. 
  11882.  
  11883. Destroying objects via the server object, rather than asking the object itself 
  11884. (as in somFree or somdTargetFree), allows the server object do any clean-up 
  11885. that is needed. For simple applications, this may not be necessary, but for 
  11886. applications that provide their own application-tailored server objects, it may 
  11887. be critical. See, for example, the persistent server example in section 6.4, 
  11888. entitled "Basic Server Programming." 
  11889.  
  11890.  
  11891. ΓòÉΓòÉΓòÉ 7.13.6. Creating remote objects using user-defined metaclasses ΓòÉΓòÉΓòÉ
  11892.  
  11893. An application may wish to define its own constructor methods for a particular 
  11894. class, via a user-supplied metaclass. In this case, the somdNewObject method 
  11895. should not be used, since it simply calls the default constructor method, 
  11896. somNew, defined by SOMClass. 
  11897.  
  11898. Instead, the application can obtain a proxy to the actual class object in the 
  11899. server process. It can do so via the somdGetClassObj method, invoked on the 
  11900. SOMDServer proxy returned by one of the somdFindServerXxx methods. The 
  11901. application-defined constructor method can then be invoked on the proxy for the 
  11902. remote class object. 
  11903.  
  11904. Note:  The same issues apply to destructor methods. If the application defines 
  11905.        its own destructor methods, they can be called via the class object 
  11906.        returned by somdGetClassObj, as opposed to calling somdDestroyObject. 
  11907.  
  11908.  The following example creates a new object in a remote server using an 
  11909.  application-defined constructor method, "makeCar", which is assumed to have 
  11910.  been defined in the metaclass of "Car", named "MetaCar". 
  11911.  
  11912.   #include <somd.h>
  11913.   #include <Car.h>
  11914.   main( )
  11915.   {
  11916.       Environment ev;
  11917.       SOMDServer server;
  11918.       Car car;
  11919.       MetaCar carClass;
  11920.  
  11921.       SOM_InitEnvironment(&ev);
  11922.       SOMD_Init(&ev);
  11923.  
  11924.       /* find a Car server */
  11925.       server = _somdFindAnyServerByClass(SOMD_ObjectMgr, &ev, "Car");
  11926.  
  11927.       /* get the class object for Car */
  11928.       carClass = (MetaCar) _somdGetClassObj(server, &ev, "Car");
  11929.  
  11930.       /* create the car object */
  11931.       car = _makeCar(carClass, &ev, "Red", "Toyota", "2-door");
  11932.  
  11933.       ...
  11934.   }
  11935.  
  11936.  
  11937. ΓòÉΓòÉΓòÉ 7.13.7. Saving and restoring references to objects ΓòÉΓòÉΓòÉ
  11938.  
  11939. A proxy is a kind of "object reference". An object reference contains 
  11940. information that is used to identify a target object. 
  11941.  
  11942. To enable clients to save references to remote objects (in a file system, for 
  11943. example) or exchange references to remote objects (with other application 
  11944. processes), DSOM must be able to externalize proxies. To "externalize a proxy" 
  11945. means to create a string ID for a proxy that can be used by any process to 
  11946. identify the remote target object. DSOM must also support the translation of 
  11947. string IDs back into proxies. 
  11948.  
  11949. The DSOM Object Manager defines two methods for converting between proxies and 
  11950. their string IDs: somdGetIdFromObject and somdGetObjectFromId. 
  11951.  
  11952. Here is an example client program that creates a remote "Car" object. It 
  11953. generates a string ID corresponding to the proxy, and saves the string ID to a 
  11954. file for later use. 
  11955.  
  11956. #include <stdio.h>
  11957. #include <somd.h>
  11958. #include <Car.h>
  11959. main( )
  11960. {
  11961.     Environment ev;
  11962.     Car car;
  11963.     string somdObjectId;
  11964.     FILE* file;
  11965.  
  11966.     SOM_InitEnvironment(&ev);
  11967.     SOMD_Init(&ev);
  11968.  
  11969.     /* create a remote Car object */
  11970.     car = _somdNewObject(SOMD_ObjectMgr, &ev, "Car", "");
  11971.  
  11972.     /* save the reference to the object */
  11973.     somdObjectId = _somdGetIdFromObject(SOMD_ObjectMgr, &ev, car);
  11974.     file = fopen("/u/joe/mycar", "w");
  11975.     fprintf(file, "%s", somdObjectId);
  11976. ...
  11977.  
  11978. Next is an example client program that retrieves the string ID and regenerates 
  11979. a valid proxy for the original remote "Car" object (assuming the remote "Car" 
  11980. object can still be found in the server). 
  11981.  
  11982. ...
  11983.     Environment ev;
  11984.     Car car;
  11985.     char buffer[256];
  11986.     string somdObjectId;
  11987.     FILE* file;
  11988.  
  11989. ...
  11990.     /* restore proxy from its string form */
  11991.     file = fopen("/u/joe/mycar", "r");
  11992.     somdObjectId = (string) buffer;
  11993.     fscanf(file, "%s", somdObjectId);
  11994.     car = _somdGetObjectFromId(SOMD_ObjectMgr, &ev, somdObjectId);
  11995. ...
  11996.  
  11997. Once the proxy has been regenerated, methods can be invoked on the proxy and 
  11998. they will be forwarded to the remote target object, as always. 
  11999.  
  12000. Note:  The somdGetIdFromObject and somdGetObjectFromId methods directly 
  12001.        correspond to the CORBA methods ORB_object_to_string and 
  12002.        ORB_string_to_object, defined on the ORB class. 
  12003.  
  12004.  
  12005. ΓòÉΓòÉΓòÉ 7.13.7.1. Finding existing objects ΓòÉΓòÉΓòÉ
  12006.  
  12007. The SOMDObjectMgr and SOMDServer classes support the methods described above, 
  12008. which allow clients to create objects in servers. However, it is also likely 
  12009. that clients will want to find and use objects that have already been created, 
  12010. usually by the servers that implement them. For example, a print service will 
  12011. create printer objects, and must then export them to clients. In that case, the 
  12012. calls to somdNewObject or somdCreateObj would be replaced with other "lookup" 
  12013. calls on some directory (server) object which would take an object name or 
  12014. identifier and return a proxy to a corresponding remote object. Likewise, the 
  12015. server that owns the object would register the exported object in the 
  12016. directory. 
  12017.  
  12018. It is important to understand that DSOM does not provide a directory service 
  12019. such as the one described. But such a directory object could be implemented by 
  12020. the application, where a table or collection object maps object names to 
  12021. proxies. The string IDs for the proxies in the directory object could be saved 
  12022. using a file (as above) or a persistent object (via the Persistence Framework 
  12023. of SOMobject Developer Toolkit). A directory server implemented using DSOM 
  12024. could be used to share the directory among processes. 
  12025.  
  12026. Upon a lookup call, the directory server could find the corresponding proxy (or 
  12027. its string ID) in the directory, and return it to the caller. 
  12028.  
  12029.  
  12030. ΓòÉΓòÉΓòÉ 7.13.8. Finding server objects ΓòÉΓòÉΓòÉ
  12031.  
  12032. The DSOM Object Manager can be used to find server object proxies using the 
  12033. somdFindServerXxx methods. However, it is important to point out that an 
  12034. application can also augment those services, by managing server proxies itself. 
  12035. Server proxies can be maintained in an application-specific directory, stored 
  12036. in a file, or passed from process to process, just as any other proxies. 
  12037.  
  12038.  
  12039. ΓòÉΓòÉΓòÉ 7.13.9. Invoking methods on remote objects ΓòÉΓòÉΓòÉ
  12040.  
  12041. As described earlier, DSOM proxies are local representatives of remote objects, 
  12042. and as such, they can be treated like the target objects themselves. Method 
  12043. calls are invoked in exactly the same manner as if the object is local. This is 
  12044. true both for method calls using the static bindings (as most of our examples 
  12045. have shown), as well as for dynamic dispatching calls, where SOM facilities 
  12046. (such as the somDispatch method) are used to construct method calls at run 
  12047. time. 
  12048.  
  12049. CORBA 1.1 also defines a dynamic invocation interface that is implemented by 
  12050. DSOM. It is described later in section 6.9, "Advanced Topics". 
  12051.  
  12052. The DSOM run time is responsible for transporting any input method argument 
  12053. values supplied by the caller (defined by legal IDL types) to the target object 
  12054. in a remote call. Likewise, the DSOM run time transports the return value and 
  12055. any output argument values back to the caller following the method call. 
  12056.  
  12057. Note:  DSOM uses the Interface Repository (IR) to discover the "signature" of a 
  12058.        method (that is, the method's prototype). It is important that the 
  12059.        contents of the IR match the method bindings used by the application 
  12060.        program (i.e. the same IDL file is used to update the IR and to generate 
  12061.        bindings). 
  12062.  
  12063.  DSOM can make remote invocations only of methods whose parameter types are 
  12064.  among the following IDL types:  basic types (short, long, unsigned short, 
  12065.  unsigned long, float, double, char, boolean, octet), enum, struct, union, 
  12066.  sequence, string, array, any, and object. The members of a struct, union, 
  12067.  sequence, or array and the value of an any, must also be from the above list 
  12068.  of supported DSOM types. 
  12069.  
  12070.  In addition to the preceding types, DSOM also supports method parameters of 
  12071.  type pointer to one of the above types (for example, long*) Pointers to 
  12072.  pointers are not supported, however, and pointers embedded within one of the 
  12073.  above types (for example, a pointer within a struct) are not supported The 
  12074.  "void *" type is also not supported. Currently, DSOM has the limitation that 
  12075.  NULL pointer values cannot be returned as inout or out method arguments 
  12076.  although it is expected that this limitation will be addressed in a future 
  12077.  release. 
  12078.  
  12079.  Types declared as SOMFOREIGN types are not currently supported by DSOM. 
  12080.  Because the SOM somI is declared as a SOMFOREIGN type, this implies that any 
  12081.  method having a parameter of type somId cannot be invoked remotely using DSOM. 
  12082.  This restriction includes the  SOM methods: somRespondsTo, somSupportsMethod, 
  12083.  somGetMethodDescriptor, somGetMethodIndex, and somGetNthMethodInfo. 
  12084.  
  12085.  When a method parameter is an object type (that is, an instance of SOMObject 
  12086.  or some class derived from SOMObject), a client program making a remote 
  12087.  invocation of that method must pass an object reference for that parameter, 
  12088.  rather than passing a local SOMObject, unless the client program is also DSOM 
  12089.  server program, in which case DSOM will automatically convert the local object 
  12090.  into an object reference. 
  12091.  
  12092.  Methods having the procedure SOM IDL modifier cannot be invoked remotely using 
  12093.  DSOM.  This is because these "methods" are called directly, rather than via 
  12094.  the normal method resolution mechanisms on which DSOM relies. 
  12095.  
  12096.  
  12097. ΓòÉΓòÉΓòÉ 7.13.9.1. Determining memory allocation and ownership ΓòÉΓòÉΓòÉ
  12098.  
  12099. When a method is invoked that returns a result of type string, sequence, or 
  12100. array, DSOM will allocate memory in the client's address space for the result. 
  12101. Ownership of this memory becomes the responsibility of the client program. When 
  12102. the client program has finished using it, the client should free the memory 
  12103. using the ORBfree function, rather than using free or SOMFree (This is because 
  12104. the memory has been allocated by DSOM using special memory management 
  12105. techniques; therefore, the client should ask DSOM to also free the memory.) 
  12106.  
  12107. When invoking a method using DSOM, the client program is  responsible for 
  12108. providing storage for all in arguments and for all inout/out arguments, with 
  12109. the following exceptions: DSOM will allocate storage for a string or for the 
  12110. _buffer field of a sequence when used as an out argument, and will allocate 
  12111. storage for the_value field of an any when used as an inout or out argument. 
  12112. This storage becomes the responsibility of the client program and should later 
  12113. be freed using ORBfree. For a string or sequence used as an inout argument, the 
  12114. out result is constrained to be no larger than the size of the in argument 
  12115. allocated by the client. 
  12116.  
  12117.  
  12118. ΓòÉΓòÉΓòÉ 7.13.10. Passing object references in method calls ΓòÉΓòÉΓòÉ
  12119.  
  12120. When pointers to objects are returned as method output values (as in the 
  12121. previous examples), DSOM automatically converts the object pointers (in the 
  12122. server) to object proxies in the client. 
  12123.  
  12124. Likewise, when a client passes object (proxy) pointers as input arguments to a 
  12125. method, DSOM automatically converts the proxy argument in the client to an 
  12126. appropriate object reference in the server. 
  12127.  
  12128. Note:  If the proxy is for an object that is in the same server as the target 
  12129.        object, DSOM gives the object reference to the server object for 
  12130.        resolution to a SOM object pointer. Otherwise, DSOM leaves the proxy 
  12131.        alone, since the proxy must refer to an object in some process other 
  12132.        than the target's server. 
  12133.  
  12134.  
  12135. ΓòÉΓòÉΓòÉ 7.13.11. Memory management ΓòÉΓòÉΓòÉ
  12136.  
  12137. DSOM programs must manage four different kinds of memory resources: objects, 
  12138. object references, Environment structures, and blocks of memory. There are 
  12139. different techniques for allocating and releasing each kind of resource. 
  12140.  
  12141. Objects and object references 
  12142.  
  12143. Creating and destroying remote objects was discussed previously in this section 
  12144. (see "Creating remote objects" and "Destroying remote objects"). Creating and 
  12145. destroying local objects is described in section 3.2, "Using SOM Classes - the 
  12146. Basics," in Chapter 3, "Using SOM Classes in Client Programs."  Object 
  12147. references are typically created automatically by DSOM as needed by the client 
  12148. program. They are also released in the client program by using either the 
  12149. release method or the somdProxyFree method. (The two methods are equivalent.) 
  12150.  
  12151. Environment structures 
  12152.  
  12153. When a client invokes a method and the method returns an exception in the 
  12154. Environment structure, it is the client's responsibility to free the exception. 
  12155. This is done by calling either exception_free or somdExceptionFree on the 
  12156. Envirnmen structure in which the exception was returned. (The two functions are 
  12157. equivalent.) A similar function, somExceptionFree, is available for SOM 
  12158. programmers however DSOM programmers can use somdExceptionFree to free all 
  12159. exceptions (regardless of whether they were returned from a local or remote 
  12160. method call). 
  12161.  
  12162. Blocks of memory 
  12163.  
  12164. For allocating and releasing blocks of memory within a client program, SOM 
  12165. provides the SOMMalloc and SOMFree functions (analogous to the C "mallo" and 
  12166. "free" functions). The "Memory Management" section of Chapter 3 describes these 
  12167. functions. To release memory allocated by DSOM in response to a remote method 
  12168. call, however, DSOM client programs should use the ORBfree function 
  12169.  
  12170. For example, when a method is invoked that returns a result of type string, 
  12171. sequence, or array, DSOM will allocate memory for the result in the client's 
  12172. address space. Ownership of this memory becomes the responsibility of the 
  12173. client program. When finished using this memory, the client program should free 
  12174. it using the ORBfree function, rather than free or SOMFree. This is because the 
  12175. memory has been allocated by DSOM using special memory-management techniques; 
  12176. therefore, the client should ask DSOM to also free the memory. If the storage 
  12177. is freed using SOMFree rather than ORBfree, then memory leaks will result. 
  12178.  
  12179. The differences between the SOMFree and ORBfree functions are twofold: 
  12180.  
  12181.    1. First, SOMFree should only be used to free memory not allocated by 
  12182.       DSO(for example, memory the client program allocated itself using 
  12183.       SOMMalloc), while ORBfree should be used to free memory allocated by DSOM 
  12184.       in response to a remote method call. 
  12185.  
  12186.    2. Second, SOMFee only frees a single block of memory (in the same way that 
  12187.       the C "free" function does), while ORBfree will free an entire data 
  12188.       structure, including any allocated blocks of memory within in. For 
  12189.       example, if a remote method call returns a sequence of structs, and each 
  12190.       struct contains a string, ORBfree will free, with a single call, not only 
  12191.       the sequence's "_buffer" member, but also each struct and all the strings 
  12192.       within the structs. Freeing a similar data structure using SOMFree would 
  12193.       require multiple calls (one for each call to SOMMalloc used to build the 
  12194.       data structure). 
  12195.  
  12196.  Some programmers may wish to use a single function to free blocks of memory, 
  12197.  regardless of whether they were allocated locally or by DSOM in response to a 
  12198.  remote method call. For these programmers, DSOM provides a function, 
  12199.  SOMD_NoORBfree, which can be called just after calling SOMD_Init in the client 
  12200.  program. (It requires no arguments and returns no value.) This function 
  12201.  specifies that the client program will free all memory blocks using SOMFree, 
  12202.  rather than ORBfree. In response to this call, DSOM will not keep track of the 
  12203.  memory it allocates for the client. Instead, it assumes that the client 
  12204.  program will be responsible for walking all data structures returned from 
  12205.  remote method calls, while calling SOMFree for each block of memory within. 
  12206.  
  12207.  
  12208. ΓòÉΓòÉΓòÉ 7.13.11.1. Memory management for method parameters ΓòÉΓòÉΓòÉ
  12209.  
  12210. For each method, five SOM IDL modifiers are available to specify the method's 
  12211. memory-management policy  (that is, whether the caller or the object owns the 
  12212. parameters' memory after the method is invoked). These modifiers are 
  12213. memory_management, caller_owns_result, caller_owns_parameters, 
  12214. object_owns_result, and object_owns_parameters. For a complete description of 
  12215. these modifiers and their meanings, see the section entitled "Implementation 
  12216. Statements" in Chapter 4, "SOM IDL and the SOM Compiler." 
  12217.  
  12218. Note that the memory-management policy for a particular parameter applies to 
  12219. the parameter and all the memory embedded within it (for example, if a struct 
  12220. is owned by the caller, then so are all the struct's members). Also note that 
  12221. the "object-owned" memory-management policy, specified by the 
  12222. object_owns_result and object_owns_parameters modifiers, is not  supported by 
  12223. DSM for metods invoked using the Dynamic Invocation Interface (DII). (This is 
  12224. because the "object-owned" policy is not CORBA-compliant, and because it 
  12225. precludes reusing Request objects to invoke a method multiple times.) 
  12226.  
  12227.  
  12228. ΓòÉΓòÉΓòÉ 7.13.11.2. The CORBA policy for parameter memory management ΓòÉΓòÉΓòÉ
  12229.  
  12230. When a class contains the SOM IDL modifier memory_management = corba, this 
  12231. signifies that all methods introduced by the class follow the CORBA 
  12232. specification for parameter memory management, except where a particular method 
  12233. has an explicit modifier (object_owns_result or object_owns_parameters) that 
  12234. indicates otherwise. The remainder of this section describes the CORBA 
  12235. specification for parameter memory management. 
  12236.  
  12237. Caller frees parameters and return results 
  12238.  
  12239. The CORBA memory-management policy specifies that the caller of a method is 
  12240. responsible for freeing all parameters and the return result after the method 
  12241. call is complete. This applies regardless of whether the parameter was 
  12242. allocated by the caller or the object (or, in the case of a remote method call, 
  12243. by DSOM). In other words, the CORBA policy asserts that parameters are 
  12244. uniformly "caller-owned". 
  12245.  
  12246. Allocation responsibilities 
  12247.  
  12248. Whether the parameter or return result should be allocated by the caller or by 
  12249. the object depends on the type  of the parameter and its mode  ("in", "inout", 
  12250. "out", or "return").  In general, the caller is responsible for allocating 
  12251. storage for most parameters and return results. More specifically, CORBA 
  12252. requires that storage for all "in" arguments, for all "inout" or "out" 
  12253. arguments, and for all "return" results must be provided by the client program, 
  12254. with certain exceptions as itemized below. 
  12255.  
  12256. The object is responsible for allocating storage as follows: 
  12257.  
  12258.      for strings when used as "out" arguments or as "return" results 
  12259.  
  12260.      for the "_buffer" field of sequences when used as "out" arguments or as 
  12261.       "return" results, 
  12262.  
  12263.      for the "_value" field of anys when used as "inout" or "out" arguments or 
  12264.       as "return" results, 
  12265.  
  12266.      for pointer types when used as "inout" or "out" arguments or as "return" 
  12267.       results, 
  12268.  
  12269.      for arrays when used as "return" results, and 
  12270.  
  12271.      for objects when used as "inout" or "out" arguments or as "return" 
  12272.       results. 
  12273.  
  12274.  Note:  For "inout" strings and sequences, the "out" result is constrained to 
  12275.         be no larger than the size of the "in" argument allocated by the 
  12276.         client. 
  12277.  
  12278.  Ownership of memory allocated in the above cases becomes the responsibility of 
  12279.  the client program. For remote method calls, when a remote object allocates 
  12280.  memory for a parameter or "return" value, DSOM subsequently allocates memory 
  12281.  in the client's address space for the parameter or result. For a 
  12282.  parameter/result that is an object (rather than a block of memory) DSOM 
  12283.  automatically creates an object reference (a proxy object) in the client's 
  12284.  address space. In each case, the memory or the proxy object becomes the 
  12285.  responsibility of the client program and should later be freed by the client, 
  12286.  using ORBfree for blocks of memory or release for proxy objects. 
  12287.  
  12288.  
  12289. ΓòÉΓòÉΓòÉ 7.13.11.3. The 'somdReleaseResources' method and object-owned parameters ΓòÉΓòÉΓòÉ
  12290.  
  12291. As stated earlier, the CORBA policy asserts that method parameters and return 
  12292. results are uniformly caller-owned. This means the method caller has the 
  12293. responsibility for freeing memory after invoking a method, regardless of 
  12294. whether the memory was allocated by the caller or the object. 
  12295.  
  12296. A class implementor can designate certain method parameters and results as 
  12297. object-owned, however, by using the object_owns_result and 
  12298. object_owns_parameters SOM IDL modifiers. These modifiers signify that the 
  12299. object, rather than the caller, is responsible for freeing the memory 
  12300. associated with the parameter/result. For "in" parameters, the object can free 
  12301. the memory any time after receiving it; for "inout" and "out" parameters, and 
  12302. for return results, the object will free the memory sometime before the object 
  12303. is destroyed. (See the section entitled "Implementation statements" in Chapter 
  12304. 4, "SOM IDL and the SOM Compiler," for more information on these modifiers.) 
  12305.  
  12306. When a DSOM client program makes a remote method invocation, via a proxy, and 
  12307. the method being invoked has an object-owned parameter or return result, then 
  12308. the client-side memory associated with the parameter/result will be owned by 
  12309. the caller's proxy, and the server-side memory will be owned by the remote 
  12310. object. The memory owned by the caller's proxy will be freed when the proxy is 
  12311. released by the client program. (The time at which the server-side memory will 
  12312. be freed depends on the implementation of the remote object.) 
  12313.  
  12314. A DSOM client can also instruct a proxy object to free all memory that it owns 
  12315. on behalf of the client without releasing the proxy (assuming that the client 
  12316. program is finished using the object-owned memory), by invoking the 
  12317. somdReleaseResource method on the proxy object. Calling somdReleaseResources 
  12318. can prevent unused memory from accumulating in a proxy. 
  12319.  
  12320. For example, consider a client program repeatedly invoking a remote method 
  12321. "get_string", which returns a string that is designated (in SOM IDL) as 
  12322. "object-owned". The proxy on which the method is invoked will store the memory 
  12323. associated with all the returned strings, even if the strings are not unique, 
  12324. until the proxy is released. If the client program only uses the last result 
  12325. returned from "get_string", then unused memory accumulates in the proxy. The 
  12326. client program can prevent this by invoking somdReleaseResources on the proxy 
  12327. object periodicall (for example, each time it finishes using the result of the 
  12328. last "get_string" call). 
  12329.  
  12330.  
  12331. ΓòÉΓòÉΓòÉ 7.13.12. Writing clients that are also servers ΓòÉΓòÉΓòÉ
  12332.  
  12333. In many applications, processes may need to play both client and server roles. 
  12334. That is, objects in the process may make requests of remote objects on other 
  12335. servers, but may also implement and export objects, requiring that it be able 
  12336. to respond to incoming requests. Details of how to write programs in this 
  12337. peer-to-peer style are explained in section 6.9, "Advanced Topics". 
  12338.  
  12339.  
  12340. ΓòÉΓòÉΓòÉ 7.13.13. Compiling and linking clients ΓòÉΓòÉΓòÉ
  12341.  
  12342. All client programs must include the header file "somd.h" (or for C++, 
  12343. "somd.xh") in addition to any "<className>.h" (or "<className>.xh") header 
  12344. files they require from application classes. All DSOM client programs must link 
  12345. to the SOMobjects Toolkit library: "libsomtk.a" on AIX and "somtk.lib" on OS/2. 
  12346. For more information, see the topic "Compiling and linking" in Chapter 3, 
  12347. "Using SOM Classes in Client Programs." 
  12348.  
  12349.  
  12350. ΓòÉΓòÉΓòÉ 7.14. Basic Server Programming ΓòÉΓòÉΓòÉ
  12351.  
  12352. Server programs execute and manage object implementations. That is, they are 
  12353. responsible for: 
  12354.  
  12355.      Notifying the DSOM daemon that they are ready to begin processing 
  12356.       requests, 
  12357.  
  12358.      Accepting client requests, 
  12359.  
  12360.      Loading class library DLLs when required, 
  12361.  
  12362.      Creating/locating/destroying local objects, 
  12363.  
  12364.      Demarshalling client requests into method invocations on their local 
  12365.       objects, 
  12366.  
  12367.      Marshalling method invocation results into responses to clients, and 
  12368.  
  12369.      Sending responses back to clients. 
  12370.  
  12371.  As mentioned previously, DSOM provides a simple, "generic" server program that 
  12372.  performs all of these tasks. All the server programmer needs to provide are 
  12373.  the application class library(ies) DLL that the implementer wants to 
  12374.  distribute. Optionally, the programmer can also supply an application#specific 
  12375.  server class, derived from SOMDServer. (The SOMDServer class can be used by 
  12376.  default.) The server program does the rest automatically. 
  12377.  
  12378.  The "generic" server program is called somdsvr and can be found in 
  12379.  /usr/lpp/som/bin/somdsvr on AIX and in %SOMBASE%\bin\somdsvr.exe on OS/2. 
  12380.  
  12381.  Some applications may require additional flexibility or functionality than 
  12382.  what is provided by the generic server program. In that case, 
  12383.  application-specific server programs can be developed. This section discusses 
  12384.  the steps involved in writing such a server program. 
  12385.  
  12386.  To create a server program, a server writer needs to know what services the 
  12387.  DSOM run-time environment will provide and how to use those services to 
  12388.  perform the duties (listed above) of a server. The DSOM run-time environment 
  12389.  provides several key objects that can be used to perform server tasks. These 
  12390.  objects and the services they provide will be discussed in this section. 
  12391.  Examples showing how to use the run-time objects to write a server are also 
  12392.  shown. 
  12393.  
  12394.  
  12395. ΓòÉΓòÉΓòÉ 7.14.1. Server run-time objects ΓòÉΓòÉΓòÉ
  12396.  
  12397. There are three DSOM run-time objects that are important in a server: 
  12398.  
  12399.      The server's implementation definition (ImplementationDef), 
  12400.  
  12401.      The SOM Object Adapter (SOMOA), and 
  12402.  
  12403.      The application-specific server object (an instance of either SOMDServer 
  12404.       or a class derived from SOMDServer). 
  12405.  
  12406.  
  12407. ΓòÉΓòÉΓòÉ 7.14.1.1. Server implementation definition ΓòÉΓòÉΓòÉ
  12408.  
  12409. A server's implementation definition must be registered in the Implementation 
  12410. Repository before a server can be used. When a client attempts to invoke a 
  12411. method on a remote object, DSOM consults the Implementation Repository to find 
  12412. the location of the target object's server. 
  12413.  
  12414. An implementation definition is represented by an object of class 
  12415. ImplementationDef, whose attributes describe a server's ID, user-assigned 
  12416. alias, host name, program pathname, the class of its server object, whether or 
  12417. not it is multi-threaded, and so forth. Implementation IDs uniquely identify 
  12418. servers within the Implementation Repository, and are used as keys into the 
  12419. Implementation Repository when retrieving the ImplementationDef for a 
  12420. particular server. 
  12421.  
  12422. It is possible to change the implementation characteristics of a server, even 
  12423. to the point of using a completely different server program on another machine 
  12424. (with Workgroup DSOM). Thus, the implementation ID identifies a logical server, 
  12425. and the ImplementationDef describes the current implementation of that logical 
  12426. server. 
  12427.  
  12428. See the topic "Registering Servers and Classes" in section 6.6 for details on 
  12429. server registration. Two registration methods are described: "manual," (via the 
  12430. regimpl, the wregimpl, or the pregimpl utility) and "programmatic," 
  12431. ImplRepository methods. 
  12432.  
  12433. When a server is initialized, it must retrieve a copy of its ImplementationDef, 
  12434. and keep it in a global variable (SOMD_ImplDefObject). This variable is used by 
  12435. the DSOM run time. (Client-only programs may leave the SOMD_ImplDefObject 
  12436. variable set to NULL.) 
  12437.  
  12438.  
  12439. ΓòÉΓòÉΓòÉ 7.14.1.2. SOM Object Adapter (SOMOA) ΓòÉΓòÉΓòÉ
  12440.  
  12441. The SOM Object Adapter (SOMOA) is the main interface between the server 
  12442. application and the DSOM run time. The SOMOA is responsible for most of the 
  12443. server duties listed at the beginning of this section. In particular, the SOMOA 
  12444. object handles all communications an interpretation of inbound requests and 
  12445. outbound results. When clients send requests to a server, the requests are 
  12446. received and processed by the SOMOA. 
  12447.  
  12448. The SOMOA works together with the server object to create and resolve DSOM 
  12449. references to local objects, and dispatch methods on objects. 
  12450.  
  12451. There is one SOMOA object per server process. (The SOMOA class is implemented 
  12452. as a single instance class.) 
  12453.  
  12454.  
  12455. ΓòÉΓòÉΓòÉ 7.14.1.3. Server object ΓòÉΓòÉΓòÉ
  12456.  
  12457. Each server process contains a single server object, which has the following 
  12458. responsibilities for managing objects in the server: 
  12459.  
  12460.      Provides an interface to client applications for basic object creation 
  12461.       and destruction services, as well as any other application-specific 
  12462.       object-management services that may be required by clients. For example, 
  12463.       a print server may have a method that returns a list of all printers 
  12464.       managed by that server. Clients may call this method to find out what 
  12465.       printers are available. 
  12466.  
  12467.      Provides an interface to the SOM Object Adapter for support in the 
  12468.       creation and management of DSOM object references (which are used 
  12469.       identify an object in the server), and for dispatching requests. 
  12470.  
  12471.      The server class, SOMDServer, defines the base interface that must be 
  12472.       supported by any server object. In addition, SOMDServer provides a 
  12473.       default implementation that is suited to managing transient SOM objects 
  12474.       in a server. This section will show how an application might override the 
  12475.       basic SOMDServer methods and introduce new methods in order to tailor the 
  12476.       server object functionality to a particular application. 
  12477.  
  12478.  
  12479. ΓòÉΓòÉΓòÉ 7.14.2. Server activation ΓòÉΓòÉΓòÉ
  12480.  
  12481. Server programs may be activated either 
  12482.  
  12483.      Automatically by the DSOM daemon, somdd, or 
  12484.  
  12485.      Manually via command line invocation, or under application control. 
  12486.  
  12487.  When a server is activated automatically by somdd, it will be passed a single 
  12488.  argument (in argv[1]) that is the implementation ID assigned to the server 
  12489.  implementation when it was registered into the Implementation Repository 
  12490.  (discussed above and in section 6.6, "Configuring DSOM Applications"). This is 
  12491.  useful when the server program cannot know until activation which "logical" 
  12492.  server it is implementing. (This is true for the generic server provided with 
  12493.  DSOM.) The implementation ID is used by the server to retrieve its 
  12494.  ImplementationDef from the Implementation Repository. 
  12495.  
  12496.  A server that is not activated by somdd may obtain its ImplementationDef from 
  12497.  the Implementation Repository in any manner that is convenient: by ID, by 
  12498.  alias, and so forth. Moreover, a server may choose to "register itself" 
  12499.  dynamically, as part of its initialization. To do so, the server would use the 
  12500.  programmatic interface to the Implementation Repository. 
  12501.  
  12502.  For example, suppose that the server program "myserver" was designed so that 
  12503.  it could be activated either automatically or manually. This requires that it 
  12504.  be written to expect the implementation ID as its first argument, and to use 
  12505.  that argument to retrieve its ImplementationDef from the Implementation 
  12506.  Repository. If an application defines a server in the Implementation 
  12507.  Repository whose implementation ID is 
  12508.  
  12509.   2bcdc4f2-0f62f780-7f-00-10005aa8afdc
  12510.  then "myserver" could be run as that server by invoking the following command: 
  12511.  
  12512.   myserver 2bcdc4f2-0f62f780-7f-00-10005aa8afdc
  12513.  
  12514.  AIX users should be aware that, unless the SetUserID mode bit is set on the 
  12515.  file containing the server program, the UID for the server process will be 
  12516.  inherited from the somdd process. To set the SetUserID mode bit from the AIX 
  12517.  command line, type one of the following commands: 
  12518.  
  12519.   chmod 4000 <filename>     - or -
  12520.   chmod u+s <filename>
  12521.  
  12522.  where "<filename>" denotes the name of the file containing the server program. 
  12523.  For additional details, see the "chmod" command in InfoExplorer or consult the 
  12524.  "man" pages. 
  12525.  
  12526.  
  12527. ΓòÉΓòÉΓòÉ 7.14.3. Initializing a server program ΓòÉΓòÉΓòÉ
  12528.  
  12529. The following subjects are discussed in this section: 
  12530.  
  12531.      Initializing the DSOM run-time environment 
  12532.      Initializing the server's ImplementationDef 
  12533.      Initializing the SOM Object Adapter 
  12534.      When initialization fails 
  12535.  
  12536.  
  12537. ΓòÉΓòÉΓòÉ 7.14.3.1. Initializing the DSOM run-time environment ΓòÉΓòÉΓòÉ
  12538.  
  12539. The first thing the server program should do is to initialize the DSOM run time 
  12540. by calling the SOMD_Init function. This causes the various DSOM run-time 
  12541. objects to be created and initialized, including the Implementation Repository 
  12542. (accessible via the global variable SOMD_ImplRepObject), which is used in the 
  12543. next initialization step. 
  12544.  
  12545.  
  12546. ΓòÉΓòÉΓòÉ 7.14.3.2. Initializing the server's ImplementationDef ΓòÉΓòÉΓòÉ
  12547.  
  12548. Next, the server program is responsible for initializing its implementationDef, 
  12549. referred to by the global variable SOMD_ImplDefObject. It is initialized to 
  12550. NULL by SOMD_Init. (For client programs it should be left as NULL.) If the 
  12551. server implementation was registered with the Implementation Repository before 
  12552. the server program was activated (as will be the case for all servers that are 
  12553. activated automatically by somdd), then the ImplementationDef can be retrieved 
  12554. from the Implementation Repository. Otherwise, the server program can register 
  12555. its implementation with the Implementation Repository dynamically (as shown in 
  12556. section 6.6, "Configuring DSOM applications"). 
  12557.  
  12558. The server can retrieve its ImplementationDef from the Implementation 
  12559. Repository by invoking the find_impldef method on SOMD_ImplRepObject.  It 
  12560. supplies, as a key, the implementation ID of the desired ImplementationDef. 
  12561.  
  12562. The following code shows how a server program might initialize the DSOM 
  12563. run-time environment and retrieve its ImplementationDef from the Implementation 
  12564. Repository. 
  12565.  
  12566. #include <somd.h> /* needed by all servers */
  12567. main(int argc, char **argv)
  12568. {
  12569.    Environment ev;
  12570.    SOM_InitEnvironment(&ev);
  12571.  
  12572. /* Initialize the DSOM run-time environment */
  12573.    SOMD_Init(&ev);
  12574.  
  12575. /* Retrieve its ImplementationDef from the Implementation
  12576.    Repository by passing its implementation ID as a key */
  12577.    SOMD_ImplDefObject =
  12578.       _find_impldef(SOMD_ImplRepObject, &ev, argv[1]);
  12579. ...
  12580. }
  12581.  
  12582.  
  12583. ΓòÉΓòÉΓòÉ 7.14.3.3. Initializing the SOM Object Adapter ΓòÉΓòÉΓòÉ
  12584.  
  12585. The next step the server must take before it is ready to accept and process 
  12586. requests from clients is to create a SOMOA object and initialize the global 
  12587. variable SOMD_SOMOAObject to point to it. This is accomplished by the 
  12588. assignment: 
  12589.  
  12590. SOMD_SOMOAObject = SOMOANew();
  12591.  
  12592. Note:  The SOMOA object is not created automatically by SOMD_Init because it is 
  12593.        only required by server processes. 
  12594.  
  12595.  After the global variables have been initialized, the server can do any 
  12596.  application-specific initialization required before processing requests from 
  12597.  clients. Finally, when the server is ready to process requests, it must call 
  12598.  the impl_is_ready method on the SOMOA: 
  12599.  
  12600.   _impl_is_ready(SOMD_SOMOAObject, &ev, SOMD_ImplDefObject);
  12601.  
  12602.  The SOMOA will then set up a communications port for incoming messages, which 
  12603.  it registers with the DSOM daemon. Once the DSOM daemon has been notified of 
  12604.  the server's port, it assists client applications in "binding" (i.e., 
  12605.  establishing a connection) to that server. 
  12606.  
  12607.  The impl_is_ready method also causes the server object, whose class is defined 
  12608.  in the server's ImplementationDef, to be created. The server object can be 
  12609.  referenced through the global variable, SOMD_ServerObject. 
  12610.  
  12611.  
  12612. ΓòÉΓòÉΓòÉ 7.14.3.4. When initialization fails ΓòÉΓòÉΓòÉ
  12613.  
  12614. It is possible that a server will encounter some error when initializing 
  12615. itself. Servers must attempt to notify DSOM that their activation failed, using 
  12616. the activate_impl_failed method. This method is called as follows: 
  12617.  
  12618. /* tell the daemon (via SOMOA) that activation failed */
  12619. _activate_impl_failed(SOMD_SOMOAObject,&ev, SOMD_ImplDefObject, rc);
  12620. Server writers should be aware, however, that until the server's 
  12621. SOMD_ImpldefObject has been initialized, it is not possible to call the 
  12622. _activate_impl_failed method on the DSOM daemon. 
  12623.  
  12624. Note:  A server program should not call activate_impl_failed once it has called 
  12625.        impl_is_ready. 
  12626.  
  12627.  
  12628. ΓòÉΓòÉΓòÉ 7.14.4. Processing requests ΓòÉΓòÉΓòÉ
  12629.  
  12630. The SOMOA is the object in the DSOM run-time environment that receives client 
  12631. requests and transforms them into method calls on local server objects. In 
  12632. order for SOMOA to listen for a request, the server program must invoke one of 
  12633. two methods on SOMD_SOMOAObject. If the server program wishes to turn control 
  12634. over to SOMD_SOMOAObject completely (that is, effectively have SOMD_SOMOAObject 
  12635. go into an infinite request-processing loop), then it invokes the 
  12636. execute_request_loop method on SOMD_SOMOAObject as follows: 
  12637.  
  12638. rc = _execute_request_loop(SOMD_SOMOAObject, &ev, SOMD_WAIT);
  12639.  
  12640. Note:  This is the way the DSOM provided "generic" server program interacts 
  12641.        with SOMD_SOMOAObject. 
  12642.  
  12643.  The execute_request_loop method takes an input parameter of type Flags. The 
  12644.  value of this parameter should be either SOMD_WAIT or SOMD_NO_WAIT. If 
  12645.  SOMD_WAIT is passed as argument, execute_request_loop will return only when an 
  12646.  error occurs. If SOMD_NO_WAIT is passed, it will return when there are no more 
  12647.  outstanding messages to be processed. SOMD_NO_WAIT is usually used when the 
  12648.  server is being used with the event manager. See "Peer vs. client-server 
  12649.  processes" in section 6.9, "Advanced Topics," for more details. 
  12650.  
  12651.  If the server wishes to incorporate additional processing between request 
  12652.  executions, it can invoke the execute_next_request method to receive and 
  12653.  execute requests one at a time: 
  12654.  
  12655.   for(;;) {
  12656.      rc = _execute_next_request(SOMD_SOMOAObject, &ev, SOMD_NO_WAIT);
  12657.      /* perform app-specific code between messages here, e.g., */
  12658.         if (!rc) numMessagesProcessed++;
  12659.   }
  12660.  
  12661.  Just like execute_request_loop, execute_next_request has a Flags argument that 
  12662.  can take one of two values: SOMD_WAIT or SOMD_NO_WAIT. If execute_next_request 
  12663.  is invoked with the SOMD_NO_WAIT flag and no message is available, the method 
  12664.  returns immediately with a return code of SOMDERROR_NoMessages. If a request 
  12665.  is present, it will execute it. Thus, it is possible to "poll" for incoming 
  12666.  requests using the SOMD_NO_WAIT flag. 
  12667.  
  12668.  
  12669. ΓòÉΓòÉΓòÉ 7.14.5. Exiting a server program ΓòÉΓòÉΓòÉ
  12670.  
  12671. When a server program exits, it should notify the DSOM run time that it is no 
  12672. longer accepting requests. This should be done whether the program exits 
  12673. normally, or as the result of an error. If this is not done, somdd will 
  12674. continue to think that the server program is active, allowing clients to 
  12675. attempt to connect to it, as well as preventing a new copy of that server from 
  12676. being activated. 
  12677.  
  12678. To notify DSOM when the server program is exiting, the deactivate_impl method 
  12679. defined on SOMOA should be called. For example, 
  12680.  
  12681.  /* tell DSOM (via SOMOA) that server is now terminating */
  12682.     _deactivate_impl(SOMD_SOMOAObject, &ev, SOMD_ImplDefObject);
  12683.  
  12684. Note:  For robustness, it would be worthwhile to add appropriate "exit 
  12685.        handlers" or "signal handlers" to your application servers that call the 
  12686.        deactivate_impl method upon abnormal program termination. This ensures 
  12687.        the the DSOM daemon is made aware of the server's termination, so that 
  12688.        client connections are no longer allowed. 
  12689.  
  12690.  Finally, at the end of a server program, the SOMD_Uninit procedure must be 
  12691.  called to free DSOM run-time objects, and to release semaphores, shared memory 
  12692.  segments, and any other system resources. 
  12693.  
  12694.  For example, the exit code in the server program might look like this: 
  12695.  
  12696.       ...
  12697.       SOMD_Uninit(&e);
  12698.       SOM_UninitEnvironment(&e);
  12699.   }
  12700.  
  12701.  Observe also the SOM_UninitEnvironment call, which frees any memory associated 
  12702.  with the specified Environment structure. 
  12703.  
  12704.  When a Windows DSOM server application receives a WM_QUIT message while 
  12705.  processing incoming requests, the execute_request_loop method will return 
  12706.  SOMDERROR_WMQUIT.  When the server receives SOMDERROR_WMQUIT, it should 
  12707.  perform its usual clean up and termination procedures. 
  12708.  
  12709.  
  12710. ΓòÉΓòÉΓòÉ 7.14.6. Managing objects in the server ΓòÉΓòÉΓòÉ
  12711.  
  12712. The following subjects are discussed in this section: 
  12713.  
  12714.      Object references, ReferenceData, and the ReferenceData table 
  12715.      Simple SOM object references 
  12716.      SOMDServer (default server-object class) 
  12717.      Creation and destruction of SOM objects 
  12718.      Mapping objects to object references 
  12719.      Hints on the use of create vs. create_constant 
  12720.      Mapping object references to objects 
  12721.      Dispatching a method 
  12722.  
  12723.  
  12724. ΓòÉΓòÉΓòÉ 7.14.6.1. Object references, ReferenceData, and the ReferenceData table ΓòÉΓòÉΓòÉ
  12725.  
  12726. One of SOMOA's responsibilities is to support the creation of object references 
  12727. (SOMDObjects). Recall from the "Stack" example discussion (in Section 6.2) that 
  12728. an object reference  is an exportable "handle" to an object and that proxies 
  12729. are examples of object references. The SOMOA interface supports three 
  12730. operations for creating object references: create, create_constant, and 
  12731. create_SOM_ref. 
  12732.  
  12733. The create and create_constant methods allow a serve to associate 
  12734. application-specific data about an object with an object reference for that 
  12735. object. This data, called reference data, is represented in a sequence of up to 
  12736. 1024 bytes of information about the object. This sequence, defined by the type 
  12737. ReferenceData, may contain the object's location, state, or any other 
  12738. characteristics meaningful to the application. Usually, ReferenceData is used 
  12739. by a server process to locate or activate an object in the server. 
  12740. ReferenceData, and hence the methods create and create_constant are usually 
  12741. only used in connection with persistent objects (objects whose lifetimes exceed 
  12742. that of the process that created them). 
  12743.  
  12744. The create method differs from the create_constant method in the following way: 
  12745. ReferenceData associated with an object reference constructed by 
  12746. create_constant is immutable whereas the the ReferenceData associated with an 
  12747. object reference created by create can be changed (via the change_id method). 
  12748. References created with create_constant return true when the method is_constant 
  12749. is invoked on them. 
  12750.  
  12751. The create method stores the ReferenceData in a ReferenceData table associated 
  12752. with the server, while create_constant maintains the ReferenceData as a 
  12753. constant part of the object reference. The ReferenceData associated with an 
  12754. object reference (whether it was constructed using create or create_constant 
  12755. can be retrieved via the SOMOA method get_id. 
  12756.  
  12757. The IDL SOMOA interface declarations of create, create_constant, get_id, and 
  12758. change_id, and the SOMDObject interface declaration of is_constant are 
  12759. presented below. 
  12760.  
  12761. /* From the SOMOA interface */
  12762.  
  12763.    sequence <octet,1024> Referencedata;
  12764.    SOMDObject create(in ReferenceData id, in InterfaceDef intf,
  12765.                      in ImplementationDef impl);
  12766.  
  12767.    SOMDObject create_constant(in ReferenceData id,
  12768.                               in InterfaceDef intf,
  12769.                               in ImplementationDef impl);
  12770.  
  12771.    ReferenceData get_id(in SOMDObject objref);
  12772.  
  12773.    void change_id(in SOMDObject objref, in ReferenceData id);
  12774.  
  12775. /* From the SOMDObject interface */
  12776.  
  12777.    boolean is_constant();
  12778.  
  12779. An example of how ReferenceData can be used by an application follows the 
  12780. description of SOMDServer objects in the next section 
  12781.  
  12782.  
  12783. ΓòÉΓòÉΓòÉ 7.14.6.2. Simple SOM object references ΓòÉΓòÉΓòÉ
  12784.  
  12785. In order to efficiently support the generation and interpretation of references 
  12786. to SOM objects, the SOMOA defines another method called create_SOM_ref. 
  12787.  
  12788. The create_SOM_ref method creates a simple DSOM reference (SOMDObject) for a 
  12789. local SOM object. The reference is "special" in that, unlike create and 
  12790. create_constant there is no user-supplied ReferenceData associated with the 
  12791. object and because the reference is only valid while the SOM object exists in 
  12792. memory. The SOMObject to which it refers can be retrieved via the 
  12793. get_SOM_object method. The is_SOM_ref method can be used to tell if the 
  12794. reference was created using create_SOM_ref or not. The IDL declarations for 
  12795. create_SOM_ref, get_SOM_object, and is_SOM_ref are displayed below: 
  12796.  
  12797. /* from SOMOA's interface */
  12798.  
  12799.    SOMDObject create_SOM_ref(in SOMObject somobj,
  12800.                              in ImplementationDef impl);
  12801.  
  12802.    SOMObject get_SOM_object(in SOMDObject somref);
  12803.  
  12804. /* from SOMDObject's interface */
  12805.  
  12806.    boolean is_SOM_ref();
  12807.  
  12808.  
  12809. ΓòÉΓòÉΓòÉ 7.14.6.3. SOMDServer (default server-object class) ΓòÉΓòÉΓòÉ
  12810.  
  12811. Every server has a server object that implements three kinds of activities: 
  12812.  
  12813.      Creation and destruction of SOM objects 
  12814.  
  12815.      Mapping between SOMObjects and SOMDObjects, and 
  12816.  
  12817.      Dispatching methods on SOM objects 
  12818.  
  12819.  Additional, application-specific server methods (for initialization, server 
  12820.  control, etc.) can be defined in a subclass of the SOMDServer class. The class 
  12821.  of the server object to be used with a server is contained in the server's 
  12822.  ImplementationDef. 
  12823.  
  12824.  Following are the IDL declarations of the SOMDServer operations: 
  12825.  
  12826.   // methods called by a client
  12827.  
  12828.      SOMObject somdCreateObj(in Identifier objclass, in string hints)
  12829.  
  12830.      void somdDeleteObj(in SOMObject somobj);
  12831.  
  12832.      SOMClass somdGetClassObj(in Identifier objclass);
  12833.  
  12834.   // methods called by SOMOA
  12835.  
  12836.      SOMDObject somdRefFromSOMObj(in SOMObject somobj);
  12837.  
  12838.      SOMObject somdSOMObjFromRef(in SOMDObject objref);
  12839.  
  12840.      void somdDispatchMethod(in SOMObject somobj,
  12841.                              out somToken retValue,
  12842.                              in somId methodId,
  12843.                              in va_list ap);
  12844.  
  12845.  
  12846. ΓòÉΓòÉΓòÉ 7.14.6.4. Creation and destruction of SOM objects ΓòÉΓòÉΓòÉ
  12847.  
  12848. The SOMDServer class defines methods for the basic creation of SOM objects in 
  12849. the server process (somdCreateObj), and for finding the SOM class object for a 
  12850. specified class (somdGetClassObj). With somdGetClassObj, a client can get a 
  12851. proxy to a class object on the server, so that methods introduced in the 
  12852. class's metaclass (for example, class-specific constructors, etc.) may be 
  12853. invoked directly on the class object. Examples of client use of these two 
  12854. methods were presented earlier in Sections 6.2 and 6.3. 
  12855.  
  12856. With somdDeleteObj, the client can involve the server object in object 
  12857. destruction. (The methods somdTargetFree and somFree are defined on the object 
  12858. themselves and do not involve the server object.) Involving the server object 
  12859. in object creation and destruction can be important for applications that need 
  12860. more control over how objects are created and destroyed, or if the application 
  12861. needs to keep track of an object's creation and destruction. 
  12862.  
  12863.  
  12864. ΓòÉΓòÉΓòÉ 7.14.6.5. Mapping objects to object references ΓòÉΓòÉΓòÉ
  12865.  
  12866. SOMDServer also defines methods that implement mappings between SOMObjects and 
  12867. SOMDObjects (object references) and a method for dispatching method calls on 
  12868. SOM objects. These methods are used by the SOM Object Adapter (SOMOA) when 
  12869. converting remote requests into method calls and results into responses. 
  12870.  
  12871. Recall from the topic "Proxy objects" in Section 6.3, "Basic Client 
  12872. Programming", that servers return proxies to remote objects as method results, 
  12873. not the remote objects themselves. Recall also that class libraries need not be 
  12874. designed to be distributed (that is, the code that implements the classes need 
  12875. not be aware of the existence of proxy objects at all). Thus, it is up to the 
  12876. DSOM run-time environment to ensure that proxies, rather than remote objects, 
  12877. are returned to clients. The SOMD_SOMOAObject and SOMD_ServerObject work 
  12878. together to perform this service. Whenever a result from a remote method call 
  12879. includes a SOMObject, the SOMD_SOMOAObject invokes the somdRefFromSOMObj method 
  12880. on SOMD_ServerObject, asking it to create a SOMDObject from the SOMObject. 
  12881.  
  12882. The default implementation (i.e., SOMDServer's implementation) for 
  12883. somdRefFromSOMObj uses the create_SOM_ref method to return a "simple" reference 
  12884. for the SOMObject. Application-specific server objects (instances of a subclass 
  12885. of SOMDServer) may elect to use create or create_constant to construct the 
  12886. object reference if the application requires Reference Data to be stored. 
  12887.  
  12888.  
  12889. ΓòÉΓòÉΓòÉ 7.14.6.6. Hints on the use of create vs. create_constant ΓòÉΓòÉΓòÉ
  12890.  
  12891. Enough context now exists so that the following question may be answered: "If 
  12892. object references constructed with create support changeable ReferenceData, but 
  12893. object references constructed with create_constant do not, why would I ever 
  12894. want to use create_constant?" 
  12895.  
  12896. Invocations of create add entries to a table called the ReferenceData Table. 
  12897. The ReferenceData Table is persistent; that is, ReferenceData saved in it 
  12898. persists between server activations. Two calls to create with the same 
  12899. arguments do not return the same SOMDObject (per CORBA 1.1 specifications) That 
  12900. is, if create is called twice with the same arguments, two entries in the 
  12901. ReferenceData Table will be created. If a server using create wishes to avoid 
  12902. cluttering up the ReferenceData Table with multiple references to the same 
  12903. object, it must maintain a table of its own to keep track of the references it 
  12904. has created to avoid calling create twice with the same arguments. 
  12905.  
  12906. The create_constant method stores the ReferenceData as part of the SOMDObject's 
  12907. state; that is, it does not add entries to the ReferenceData Table. The 
  12908. create_constant method, then, might be used by a server that does not want to 
  12909. maintain a table of references nor pay the penalty of cluttering up the 
  12910. ReferenceData Table with multiple entries. 
  12911.  
  12912.  
  12913. ΓòÉΓòÉΓòÉ 7.14.6.7. Mapping object references to objects ΓòÉΓòÉΓòÉ
  12914.  
  12915. The somdSOMObjFromRef method maps SOMDObjects to SOMObjects. This method is 
  12916. invoked by  SOMOA on the server object, for each object reference found as a 
  12917. parameter in a request. 
  12918.  
  12919. The default implementation for somdSOMObjFromRef returns the address of the 
  12920. SOMObject for which the specified object reference was create (using the 
  12921. somdRefFromSOMObj method). If the object reference was not created by the same 
  12922. server process, then an exception (BadObjref) is raised. The default 
  12923. implementation does not, however, verify that the original object (for which 
  12924. the object reference was created) still exists. If the original object has been 
  12925. deleted (for example, by another client program), then the address returned 
  12926. will not represent a valid object, and any methods invoked on that object 
  12927. pointer will result in server failure. Note: The default implementation of 
  12928. somdSOMObjFromRef does not check that the original object address is still 
  12929. valid because the check is very expensive and seriously degrades server 
  12930. performance. 
  12931.  
  12932. To have a server verify that all results from somdSOMObjFromRef represent valid 
  12933. objects, server programmers can subclass SOMDServer and override the 
  12934. somdSOMObjFromRef method to perform a validity check on the result (using the 
  12935. somIsObj function). For example, a subclass "MySOMDServer" of SOMDServer could 
  12936. implement the somdSOMObjFromRef method as follows: 
  12937.  
  12938. SOM_Scope SOMObject SOMLINK somdSOMObjFromRef(MySOMDServer somSelf,
  12939.                                               Environment * ev,
  12940.                                               SOMDObject objref)
  12941. {
  12942.     SOMObject obj;
  12943.     StExcep_INV_OBJREF *ex;
  12944.  
  12945.     /* MySOMDServerData *somThis = MySOMDServerGetData(somSelf); */
  12946.     MySOMDServerMethodDebug(*MySOMDServer*, *somdSOMObjFromRef");
  12947.  
  12948.     obj = MySOMDServer_parent_SOMDServer_somdSOMObjFromRef(somSelf,
  12949.                                                     ev, objref);
  12950.     if (somIsObj(obj))
  12951.         return (obj);
  12952.     else {
  12953.         ex = (StExcep_INV_OBJREF *)
  12954.               SOMMalloc(sizeof(StExcep_INV_OBJREF));
  12955.         ex->minor = SOMDERROR_BadObjref;
  12956.         ex->completed = NO;
  12957.         somSetException(ev, USER_EXCEPTION,
  12958.                         ex_StExcep_INV_OBJREF, ex);
  12959.         return (NULL);
  12960.     }
  12961. }
  12962.  
  12963.  
  12964. ΓòÉΓòÉΓòÉ 7.14.6.8. Dispatching a method ΓòÉΓòÉΓòÉ
  12965.  
  12966. After SOMOA (with the help of the local server object) has resolved all the 
  12967. SOMDObjects present in a request, it is ready to invoke the specified method on 
  12968. the target. Rather than invoking somDispatch directly  on the target, it calls 
  12969. the somdDispatchMethod method on the server object. The parameters to 
  12970. somdDispatchMethod are the same as the parameters for SOMObject::somDispatch 
  12971. (see the SOMobjects Developer Toolkit: Programmers Reference Manual for a 
  12972. complete description). 
  12973.  
  12974. The default implementation for somdDispatchMethod in SOMServer simply invokes 
  12975. SOMObject::somDispatch on the specified target object with the supplied 
  12976. arguments. The reason for this indirection through the server object is to give 
  12977. the server object a chance to intercept method calls coming into the server 
  12978. process, if desired. 
  12979.  
  12980.  
  12981. ΓòÉΓòÉΓòÉ 7.14.7. Example: Writing a persistent object server ΓòÉΓòÉΓòÉ
  12982.  
  12983. This section shows an example of how to provide a server class implementation 
  12984. for persistent SOM objects. (The Persistence Framework of the full-capability 
  12985. SOMobjects Developer Toolkit can be used to write a persistent object s erver; 
  12986. an example of that type is given in the SOMobjects Developer Toolkit Users 
  12987. Guide.)  All of the persistent object management is contained in the server 
  12988. class; this class can be used with the DSOM "generic" server program, somdsvr. 
  12989.  
  12990. The following example describes a user-supplied server class "MyPServer" that 
  12991. is derived from SOMDServer. The "MyPServer" class introduces five new methods: 
  12992.  
  12993.      isPObj 
  12994.      assignRefDataToPObj 
  12995.      deletePObj 
  12996.      getRefDataFromPObj 
  12997.      activatePObjFromRefData 
  12998.  
  12999.  and overrides four SOMDServer methods: 
  13000.  
  13001.      somdCreateObj 
  13002.      somdDeleteObj 
  13003.      somdRefFromSOMObj 
  13004.      somdSOMObjFromRef. 
  13005.  
  13006.  The example shows how a server class might use and manage Reference Data in 
  13007.  object references to find and activate persistent objects. 
  13008.  
  13009.  The IDL specification for "MyPServer" follows: 
  13010.  
  13011.  
  13012.   interface MyPServer : SOMDServer {
  13013.       boolean isPObj (in SOMObject obj);
  13014.       void assignRefDataToPObj(in SOMObject pobj);
  13015.       void deletePObj(in SOMObject pobj);
  13016.       ReferenceData getRefDataFromPObj(in SOMObject pobj);
  13017.       SOMObject activatePObjFromRefData(in ReferenceData rd);
  13018.     #ifdef __SOMIDL__
  13019.       implementation {
  13020.           somdCreateObj     : override;
  13021.           somdDeleteObj     : override;
  13022.           somdRefFromSOMObj : override;
  13023.           somdSOMObjFromRef : override:
  13024.       };
  13025.     #endif
  13026.   };
  13027.  
  13028.  The "isPObj" method returns TRUE if the object passed to it is a persistent 
  13029.  object. It is implemented as follows: 
  13030.  
  13031.   SOM_Scope boolean SOMLINK
  13032.   isPObj(MyPServer somSelf, Environment *ev, SOMObject obj) {
  13033.       return(obj && _somIsA(obj, MyPersistentObjectNewClass(0, 0));
  13034.   }
  13035.  
  13036.  The following two procedures override SOMDServer's implementations of 
  13037.  somdCreateObj and somdDeleteObj. 
  13038.  
  13039.   SOM_Scope SOMObject SOMLINK
  13040.                 somdCreateObj(MyPServer somSelf, Environment *ev,
  13041.                               Identifier objclass, string hints)
  13042.   {
  13043.      /* create the object as usual */
  13044.      SOMObject obj =
  13045.         parent_somdCreateObj(somSelf, ev, objclass, hints);
  13046.      /* if obj is persistent, assign Ref Data to it */
  13047.      if (_isPObj(somSelf, ev, obj))) {
  13048.         _assignRefDataToPObj(somSelf, ev, obj)
  13049.      }
  13050.      return(obj);
  13051.   }
  13052.  
  13053.  The implementation of somdCreateObj first creates the object as usual by 
  13054.  employing the implementation of SOMDServer  (MyPServer's parent). If the newly 
  13055.  created object is persistent, the job of "assignRefDataToPObj" is to associate 
  13056.  with the object a piece of data that (1) identifies the object, (2) is 
  13057.  retrievable from the object, and (3) can be coerced into ReferenceData so that 
  13058.  it can be used to create a SOMDObject (an object reference). 
  13059.  
  13060.   SOM_Scope void SOMLINK
  13061.       somdDeleteObj(MyPServer somSelf, Environment *ev, SOMObject obj)
  13062.   {
  13063.      /* is obj persistent, have the persistence framework delete it */
  13064.      if (_isPObj(somSelf, ev, obj)) {
  13065.      _deletePObj(somSelf, ev, obj);
  13066.      } else /* obj is not persistent, so delete as usual */
  13067.          parent_somdDeleteObj(somSelf, ev, obj);
  13068.   }
  13069.  
  13070.  The somdDeleteObj implementation, when the object to be deleted is persistent, 
  13071.  invokes "deletePObj" to delete the object. When the object is not persistent, 
  13072.  the SOMDServer implementation of somdDeleteObj deletes the object. 
  13073.  
  13074.  The following two procedures override SOMDServer's implementations of the 
  13075.  methods somdRefFromSOMObj and somdSOMObjFromRef: 
  13076.  
  13077.   SOM_Scope SOMDObject SOMLINK
  13078.                 somdRefFromSOMObj(MyPServer somSelf, Environment *ev,
  13079.                 SOMObject obj)
  13080.   {
  13081.     SOMDObject objref;
  13082.  
  13083.     /* is obj persistent */
  13084.     if (_isPObj(somSelf, ev, obj {
  13085.       /* Create an object reference based on identifying data. */
  13086.       ReferenceData rd = _getRefDataFromPObj(somSelf, ev, obj);
  13087.       InterfaceDef intf =
  13088.          _lookup_id(SOM_InterfaceRepository,ev,somGetClassName(obj));
  13089.       objref = _create_constant(SOMD_SOMOAObject, ev, &rd, intf
  13090.                                  SOMD_ImplDefObject);
  13091.       _somFree(intf);
  13092.       SOMFree(rd._buffer);
  13093.     } else /* obj is not persistent, so get Ref in usual way */
  13094.        objref = parent_somdRefFromSOMObj(somSelf, ev, obj);
  13095.     return(objref);
  13096.   }
  13097.  
  13098.  Method somdRefFromSOMObj is responsible for producing a SOMDObject (the"Ref" 
  13099.  in somdRefFromSOMObj) from a SOMObject. As mentioned earlier, SOMOA exports 
  13100.  two methods for creating SOMDObjects: create and create_constant. This 
  13101.  implementation uses create_constant because it does not want to store the 
  13102.  ReferenceData in the ReferenceData Table. If it did use create and store the 
  13103.  ReferenceData in the persistent table, the server object would either (1) have 
  13104.  to keep a persistent table that maps SOMObjects to SOMDObjects so that it 
  13105.  didn't call create twice with the same arguments (recall that create always 
  13106.  returns a new SOMDObject even when called twice with the same arguments), or 
  13107.  (2) fill up the ReferenceData table with SOMDObjects that contain the same 
  13108.  ReferenceData. 
  13109.  
  13110.  The prerequisites for asking SOMOA to create a SOMDObject are (1) some 
  13111.  ReferenceData to be associated with the SOMDObject, (2) an InterfaceDef that 
  13112.  describes the interface of the  object, and (3) an ImplementationDef that 
  13113.  describes te object's implementation. The InterfaceDef is retrieved from the 
  13114.  SOM Interface Repository using the object's class name as key. The 
  13115.  ImplementationDef is held in the variable SOMD_ImplDefObject that is set when 
  13116.  the server process is initialized. The "MyPServer" method "getRefDataFromPObj" 
  13117.  is used to retrieve the identifying data from the object and coerce it into 
  13118.  ReferenceData. With these three arguments, SOMOA's create_constant is called 
  13119.  to create the SOMDObject. 
  13120.  
  13121.   SOM_Scope SOMObject SOMLINK
  13122.                 somdSOMObjFromRef(MyPServer somSelf, Environment *ev,
  13123.                 SOMDObject objref)
  13124.   {  SOMObject obj;
  13125.  
  13126.      /* test if objref is mine */
  13127.      if (_is_constant(objref, ev)) {
  13128.         /* objref was mine, activate persistent object myself */
  13129.         ReferenceData rd = _get_id(SOMD_SOMOAObject, ev, objref)
  13130.         obj = _activatePObjFromRefData(somSelf, ev, &rd);
  13131.         SOMFree(rd._buffer);
  13132.      } else
  13133.        /* it's not one of mine, let parent activate object */
  13134.        obj = parent_somdSOMObjFromRef(somSelf, ev, objref);
  13135.      return obj;
  13136.   }
  13137.  
  13138.  This implementation of somdSOMObjFromRef is a little different from the others 
  13139.  in that the server object must determine whether the SOMDObject is one that it 
  13140.  created (that is, one that represents a persistent object), or is just a 
  13141.  SOMDObject that was created by the SOMDServer code (its parent). This is done 
  13142.  by asking the SOMDObject if it is a "constant" object reference (that is, one 
  13143.  created by create_constant). If the SOMDObject says that it is a "constant", 
  13144.  then the "MyPServer" may safely assume that the SOMDObject represents a 
  13145.  persisten object that it created. If the SOMDObject is determined to represent 
  13146.  a persistent object, then its  ReferenceData is used to locate/activate the 
  13147.  object it represents (via the method "activatePObjFromRefData"). 
  13148.  
  13149.  
  13150. ΓòÉΓòÉΓòÉ 7.14.8. Identifying the source of a request ΓòÉΓòÉΓòÉ
  13151.  
  13152. CORBA 1.1 specifies that a Basic Object Adapter should provide a facility for 
  13153. identifying the principal (or user) on whose behalf a request is being 
  13154. performed. The get_principal method, defined by BOA and impleented by SOMOA 
  13155. returns a Principal object, which identifies the caller of a particular method. 
  13156. From this information, an application can perform access control checking. 
  13157.  
  13158. In CORBA 1.1, the interface to Principal is not defined, and is left up to the 
  13159. ORB implementation. In the current release of DSOM, a Principal object is 
  13160. defined to have two attributes: 
  13161.  
  13162.  userName (string)   Identifies the name of the user who invoked a request. 
  13163.  
  13164.  hostName (string)   Identifies the name of the host from which the request 
  13165.                      originated. 
  13166.  
  13167.  Currently, the value of the UserName attribute is obtained from the USER 
  13168.  environment variable in the calling process. Likewise, the hostName attribute 
  13169.  is obtained from the HOSTNAME environment variable. This facility is intended 
  13170.  to provide basic information about the source of a request, and currently, is 
  13171.  not based on any specific authentication (i.e., "login") scheme. More rigorous 
  13172.  authentication and security mechanisms will be considered for future DSOM 
  13173.  implementations. 
  13174.  
  13175.  The IDL prototype for the get_principal method, defined on BOA (SOMOA) is as 
  13176.  follows: 
  13177.  
  13178.   Principal  get_principal (in SOMDObject obj,
  13179.                              in Environment *req_ev);
  13180.  
  13181.  This call will typically be made either by the target object or by the server 
  13182.  object, when a method call is received. The get_principal method uses the 
  13183.  Environment structure associated with the request, and an object reference for 
  13184.  the target object, to produce a Principal object that define the request 
  13185.  initiator. 
  13186.  
  13187.  Note:  CORBA 1.1 defines a "tk_Principal" TypeCode which is used to identify 
  13188.         the type of Principal object arguments in requests, in case special 
  13189.         handling is needed when building the request. Currently, DSOM does not 
  13190.         provide any special handling of objects of type "tk_Principal"; they 
  13191.         are treated like any other object. 
  13192.  
  13193.  
  13194. ΓòÉΓòÉΓòÉ 7.14.9. Compiling and linking servers ΓòÉΓòÉΓòÉ
  13195.  
  13196. The server program must include the "somd.h" header file. Server programs must 
  13197. link to the SOMobjects Toolkit library: "libsomtk.a" on AIX, and "somtk.lib" or 
  13198. OS/2. 
  13199.  
  13200. For more information, see the topic "Compiling and linking" in Chapter 5, 
  13201. "Implementing Classes in SOM." 
  13202.  
  13203.  
  13204. ΓòÉΓòÉΓòÉ 7.15. Implementing Classes ΓòÉΓòÉΓòÉ
  13205.  
  13206. DSOM has been designed to work with a wide range of object implementations, 
  13207. including SOM class libraries as well as non-SOM object implementations. This 
  13208. section describes the necessary steps in using SOM classes or non-SOM object 
  13209. implementations with DSOM. 
  13210.  
  13211.  
  13212. ΓòÉΓòÉΓòÉ 7.15.1. Using SOM class libraries ΓòÉΓòÉΓòÉ
  13213.  
  13214. It is quite easy to use SOM classes in multi-process DSOM-based applications as 
  13215. exemplified by the sample DSOM application presented in section 6.2, "A Simple 
  13216. DSOM Example". In fact, in many cases, existing SOM class libraries may be used 
  13217. in DSOM applications without requiring any special coding or recoding for 
  13218. distribution. This is possible through the use of DSOM's generic server 
  13219. program, which uses SOM and the SOM Object Adapter (SOMOA) to load SOM class 
  13220. libraries on demand, whenever an object of a particular class is created or 
  13221. activated. 
  13222.  
  13223. The topic "Registering servers and classes" in section 6.6 "Configuring DSOM 
  13224. Applications" discusses how to register a server implementation consisting of a 
  13225. DSOM generic server process and one or more SOM class libraries. 
  13226.  
  13227.  
  13228. ΓòÉΓòÉΓòÉ 7.15.1.1. Role of DSOM generic server program ΓòÉΓòÉΓòÉ
  13229.  
  13230. The generic server program provides basic server functionality: it continuously 
  13231. receives and executes requests (via an invocation of the SOMOA's 
  13232. execute_request_loop method), until the server is stopped. Some requests result 
  13233. in the creation of SOM objects; the generic server program will find and load 
  13234. the DLL for the object's class automatically, if it has not already been 
  13235. loaded. 
  13236.  
  13237. When generic server program functionality is not sufficient for the particular 
  13238. application, application-specific server programs can be developed. For 
  13239. example, some applications may want to interact with a user or I/O device 
  13240. between requests. The previous section, entitled "Basic Server Programming," 
  13241. discussed the steps involved in writing a server program. 
  13242.  
  13243.  
  13244. ΓòÉΓòÉΓòÉ 7.15.1.2. Role of SOM Object Adapter ΓòÉΓòÉΓòÉ
  13245.  
  13246. The SOM Object Adapter is DSOM's standard object adapter. It provides basic 
  13247. support for receiving and dispatching requests on objects. As an added feature, 
  13248. the SOMOA and the server process's server object collaborate t automate the 
  13249. task of converting SOM object pointers into DSOM object references, and vice 
  13250. versa. That is, whenever an object pointer is passed as an argument to a 
  13251. method, the SOMOA and the server object convert the pointer to a DSOM bject 
  13252. reference (since a pointer to an object is meaningless outside the object's 
  13253. address space). 
  13254.  
  13255.  
  13256. ΓòÉΓòÉΓòÉ 7.15.1.3. Role of SOMDServer ΓòÉΓòÉΓòÉ
  13257.  
  13258. The server process's server object (whose default class is SOMDServer) is 
  13259. responsible for creating/destroying objects on the server via somdCreateObj, 
  13260. somdGetClassObj, and somdDeleteObj, for mapping between object references 
  13261. (SOMDObjects) and SOMObjects via somdRefFromSOMObj and somdSOMObjFromRef, and 
  13262. for dispatching remote requests to server process objects via 
  13263. somdDispatchMethod. These last three methods are invoked on the server object 
  13264. by the SOMOA when objects are to be returned to clients, when incoming requests 
  13265. contain object references, and when the method is ready to be dispatched, 
  13266. respectively. By partitioning out these mapping and dispatching functions into 
  13267. the server object, the application can more easily customize them, without 
  13268. having to build object adapter subclasses. 
  13269.  
  13270. SOMDServer can be subclassed by applications that want to manage object 
  13271. location, object activation, and method dispatching. An example of such an 
  13272. application (which provides a server class implementation for persistent SOM 
  13273. objects) is shown in section 6.4, "Basic Server Programming." 
  13274.  
  13275. These features of SOMOA and SOMDServer make it possible to take existing OM 
  13276. classes, which have been written for a single-address space environment, and 
  13277. use them unchanged in a DSOM application. More information on the SOMOA and 
  13278. server objects can be found in the "Basic Server Programming" section. 
  13279.  
  13280.  
  13281. ΓòÉΓòÉΓòÉ 7.15.1.4. Implementation constraints ΓòÉΓòÉΓòÉ
  13282.  
  13283. The generic server program (somdsvr), the SOMOA, and the SOMDServer make it 
  13284. easy to use SOM classes with DSOM. However, if there are any parts of the class 
  13285. implementation that were written expecting a single-process environment, the 
  13286. class may have to be modified to behave properly in a client/server 
  13287. environment. Some common implementation practices to avoid are listed below 
  13288.  
  13289.      Printing to standard output. Any text printed by a method will appear at 
  13290.       the server, as opposed to the client. In fact, the server may not be 
  13291.       attached to a text display device or window, so the text may be lost 
  13292.       completely. It is preferred that any textual output generated by a method 
  13293.       be returned as an output string. 
  13294.  
  13295.       Note:  Passing textual output between the client program and the called 
  13296.              method via an "inout string" parameter is strongly discouraged. As 
  13297.              discussed in the CORBA 1.1 specification (page 94), the size of 
  13298.              the output string is constrained by the size of the input string. 
  13299.              If there was no input string value, the size of the output string 
  13300.              would be constrained to 0 bytes. Instead, it is preferred that 
  13301.              textual data be returned either as an output string (DSOM provides 
  13302.              the storage), or by passing a character array buffer (client 
  13303.              provides the storage). 
  13304.  
  13305.      Creating and deleting objects. Methods that create or delete objects may 
  13306.       have to be modified if the created objects are intended to be remote. The 
  13307.       calls to create local objects are different than the calls to create 
  13308.       remote objects. 
  13309.  
  13310.      Using pointers to client-allocated memory in instance variables. Consider 
  13311.       the following example: A class has a method that accepts a pointer to a 
  13312.       data value created by the client (e.g., a string or a struct), and simply 
  13313.       stores the pointer in an instance variable or attribute. However, in 
  13314.       DSOM, the called method is passed a pointer to a copy of the value (in 
  13315.       the request message body), but the copy is freed at the end of the 
  13316.       request. If the data value is meant to persist between requests, the 
  13317.       object is responsible for making its own copy of it. (The implementation 
  13318.       of the "_set_printerName" method in the topic "Wrapping a printer API" 
  13319.       later in this section is an example of a method performing such a copy.) 
  13320.  
  13321.      Using "procedure" methods. Methods having the procedure SOM IDL modifier 
  13322.       cannot be invoked remotely using DSOM.  This is because these "methods" 
  13323.       are called directly, rather than by the normal method resolution 
  13324.       mechanisms on which DSOM relies. 
  13325.  
  13326.  In addition to those coding practices which simply do not "port" to a 
  13327.  distributed environment, there are a few other restrictions that are imposed 
  13328.  by DSOM's (current) implementation. 
  13329.  
  13330.      Using parameter types not supported by DSOM. DSOM can make remote 
  13331.       invocations only of methods whose parameter types are among the following 
  13332.       IDL types:  basic types short, long, unsigned short, unsigned long,float, 
  13333.       double, char, boolean, octet), enum struct, union, sequence, string, 
  13334.       array, any, and object (an interface name, designating a pointer to an 
  13335.       object that supports that interface).  The members of a struct, union, 
  13336.       sequence, or array, and the value of any any, must also be from the above 
  13337.       list of supported DSOM types. 
  13338.  
  13339.       In addition to the above types, DSOM also supports method parameters of 
  13340.       type pointer to one of the above types (for example,  long*).  Pointers 
  13341.       to pointers are not supported, however, and pointers embedded within one 
  13342.       of the above types (for example, a pointer within a struct) are not 
  13343.       supported.  The "void*" type is also not supported.  Currently, DSOM has 
  13344.       the limitation that NULL pointer values cannot be returned as inout or 
  13345.       out method arguments, although it is expected that this limitation will 
  13346.       be addressed in the future release. 
  13347.  
  13348.       Types declared as SOMFOREIGN types are not currently supported by DSOM. 
  13349.  
  13350.      Packing of structures used as method arguments. If a compiler option is 
  13351.       used to pack or optimize storage of structs (including reordering of 
  13352.       struct members) or unions, it is important to indicate the exact 
  13353.       alignment of the structures using alignment modifiers expressed in the 
  13354.       implementation section of the IDL file. This information must then be 
  13355.       updated in the Interface Repository. 
  13356.  
  13357.  Some applications may need to associate specific identification information 
  13358.  with an object, to support application-specific object location or activation. 
  13359.  In that case, an application server should create object references 
  13360.  explicitly, using the create or create_constant method in SOMOA. A logical 
  13361.  place to put these calls is in a subclass of SOMDServer, as it is the server 
  13362.  object that is responsible for producing/activating objects from object 
  13363.  references. 
  13364.  
  13365.  
  13366. ΓòÉΓòÉΓòÉ 7.15.2. Using other object implementations ΓòÉΓòÉΓòÉ
  13367.  
  13368. As an Object Request Broker, DSOM must support a wide range of object 
  13369. implementations, including non-SOM implementations. For example, in a print 
  13370. spooler application, the implementation of a print queue object may be provided 
  13371. by the operating system, where the methods on the print queue are executable 
  13372. programs or system commands. As another example, consider an application that 
  13373. uses a large, existing class library that is not implemented using SOM. 
  13374. Finally, consider a class library where persistence is implemented by something 
  13375. other than the Persistence Framework. 
  13376.  
  13377. In each of these examples, the application must participate  in object 
  13378. identification, activation, initialization, and request dispatching. Each 
  13379. server supplies a server object (derived from SOMDServer) that works in 
  13380. conjunction with the SOMOA for this purpose. 
  13381.  
  13382.  
  13383. ΓòÉΓòÉΓòÉ 7.15.2.1. Wrapping a printer API ΓòÉΓòÉΓòÉ
  13384.  
  13385. Presented below is a simple example showing how an existing API could be 
  13386. "wrapped" as SOM objects. The API is admittedly trivial, but it is hoped that 
  13387. readers understand this simple example well enough to create more sophisticated 
  13388. applications of their own. 
  13389.  
  13390. The "API" wrapped in this example is comprised of two OS/2 system calls. The 
  13391. first one asks for a file to be printed on a specific printer: 
  13392.  
  13393. print /D:<printerName> <filename>
  13394.  
  13395. The second one asks for the file currently being printed on device 
  13396. <printerName> to be cancelled. 
  13397.  
  13398. print /D:<printerName> /C
  13399.  
  13400. Two IDL interfaces are declared in the module "PrinterModule": "Printer" and 
  13401. "PrinterServer". The "Printer" interface wraps the two system calls. The 
  13402. "PrinterServer" interface describes a subclass of SOMDServer. 
  13403. "PrinterModule::PrinterServer" will be the class of the server object in the 
  13404. print-server application. 
  13405.  
  13406. #include <somdserv.idl>
  13407.  
  13408. module PrinterModule {
  13409.   interface Printer : SOMObject {
  13410.     attribute string printerName;
  13411.     void print(in string fname);
  13412.     void cancel();
  13413.     #ifdef __SOMIDL__
  13414.     implementation {
  13415.       printerName: noset;   // memory to be allocated
  13416.       };
  13417.     #endif
  13418.   };
  13419.  
  13420.   interface PrinterServer :SOMDServer{
  13421.     #ifdef __SOMIDL__
  13422.     implementation {
  13423.       somdCreateObj: override;
  13424.       somdRefFromSOMObj: override;
  13425.       somdSOMObjFromRef: override;
  13426.       };
  13427.     #endif
  13428.   };
  13429.  
  13430. };
  13431.  
  13432. Note that the "Printer" interface defines one attribute, "printerName", that 
  13433. will be used to identify the printer. It will be set when a "Printer" is 
  13434. created. Printer's two operations, "print" and "cancel", correspond to the two 
  13435. system commands the interface is encapsulating. The "PrinterServer" interface 
  13436. does not introduce any new attributes or operations. It does specify that three 
  13437. of SOMDServer's methods will have their implementations overridden. 
  13438.  
  13439. The next three method procedures show how the "Printer" interface is 
  13440. implemented for the "_set_printerName", "print", and "cancel" methods. Recall 
  13441. (from the earlier topic "Implementation constraints") that "_set" methods for 
  13442. attributes must be explicitly implemented in order to allocate their memory, if 
  13443. data values need to persist between DSOM requests. 
  13444.  
  13445. SOM_Scope void  SOMLINK PrinterModule_Printer_set_printerName(
  13446.  PrinterModule_Printer somSelf, Environment *ev, string printerName)
  13447. {
  13448.     PrinterModule_PrinterData *somThis =
  13449.       PrinterModule_PrinterGetData(somSelf);
  13450.  
  13451.     if (_printerName) SOMFree(_printerName);
  13452.     _printerName = (string)SOMMalloc(strlen(printerName) + 1);
  13453.     strcpy(_printerName, printerName);
  13454. }
  13455.  
  13456.  
  13457. SOM_Scope void  SOMLINK PrinterModule_Printerprint(
  13458.  PrinterModule_Printer somSelf, Environment *ev, string fname)
  13459. {
  13460.     long rc;
  13461.     PrinterModule_PrinterData *somThis =
  13462.       PrinterModule_PrinterGetData(somSelf);
  13463.     string printCommand = (string)
  13464.       SOMMalloc(strlen(_printerName) + strlen(fname) + 10 + 1);
  13465.  
  13466.     sprintf(printCommand,"print /D:%s %s",_printerName,fname);
  13467.     rc = system(printCommand);
  13468.     if (rc) raiseException(ev,rc);
  13469. }
  13470.  
  13471.  
  13472. SOM_Scope void  SOMLINK PrinterModule_Printercancel(
  13473.  PrinterModule_Printer somSelf, Environment *ev)
  13474. {
  13475.     long rc;
  13476.     PrinterModule_PrinterData *somThis =
  13477.       PrinterModule_PrinterGetData(somSelf);
  13478.     string printCommand =
  13479.       (string) SOMMalloc(strlen(_printerName) + 12 + 1);
  13480.  
  13481.     sprintf(printCommand,"print /D:%s /C",_printerName);
  13482.     rc = system(printCommand);
  13483.     if (rc) raiseExeception(ev,rc);
  13484. }
  13485.  
  13486. Note:  The implementation of the "raiseException" procedure shown in the 
  13487.        example above must be provided by the application. However, it is not 
  13488.        shown in this example. 
  13489.  
  13490.  The three method procedures that implement the "PrinterServer" interface's 
  13491.  three overridden methods of SOMServer are very similar to the method 
  13492.  procedures of the "MyPServer" server-object class presented in the previous 
  13493.  section (6.4), and therefore have not been shown here. 
  13494.  
  13495.  
  13496. ΓòÉΓòÉΓòÉ 7.15.3. Parameter memory management ΓòÉΓòÉΓòÉ
  13497.  
  13498. There are five SOM IDL modifiers available for specifying the memory-management 
  13499. policy for the parameters of a method (regardless of whether the caller or the 
  13500. object owns the parameters' memory after the method is invoked). These 
  13501. modifiers are: 
  13502.  
  13503.   memory_management,  caller_owns_result,  caller_owns_parameters, 
  13504.  
  13505.     object_owns_result, and  object_owns_parameters.
  13506.  
  13507. See the section entitled "Implementation Statements" in Chapter 4, "SOM IDL and 
  13508. the SOM Compiler," for a complete description of these modifiers and their 
  13509. meanings. Note that the memory-management policy for a particular parameter 
  13510. applies to the parameter and all the memory embedded within it (for example, if 
  13511. a struct is owned by the caller, then so are all the struct's members). 
  13512.  
  13513. When a class contains the memory_management = corba SOM IDL modifier, this 
  13514. signifies that all methods introduced by the class follow the CORBA 
  13515. specification for parameter memory management, except where a particular method 
  13516. has an explicit modifier  (object_owns_result or object_owns_parameters) that 
  13517. indicates otherwise. For a description of the CORBA specification, see the 
  13518. earlier subtopic entitled "The CORBA policy for parameter memory management" 
  13519. (under the topic "Memory Management" in Section 6.3 of this chapter). 
  13520.  
  13521.  
  13522. ΓòÉΓòÉΓòÉ 7.15.4. Building and registering class libraries ΓòÉΓòÉΓòÉ
  13523.  
  13524. The generic server uses SOM's run-time facilities to load class libraries 
  13525. dynamically. Thus, dynamically linked libraries (DLLs) should be created for 
  13526. the classes, just as they would be for non-distributed SOM-based applications. 
  13527. For more information, see the topic Creating a SOM class library in Chapter 5 
  13528. "Implementing classes in SOM." 
  13529.  
  13530. During the development of the DLL, it is important to remember the following 
  13531. steps: 
  13532.  
  13533.      Export a routine called SOMInitModule in the DLL, which will be called by 
  13534.       SOM to initialize the class objects implemented in that library. 
  13535.       SOMInitModule should contain a <className>NewClass call for each class in 
  13536.       the DLL. 
  13537.  
  13538.      For each class in the DLL, specify the DLL name in the class's IDL file. 
  13539.       The DLL name is specified using the dllname=<name> modifier in the 
  13540.       implementation statement of the interface definition. If not specified, 
  13541.       the DLL filename is assumed to be the same as the class name. 
  13542.  
  13543.      For each class in the DLL, compile the IDL description of the class into 
  13544.       the Interface Repository. This is accomplished by invoking the following 
  13545.       command syntax: 
  13546.  
  13547.  
  13548.                     sc -sir -u stack.idl       (On AIX or OS/2)
  13549.  
  13550.       Note:  If the classes are not compiled into the Interface Repository, 
  13551.              DSOM will generate a run-time error (30056: 
  13552.              SOMDERROR_BadDescriptor) when an attempt is made to lookup the 
  13553.              signature of a method in the class (for example, on a method 
  13554.              call). 
  13555.  
  13556.      Put the DLL in one of the directories listed in LIBPATH for AIX or OS/2, 
  13557.       or listed in PATH for Windows.  This is necessary for both OS/2, AIX, and 
  13558.       Windows.) 
  13559.  
  13560.  
  13561. ΓòÉΓòÉΓòÉ 7.16. Configuring DSOM Applications ΓòÉΓòÉΓòÉ
  13562.  
  13563. The following subjects are discussed in this section: 
  13564.  
  13565.      Preparing the environment 
  13566.      Registering class interfaces 
  13567.      Registering servers and classes 
  13568.      The 'regimpl', 'pregimpl', 'wregimpl' registration utilities 
  13569.      Programmatic interface to the Implementation Repository 
  13570.      The 'dsom' server manager utility 
  13571.      Verifying the DSOM environment with 'somdchk' 
  13572.      Freeing interprocess communication resources on AIX 
  13573.  
  13574.  
  13575. ΓòÉΓòÉΓòÉ 7.16.1. Preparing the environment ΓòÉΓòÉΓòÉ
  13576.  
  13577. Some environment variables must be defined before running DSOM. Unless noted, 
  13578. these environment variables are required in both the AIX and OS/2 environments. 
  13579.  
  13580.  HOSTNAME=<name>                   Each machine that is running DSOM must have 
  13581.                                    its HOSTNAME variable set. 
  13582.  
  13583.  USER=<name>                       USER specifies the name of the DSOM user 
  13584.                                    running a client program. 
  13585.  
  13586.  SOMIR=<file(s)>                   SOMIR specifies a list of files (separated 
  13587.                                    by a colon on AIX and a semicolon on OS/2) 
  13588.                                    which together make up the Interface 
  13589.                                    Repository. See Chapter 7, "The Interface 
  13590.                                    Repository Framework," for more information 
  13591.                                    on how to set this variable. 
  13592.  
  13593.                                    Note:  For DSOM, it is preferable to use 
  13594.                                           full pathnames in the list of IR 
  13595.                                           files, since the IR will be shared by 
  13596.                                           several programs that may not all be 
  13597.                                           started in the same directory. 
  13598.  
  13599.  SOMSOCKETS=<name>                 SOMSOCKETS specifies the name of the SOM 
  13600.                                    Sockets subclass that implements the sockets 
  13601.                                    services. 
  13602.  
  13603.                                    Note:  For Workstation DSOM, this variable 
  13604.                                           is effectively ignored. (However, it 
  13605.                                           may be used by the Event Management 
  13606.                                           Framework.) 
  13607.  
  13608.  SOMDDIR=<directory>               SOMDDIR specifies the directory where 
  13609.                                    various DSOM files should be located, 
  13610.                                    including the Implementation Repository 
  13611.                                    files. See the later section in this chapter 
  13612.                                    entitled "Registering servers and classes" 
  13613.                                    for more information. 
  13614.  
  13615.                                    Note:  If this value is not set, DSOM will 
  13616.                                           attempt to use a default directory: 
  13617.                                           $SOMBASE/etc/dsom on AIX, and 
  13618.                                           %SOMBASE%\ETC\DSOM on OS/2. 
  13619.  
  13620.  SOMDPORT=<integer>                In DSOM, servers, clients and DSOM daemons 
  13621.                                    communicate with each other using a 
  13622.                                    "sockets" abstraction. In particular DSOM 
  13623.                                    clients establish connections to DSOM 
  13624.                                    servers by communicating with the DSOM 
  13625.                                    daemon, somdd, running on each server 
  13626.                                    machine. The daemon is designed to listen 
  13627.                                    for client requests on a well-known port. 
  13628.  
  13629.                                    Normally, somdd will look in the 
  13630.                                    /etc/services (for AIX) or %ETC%\SERVICES 
  13631.                                    (for OS/2) file for its well-known port 
  13632.                                    number. However, if the user has set the 
  13633.                                    SOMDPORT environment variable, the value of 
  13634.                                    SOMDPORT will be used and the "services" 
  13635.                                    file will not be consulted. The user should 
  13636.                                    pick a 16-bit integer that is not likely to 
  13637.                                    be in use by another application (check the 
  13638.                                    "services" file for ports reserved for use 
  13639.                                    on your machine). Typically, values below 
  13640.                                    1024 are reserved and should not  be used. 
  13641.  
  13642.                                    Note:  If there is no "services" file and 
  13643.                                           the SOMDPORT environment variable is 
  13644.                                           not set, DSOM will use a default port 
  13645.                                           number (currently 9393). 
  13646.  
  13647.  SOMDTIMEOUT=<integer>             SOMDTIMEOUT specifies how long a receiver 
  13648.                                    should wait for a message. The value should 
  13649.                                    be expressed in seconds. The default value 
  13650.                                    is 600 seconds (10 minutes). 
  13651.  
  13652.  SOMDDEBUG=<integer>               SOMDDEBUG may optionally be set to enable 
  13653.                                    DSOM run-time error messages. If set to 0, 
  13654.                                    error reporting is disabled. If set to 1, 
  13655.                                    error reporting is enabled. Error reports 
  13656.                                    may be directed to the file named by 
  13657.                                    SOMDMESSAGELOG, if set. 
  13658.  
  13659.  SOMDMESSAGELOG=<file>             SOMDMESSAGELOG may optionally be set to the 
  13660.                                    name of a file where DSOM run-time error 
  13661.                                    messages are recorded. If not set, error 
  13662.                                    messages will be reported on the standard 
  13663.                                    output device. 
  13664.  
  13665.  SOMDNUMTHREADS=<integer>          SOMDNUMTHREADS may optionally be set to the 
  13666.                                    maximum number of requests threads created 
  13667.                                    per server.  If SOMDNUMTHREADS is not set, 
  13668.                                    then a separate thread will be created for 
  13669.                                    each request. This environment variable is 
  13670.                                    only supported on OS/2. 
  13671.  
  13672.  Note: You may want to verify your environment variable settings by running 
  13673.  somdchk. See "Verifying the DSOM environment with 'somdchk' later in this 
  13674.  chapter. 
  13675.  
  13676.  
  13677. ΓòÉΓòÉΓòÉ 7.16.2. Registering class interfaces ΓòÉΓòÉΓòÉ
  13678.  
  13679. DSOM relies heavily on the Interface Repository for information on method 
  13680. signatures (that is, a description of the method's parameters and return 
  13681. value). It is important to compile the IDL for all application classes into the 
  13682. IR before running the application. 
  13683.  
  13684. For each class in the DLL, compile the IDL description of the class into the 
  13685. Interface Repository. This is accomplished by invoking the following command 
  13686. syntax: 
  13687.  
  13688.     sc -sir -u stack.idl     (on AIX or OS/2)
  13689.  
  13690. If the default SOM IR (supplied with the SOMobjects Toolkit and Run times) is 
  13691. not used by the application, the user's IR must include the interface 
  13692. definitions for: 
  13693.  
  13694.      the appropriate Sockets class (if the SOMSOCKETS environment variable is 
  13695.       set), 
  13696.  
  13697.      the server class (derived from SOMDServer), and 
  13698.  
  13699.      the definitions of the standard DSOM exceptions (found in file 
  13700.       "stexcep.idl") that may be returned by a method call. 
  13701.  
  13702.  
  13703. ΓòÉΓòÉΓòÉ 7.16.3. Registering servers and classes ΓòÉΓòÉΓòÉ
  13704.  
  13705. Implementation definitions: 
  13706.  
  13707. The Implementation Repository holds ImplementationDef objects The 
  13708. ImplementationDef class defines attributes necessary for the SOMOA to find and 
  13709. activate the implementation of an object. Details of the ImplementationDef 
  13710. object are not currently defined in the CORBA 1.1 specification; the attributes 
  13711. that have been defined are required by DSOM. 
  13712.  
  13713. Listed below is each available attribute, with its corresponding type in 
  13714. parentheses, followed by a description of its purpose: 
  13715.  
  13716.  impl_id (string)              Contains the DSOM-generated identifier for a 
  13717.                                server implementation. 
  13718.  
  13719.  impl_alias (string)           Contains the "alias" (user-friendly name) for a 
  13720.                                server implementation. 
  13721.  
  13722.  impl_program (string)         Contains the name of the program or command file 
  13723.                                which will be executed when a process for this 
  13724.                                server is started automatically by somdd. If the 
  13725.                                full pathname is not specified, the directories 
  13726.                                specified in the  PATH environment variable will 
  13727.                                be searched for the named program or command 
  13728.                                file. 
  13729.  
  13730.                                Optionally, the server program can be run under 
  13731.                                control of a "shell" or debugger, by specifying 
  13732.                                the shell or debugger name first, followed by 
  13733.                                the name of the server program. (A space 
  13734.                                separates the two program names.)  For example, 
  13735.  
  13736.                                                                               dbx myprogram
  13737.  
  13738.                                will start the program "myprogram" under control 
  13739.                                of "dbx". 
  13740.  
  13741.                                Servers that are started automatically by somdd 
  13742.                                will always be passed their impl_id as the first 
  13743.                                parameter, in order to retrieve their 
  13744.                                ImplementationDef (if desired). 
  13745.  
  13746.  impl_flags (Flags)            Contains a bit-vector of flags used to identify 
  13747.                                server options (for example, the 
  13748.                                IMPLDEF_MULTI_THREAD flag indicates 
  13749.                                multi-threading). See the impldef.idl file for 
  13750.                                the complete set of valid ImplementationDef 
  13751.                                flags. Unused flag bits are reserved for future 
  13752.                                use by IBM. 
  13753.  
  13754.  impl_server_class (string)    Contains the name of the SOMDServer class or 
  13755.                                subclass created by the server process. 
  13756.  
  13757.  impl_refdata_file (string)    Contains the full pathname of the file used to 
  13758.                                store ReferenceData for the server. 
  13759.  
  13760.  impl_refdata_bkup (string)    Contains the full pathname of the backup mirror 
  13761.                                file used to store ReferenceData for the server. 
  13762.                                This file can be used to restore a copy of the 
  13763.                                primary file in case it becomes corrupted. (It 
  13764.                                would be a good idea to keep the primary and 
  13765.                                backup files in different disk volumes.) 
  13766.  
  13767.  impl_hostname (string)        Contains the hostname of the machine where the 
  13768.                                server is located. 
  13769.  
  13770.  
  13771. ΓòÉΓòÉΓòÉ 7.16.4. The 'regimpl', 'pregimpl', 'wregimpl' registration utilities ΓòÉΓòÉΓòÉ
  13772.  
  13773. Before an implementation (a server program and class libraries) can be used by 
  13774. client applications, it must be registered with DSOM by running the 
  13775. implementation registration utility, regimpl (on AIX), pregimpl (on OS/2) or 
  13776. wregimpl (on Windows).  The  regimpl  utility can also be executed from the DOS 
  13777. command line;  this facility is available primarily for use in batch files. 
  13778. During execution of regimpl, pregimpl, or wregimpl, DSOM updates it database to 
  13779. include the new server implementation and the associated classes. This enables 
  13780. DSOM to find and, if necessary, to activate the server so that clients can 
  13781. invoke methods on it. 
  13782.  
  13783. Typically, DSOM users employ the generic SOM-object server program, described 
  13784. below. A discussion on how to write a specific (non-generic) server program is 
  13785. found in the earlier section, "Basic Server Programming." 
  13786.  
  13787.  
  13788. ΓòÉΓòÉΓòÉ 7.16.4.1. Registration steps Using 'regimpl' ΓòÉΓòÉΓòÉ
  13789.  
  13790. Registering a server implementation and its classes requires the steps 
  13791. described in the following paragraphs. 
  13792.  
  13793. First, make sure the SOMDDIR environment variable is defined to the name of the 
  13794. Implementation Repository directory, as discussed in the section "Preparing the 
  13795. Environment." 
  13796.  
  13797. Then, to run the regimpl utility, at the system prompt enter: 
  13798.  
  13799. > regimpl 
  13800.  
  13801. This brings up the DSOM Implementation Registration Utility menu, shown below. 
  13802. To begin registering the new implementation, select "1.Add" from the 
  13803. IMPLEMENTATION OPERATIONS section; that is, at the "Enter operation:" prompt, 
  13804. enter "1" (as shown in bold): 
  13805.  
  13806. DSOM IMPLEMENTATION REGISTRATION UTILITY
  13807. (C) Copyright IBM Corp. 1992,1993.  All rights reserved.
  13808.  
  13809. Implementation data being loaded from: /u/xyz/dsomRepos/
  13810.  
  13811. [ IMPLEMENTATION OPERATIONS ]
  13812.  1.Add  2.Delete  3.Change
  13813.  4.Show one  5.Show all  6.List aliases
  13814. [ CLASS OPERATIONS ]
  13815.  7.Add  8.Delete  9.Delete from all  10.List classes
  13816. [ SAVE & EXIT OPERATIONS ]
  13817.  11.Save data  12.Exit
  13818. Enter operation: 1
  13819.  
  13820. The regimpl utility then issues several prompts for information about the 
  13821. server implementation (typical responses are shown in bold as an example). 
  13822.  
  13823. Implementation alias.  Enter a "shorthand" name for conveniently referencing 
  13824. the registered server implementation while using regimpl: 
  13825.  
  13826. Enter an alias for new implementation:  myServer
  13827.  
  13828. Program name.  Enter the name of the program that will execute as the server. 
  13829. This may be the name of one of the DSOM generic servers (discussed under the 
  13830. later topic "Running DSOM Servers") or a user-defined name for one of these 
  13831. servers. If the program is located in PATH, only the program name needs to be 
  13832. specified. Otherwise, the pathname must be specified. 
  13833.  
  13834. Enter server program name:(default: somdsvr)  <return>
  13835.  
  13836. Multi-threading.  Specify whether or not the server expects the SOM Object 
  13837. Adapter (SOMOA) to run each method in a separate thread or not. Notes: You must 
  13838. ensure that methods executed by the server are "thread safe". On AIX or 
  13839. Windows, you must also register a thread package to use a multi-threaded 
  13840. server. See "Customizing Multi-threading Services" in Chapter 5, "Implementing 
  13841. Classes in SOM". 
  13842.  
  13843. Allow multiple threads in the server? [y/n]
  13844. (default: n) : n
  13845.  
  13846. Server class.  Enter the name of the SOMDServer class or subclass that will 
  13847. manage the objects in the server. 
  13848.  
  13849. Enter server class (default: SOMDServer) : <return>
  13850.  
  13851. Reference data file name.  Enter the full pathname of the file used to store 
  13852. ReferenceData associated with object references created by this server. Note: A 
  13853. file name is required only  if the server is using the create method to 
  13854. generate object references. 
  13855.  
  13856. Enter object reference file name (optional) :  <return>
  13857. Backup reference data file name.  Enter the full pathname of the backup file 
  13858. used to mirror the primary ReferenceData file for this server. Note: a file 
  13859. name is required only if (1) a primary reference data file has been specified, 
  13860. and (2) the application desires an online backup to be maintained. This file 
  13861. can be used to restore a copy of the primary file should it become corrupted. 
  13862.  
  13863. Enter object reference backup file name (optional) : <return>
  13864.  
  13865. Host machine name.  This is the name of the machine on which the server program 
  13866. code is stored. The same name should be indicated in the HOSTNAME environment 
  13867. variable. (If "localhost" is entered, the contents of the HOSTNAME environment 
  13868. variable will be used. 
  13869.  
  13870. Enter host machine name:(default: localhost)  <return>
  13871.  
  13872. The regimpl system next displays a summary of the information defined thus far, 
  13873. and asks for confirmation before adding it. Enter "y" to save the 
  13874. implementation information in the Implementation Repository. 
  13875.  
  13876.  
  13877. ================================================================
  13878. Implementation id.........: 2befc82b-13a11e00-7f-00-10005ac9272a
  13879. Implementation alias......: myServer
  13880. Program name..............: somdsvr
  13881. Multithreaded.............: No
  13882. Server class..............:SOMDServer
  13883. Object reference file.....:
  13884. Object reference backup...:
  13885. Host Name.................: localhost
  13886.  
  13887. The above implementation is about to be added. Add? [y/n] y
  13888. Implementation 'myServer' successfully added
  13889. Add class.  Once the server implementation is added, the complete menu 
  13890. reappears. The next series of prompts and entries will identify the classes 
  13891. associated with this server. To begin, from the CLASS OPERATIONS section, 
  13892. select "7.Add": 
  13893.  
  13894.  
  13895. [ IMPLEMENTATION OPERATIONS ]
  13896.  1.Add  2.Delete  3.Change
  13897.  4.Show one  5.Show all  6.List aliases
  13898. [ CLASS OPERATIONS ]
  13899.  7.Add  8.Delete  9.Delete from all  10.List classes
  13900. [ SAVE & EXIT OPERATIONS ]
  13901.  11.Save data  12.Exit
  13902.  
  13903. Enter operation: 7
  13904. Class name.  Enter the name of a class associated with the implementation 
  13905. alias. 
  13906.  
  13907. Enter name of class:  class1
  13908.  
  13909. Implementation alias.  Enter the alias for the server that implements the new 
  13910. class (this should be the same alias as given above). 
  13911.  
  13912. Enter alias of implementation that implements class:  myServer
  13913.  
  13914. Class 'class1' now associated with implementation 'myServer'
  13915.  
  13916. The top-level menu will then reappear. Repeat the previous three steps until 
  13917. all classes have been associated with the server. 
  13918.  
  13919. Then, from the SAVE & EXIT OPERATIONS section, select "11.Save data" to 
  13920. complete the registration. Finally, select "12.Exit" to exit the regimpl 
  13921. utility. 
  13922.  
  13923. [ IMPLEMENTATION OPERATIONS ]
  13924.  1.Add  2.Delete  3.Change
  13925.  4.Show one  5.Show all  6.List aliases
  13926. [ CLASS OPERATIONS ]
  13927.  7.Add  8.Delete  9.Delete from all  10.List classes
  13928. [ SAVE & EXIT OPERATIONS ]
  13929.  11.Save data  12.Exit
  13930.  
  13931. Enter operation:  11
  13932.  
  13933. Enter operation:  12
  13934.  
  13935.  
  13936. ΓòÉΓòÉΓòÉ 7.16.4.2. Command line interface to 'regimpl' ΓòÉΓòÉΓòÉ
  13937.  
  13938. The regimpl utility also has a command line interface. The command flags 
  13939. correspond to the interactive commands described above. The syntax of the 
  13940. regimpl commands follow. 
  13941.  
  13942. Note:  The regimpl command and any optional regimpl command flags can be 
  13943.        entered at a system prompt, and the command will execute as described 
  13944.        below.  For OS/2 and Windows users, this et-based interface is 
  13945.        particularly useful in batch files.
  13946.  
  13947.  To enter interactive mode: 
  13948.  
  13949.     regimpl
  13950.  
  13951.  To add an implementation: 
  13952.  
  13953.     regimpl -A -i <str> [-p <str>] [-v <str>] [-f <str>] [-b <str>]
  13954.                           [-h <str>] [-m {on|off}] [-z <str>] [-n {on|off}]
  13955.  
  13956.  To update an implementation: 
  13957.  
  13958.     regimpl -U -i <str> [-p <str>] [-v<str>] [-f <str>]  [-b <str>]
  13959.                            [-h <str>] [-m {on|off}] [-n {on|off}]
  13960.  
  13961.  To delete one or more implementations: 
  13962.  
  13963.     regimpl -D -i <str> [-i ...]
  13964.  
  13965.  To list all, or selected, implementations: 
  13966.  
  13967.     regimpl -L  [-i <str> [-i ...]]
  13968.  
  13969.  To list all implementation aliases: 
  13970.  
  13971.     regimpl -S
  13972.  
  13973.  To add class associations to one or more implementations: 
  13974.  
  13975.     regimpl -a -c <str> [-c ...] -i <str> [-i ...rbrk.
  13976.  
  13977.  To delete class associations from all, or selected, implementations: 
  13978.  
  13979.    regimpl -d -c <str> [-c ...][-i <str> [-...]]
  13980.  
  13981.  To list classes associated with all, or selected, implementation: 
  13982.  
  13983.     regimpl -l [-i <str> [-i ...]]
  13984.  
  13985.  The following parameters are used in the commands described above: 
  13986.  
  13987.  
  13988.   -i <str>    = Implementation alias name(maximum of 16 -i names)
  13989.   -p <str>    = Server program name  (default: somdsvr)
  13990.   -v <str>    = Server-class name  (default: SOMDServer)
  13991.   -f <str>    = Reference data file name  (optional)
  13992.   -b <str>    = Reference data backup file name  (optional)
  13993.   -h <str>    = Host machine name  (default: localhost)
  13994.   -m {on|off} = Enable multi-threaded server  (optional)
  13995.   -z <str>    = Implementation ID (optional)
  13996.   -c <str>    = Class name(maximum of 16 -c names)
  13997.   -n {on|off} = Designate the server as nonstoppable (optional),
  13998.                 meaning that the server cannot be stopped using
  13999.                 the SOMDServerMgr interfaces or the "dsom" utility.
  14000.  
  14001.  
  14002. ΓòÉΓòÉΓòÉ 7.16.4.3. Registration steps using 'pregimpl' or 'wregimpl' ΓòÉΓòÉΓòÉ
  14003.  
  14004. The pregimpl utility is a Presentation Manager version of regimpl, the DSOM 
  14005. implementation definition utility. Similarly, the wregimpl utility is a Windows 
  14006. version of regimpl. The pregimpl and wregimpl utilities offer all the 
  14007. functionality of regimpl except its command-line arguments (described earlier 
  14008. in "Command line interface to `regimpl'"). In addition, the pregimpl and 
  14009. wregimpl utilities provide an intuitive GUI interface in place of regimpl's 
  14010. text-based interface. Before proceeding, you should first familiarize yourself 
  14011. with the basic registration process described earlier in "Registration steps 
  14012. using 'regimpl'". 
  14013.  
  14014. Note: OS/2 or Windows users can execute the text-interface regimpl utility by 
  14015. entering "regimpl" at a system prompt, as described in the previous topic, 
  14016. "Command line interface to `regimpl'." This facility is available primarily for 
  14017. use in batch files. 
  14018.  
  14019. You can start the pregimpl or wregimpl utility conveniently in either of two 
  14020. ways: 
  14021.  
  14022.      From the Register Impls icon in the SOMobjects icon group, or 
  14023.  
  14024.      From the Run option of the File menu. 
  14025.  
  14026.  With pregimpl or wregimpl, you can view, add, change or delete DSOM 
  14027.  implementation definitions, as well as view add or delete implementation class 
  14028.  definitions. These basic functions are accessible from the main menu in the 
  14029.  initial window that displays when you start pregimpl or wregimpl. Thus, the 
  14030.  main menu offers the choices: 
  14031.  
  14032.       File 
  14033.       Implementations 
  14034.       Classes 
  14035.  
  14036.  To work with an implementation definition,  first click Implementations on the 
  14037.  main menu (or press Alt-I). The pulldown menu that appears shows the options: 
  14038.  
  14039.       View 
  14040.       Add 
  14041.       Change 
  14042.       Delete 
  14043.  
  14044.  To add an implementation definition, click Add  on the pulldown menu (or press 
  14045.  A). This will bring up the Add Implementations  dialog box, where you can 
  14046.  define or change fields as necessary. The "Alias" field is the only blank 
  14047.  field for which a setting is mandatory. For this, you should enter a 
  14048.  "shorthand" name for conveniently referencing the registered server 
  14049.  implementation while using pregimpl or wregimpl; for example:  myServer 
  14050.  
  14051.  Except for the "Alias" setting, the remainder of the fields may be left either 
  14052.  blank or with the default settings that are provided (see "Registration steps 
  14053.  using 'regimpl'". for descriptions of the defaults). If you should clear a 
  14054.  field that originally contained a default, then when the implementation is 
  14055.  applied, pregimpl or wregimpl will still use the default setting [Note: The 
  14056.  implementation-ID ("Impl ID") field is also displayed. This is not an editable 
  14057.  field but is shown for information purposes.] 
  14058.  
  14059.  Once the definition is complete, click Apply  (or press Alt-A) to add the 
  14060.  definition. Click Discard  (or Alt-D) to discard a new definition. You can 
  14061.  select Exit (or Alt-X) at any time to exit the dialog box. (Message boxes or 
  14062.  confirmation windows typically appear after you make entries.) 
  14063.  
  14064.  To change an implementation definition,  click Change  from the 
  14065.  Implementations pulldown menu (or press C). In the Change Implementations 
  14066.  dialog box that appears, you can select the desired implementation by 
  14067.  scrolling though the list box on the left and highlighting your choice. Each 
  14068.  time an implementation is highlighted, details of its definition will appear 
  14069.  in the edit fields on the right. You can change any of the fields except the 
  14070.  implementation-ID. Once the changes are made, click Apply  (or Alt-A) or 
  14071.  Discard  (or Alt-D) as desired. Click Exit  (or Alt-X) to exit the dialog box. 
  14072.  
  14073.  The View  and Delete  implementations functions work similarly to the Change 
  14074.  Implementations function above. That is, you can highlight a selection in the 
  14075.  list box on the left, and details of its definition will appear in the edit 
  14076.  fields on the right. In the Delete Implementations dialog box, click Delete 
  14077.  Current Implementation  to delete a selected implementation definition. For 
  14078.  either function, click Exit  (or Alt-X) to exit the dialog box. 
  14079.  
  14080.  To work with class definitions,  first click Classes from the main menu (or 
  14081.  press Alt-C). This produces a pulldown menu with the options: 
  14082.  
  14083.       View 
  14084.       Add 
  14085.       Delete 
  14086.  
  14087.  To add classes, select Add  on the Classes pulldown menu (or press A) From the 
  14088.  resulting Add Classes  dialog box, you can select an implementation by 
  14089.  scrolling through the list box on the left and highlighting your choice. When 
  14090.  an implementation is selected, the classes associated with it will display in 
  14091.  the list box on the right. To add a new class name to the highlighted 
  14092.  implementation, enter the name in the edit field at the bottom right, and 
  14093.  click Add Class (or press Alt-A). The new class name will then appear in the 
  14094.  list box on the right. 
  14095.  
  14096.  The current class name will not be cleared from the edit field, so that more 
  14097.  implementations may be selected, if appropriate, and the same class can be 
  14098.  added to them. Or, you can enter another new class name and add it to the 
  14099.  implementation as described above. Exit  (or Alt-X) may be selected at any 
  14100.  time to exit the dialog box. 
  14101.  
  14102.  To view classes,select View  from the Classes pulldown menu (or press V). When 
  14103.  you highlight an implementation in the list box on the left, the classes 
  14104.  associated with the implementation will be shown in the list box on the right. 
  14105.  
  14106.  To switch key order, select the "Classes" radio button under "Display keyed 
  14107.  by". This causes all of the defined classes to appear in the list box on the 
  14108.  left. When you highlight a class name, all of the implementations associated 
  14109.  with that class will appear in the list box on the right. Exit  (or Alt-X) may 
  14110.  be selected at any time to exit the dialog box. 
  14111.  
  14112.  To delete classes,select Delete  from the Classes pulldown menu (or press D). 
  14113.  When you highlight an implementation in the list box on the left, the classes 
  14114.  associated with the implementation will be shown in the list box on the right. 
  14115.  You can then highlight a class and click Delete Class  (or Alt-D) to delete 
  14116.  the class from the highlighted implementation. A confirmation window will 
  14117.  appear next, which will also give you the option of deleting the class from 
  14118.  all  implementations. Exit  (or Alt-X) may be selected at any time to exit the 
  14119.  dialog box. 
  14120.  
  14121.  Important: Please note that any changes are saved internally in memory, but 
  14122.  are not  written to the database until you save the changes by clicking File 
  14123.  (or Alt-F) from the main menu and the n Save  (or S) from the resulting 
  14124.  pulldown menu. Conversely, you can abort all changes and reload the original 
  14125.  database by clicking File (Alt-F) and then Abort+Reload  (A). To exit the 
  14126.  pregimpl or wregimpl program, click File  (Alt-F) and then Exit  (X). 
  14127.  
  14128.  
  14129. ΓòÉΓòÉΓòÉ 7.16.5. Programmatic interface to the Implementation Repository ΓòÉΓòÉΓòÉ
  14130.  
  14131. The Implementation Repository can be accessed and updated dynamically using the 
  14132. programmatic interface provided by the ImplRepository class (defined in 
  14133. "implrep.idl"). The global variable SOMD_ImplRepObject is initialized by 
  14134. SOMD_Init to point to the ImplRepositor object. The following methods are 
  14135. defined on it: 
  14136.  
  14137.             void  add_impldef (in ImplementationDef impldef)
  14138.  
  14139.       Adds an implementation definition to the Implementation Repository. 
  14140.       (Note: The value of the "impl_id" attribute is ignored. A unique ImplId 
  14141.       will be generated for the newly added ImplementationDef.) 
  14142.  
  14143.             void  delete_impldef (in ImplId implid);
  14144.  
  14145.       Deletes an implementation definition from the Implementation Repository. 
  14146.  
  14147.             void update_impldef(in ImplementationDef impldef);
  14148.  
  14149.       Updates the implementation definition (defined by the "impl_id" of the 
  14150.       supplied implementationDef) in the Implementation Repository. 
  14151.  
  14152.             ImplementationDef find_impldef(in ImplId implid);
  14153.  
  14154.       Returns a server implementation definition given its ID. 
  14155.  
  14156.             ImplementationDef find_impldef_by_alias(in string alias_name);
  14157.  
  14158.       Returns a server implementation definition, given its user-friendly 
  14159.       alias. 
  14160.  
  14161.             sequence<ImplementationDef>  find_impldef_by_class
  14162.                                                         (in string classname)
  14163.  
  14164.       Returns a sequence of ImplementationDefs for those servers that have an 
  14165.       association with the specified class. Typically, a server is associated 
  14166.       with the classes it knows how to implement, by registering its known 
  14167.       classes via the add_class_to_impldef method. 
  14168.  
  14169.             ORBStatus  find_all_impldefs  (out sequence<ImplementationDef> outimpldefs);
  14170.  
  14171.       Retrieves all ImplementationDef objects in the Implementation Repository. 
  14172.  
  14173.  The following methods maintain an association between server implementations 
  14174.  and the names of the classes they implement. These methods effectively 
  14175.  maintain a mapping of <className, Implid>. 
  14176.  
  14177.             void add_class_to_impldef (in ImplId implid,
  14178.                                         in string classname);
  14179.  
  14180.       Associates a class, identified by name, with a server, identified by its 
  14181.       ImplId. This type of association is used to lookup server implementations 
  14182.       via the find_impldef_by_class method. 
  14183.  
  14184.             void  remove_class_from_impldef (
  14185.                                          in ImplId implid,
  14186.                                          in string classname);
  14187.  
  14188.       Removes the association of a particular class with a server. 
  14189.  
  14190.             void remove_class_from_all (
  14191.  
  14192.                                        in string classname);
  14193.  
  14194.       Removes the association of a particular class from all server 
  14195.       implementations in the Implementation Repository. 
  14196.  
  14197.             sequence<string>  find_classes_by_impldef
  14198.                                           (in ImplId implid);
  14199.  
  14200.       Returns a sequence of class names associated with a server. 
  14201.  
  14202.  With the ImplRepository programmatic interface, it is possible for an 
  14203.  application to define additional server implementations at run time. 
  14204.  
  14205.  
  14206. ΓòÉΓòÉΓòÉ 7.16.6. The 'dsom' server manager utility ΓòÉΓòÉΓòÉ
  14207.  
  14208. The dsom utility is a command-line utility program used to manage server 
  14209. processes. At present, server processes that can be managed are limited to 
  14210. those present in the Implementation Repository. The choice of Implementation 
  14211. Repository is determined by the environment variable SOMDDIR. The dsom utility 
  14212. can be used to start, restart, stop, list, enable, or disable server processes. 
  14213. Note: The dsom command requires somdd to be running on the machine in which the 
  14214. server process is (or will be) located. 
  14215.  
  14216. The syntax of the dsom command is as follows: 
  14217.  
  14218. dsom <cmd> { impl_alias1 [impl_alias2 ...] |-a}
  14219.  
  14220. where <cmd> can be any one of the terms:  start, restart, stop, list, disable, 
  14221. or enable. Each impl_alias is the server-alias name for a server process All 
  14222. forms of the command take one or more server-alias names, or a wild card option 
  14223. -a. The -a will be replaced with all of the server-alias names present in the 
  14224. Implementation Repository. 
  14225.  
  14226. For example, to start one or more server processes, the command takes the form: 
  14227.  
  14228. dsom start { impl_alias1 [impl_alias2 ...] | -a }
  14229.  
  14230. To restart one or more server processes: 
  14231.  
  14232. dsom restart { impl_alias1 [impl_alias2 ...] | -a }
  14233.  
  14234. Note:  A server registered (using regimpl) as "nonstoppable" cannot be 
  14235.        terminated using the "dsom stop" command or its programmatic equivalent, 
  14236.        SOMDServerMgr::somdShutdownServer. 
  14237.  
  14238.  To stop one or more server processes: 
  14239.  
  14240.   dsom stop { impl_alias1 [impl_alias2 ...] | -a }
  14241.  
  14242.  Note:  A server registered (using regimpl) as "nonstoppable" cannot be 
  14243.         terminated using the "dsom stop" command or its programmatic 
  14244.         equivalent, SOMDServerMgr::somdShutdownServer. 
  14245.  
  14246.  To list the status of one or more server processes: 
  14247.  
  14248.   dsom list { impl_alias1 [impl_alias2 ...] | -a }
  14249.  
  14250.  To prevent the server processes from starting, use the disable command. To 
  14251.  disable one or more server processes: 
  14252.  
  14253.   dsom disable { impl_alias1 [impl_alias2 ...] | -a }
  14254.  
  14255.  A previously disabled server process can be enabled by the enable command. To 
  14256.  enable one or more server processes: 
  14257.  
  14258.   dsom enable { impl_alias1 [impl_alias2 ...] | -a }
  14259.  
  14260.  
  14261. ΓòÉΓòÉΓòÉ 7.16.6.1. Interpretation of 'dsom' messages ΓòÉΓòÉΓòÉ
  14262.  
  14263. The messages generated by the dsom utility have a one-to-one mapping on the 
  14264. DSOM error codes. Knowing this mapping will aid in a better understanding of 
  14265. the dsom return messages. The following six messages are mapped onto the DSOM 
  14266. error code of 0 (success): 
  14267.  
  14268.  'dsom' cmd          Message 
  14269.  
  14270.  start               **Started server process** 
  14271.  
  14272.  restart             **Restarted server process** 
  14273.  
  14274.  list                **Server process currently running** 
  14275.  
  14276.  stop                **Stopped server process** 
  14277.  
  14278.  disable             **Successfully disabled server** 
  14279.  
  14280.  enable              **Successfully enabled server** 
  14281.  
  14282.  The messages generated by the dsom utility commands are mapped onto DSOM error 
  14283.  codes, as follows: 
  14284.  
  14285.   ΓöîΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÉ
  14286.   ΓöéDSOM ERROR CODE               ΓöéMESSAGE                                      Γöé
  14287.   Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  14288.   ΓöéSOMDERROR_ServerNotFound      Γöé**Server process not running**               Γöé
  14289.   Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  14290.   ΓöéSOMDERROR_NotProcessOwner     Γöé**Cannot stop server; Not process owner**    Γöé
  14291.   Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  14292.   ΓöéSOMDERROR_NoSocketsClass      Γöé**Cannot find Sockets class**                Γöé
  14293.   Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  14294.   ΓöéSOMDERROR_NoRemoteComm        Γöé**Not enabled for Workgroup**                Γöé
  14295.   Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  14296.   ΓöéSOMDERROR_CommTimeOut         Γöé**Client timed out**                         Γöé
  14297.   Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  14298.   ΓöéSOMDERROR_SendError           Γöé**Send Error**                               Γöé
  14299.   Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  14300.   ΓöéSOMDERROR_SocketSend          Γöé**Send Error**                               Γöé
  14301.   Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  14302.   ΓöéSOMDERROR_ServerInactive      Γöé**Server activation pending**                Γöé
  14303.   Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  14304.   ΓöéSOMDERROR_NoSOMDInit          Γöé**Unable to create global LocSerObject**     Γöé
  14305.   Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  14306.   ΓöéSOMDERROR_UnknownError        Γöé**Command not supported by daemon*           Γöé
  14307.   Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  14308.   ΓöéSOMDERROR_ServerDisabled      Γöé**Server process is currently disabled**     Γöé
  14309.   Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  14310.   ΓöéSOMDERROR_CouldNotStartProcessΓöé**Server process cannot be started**         Γöé
  14311.   Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  14312.   ΓöéSOMDERROR_ServerToBeDeleted   Γöé**Current server process marked for deletion;Γöé
  14313.   Γöé                              Γöétry again**                                  Γöé
  14314.   Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  14315.   ΓöéAny other error               Γöé**Request unsuccessful; Unknown error**      Γöé
  14316.   ΓööΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÿ
  14317.  
  14318.  In addition, if the impl_alias specified with any dsom utility command is not 
  14319.  present in the Implementation Repository, DSOM will generate the message: 
  14320.  **Server alias not found in Implementation Repository**. 
  14321.  
  14322.  Programmatic interface to manage server processes 
  14323.  
  14324.  Server processes can also be managed by using the programmatic interface 
  14325.  provided by the SOMDServerMgr class. For descriptions of the SOMDServerMgr 
  14326.  class and its corresponding methods, see the DSOM section of the SOMobjects 
  14327.  Developer Toolkit Programmers Reference Manual. 
  14328.  
  14329.  
  14330. ΓòÉΓòÉΓòÉ 7.16.7. Verifying the DSOM environment with 'somdchk' ΓòÉΓòÉΓòÉ
  14331.  
  14332. The somdchk program evaluates the environment to verify whether DSOM can 
  14333. operate correctly. As described in the preceding topic s of Sections 6.5 
  14334. "Implementing Classes" and 6.6 "Configuring DSOM Applications," to  operate 
  14335. correctly DSOM must be able to find the appropriate libraries (DLLs), the 
  14336. Interface Repository, and the Implementation Repository. The settings of 
  14337. various environment variables help DSOM find the path to the libraries and 
  14338. repositories. 
  14339.  
  14340. The somdchk program generates messages that evaluate the DSOM environment. It 
  14341. determines whether the necessary SOM DLLs can be located, whether DSOM is 
  14342. enabled for workgroup (cross-machine) communication, whether Interface and 
  14343. Implementation Repositories can be located, and it displays the settings of 
  14344. important environment variables. In its "verbose" mode, somdchk gives the 
  14345. default settings for DSOM environment variables and explains how DSOM uses 
  14346. them. 
  14347.  
  14348. On AIX or OS/2, the program is invoked from the command line using the syntax 
  14349. given below. The optional verbose setting can be turned on by including the -v 
  14350. option with the command: 
  14351.  
  14352. somdchk  [-v]
  14353.  
  14354. On Windows, the somdchk program can be invoked by double clicking on the 
  14355. SOMDCHK icon. The resulting messages will appear in the message window. 
  14356.  
  14357. The following example shows sample output from the somdchk -v  command on AIX. 
  14358. Output on other platforms would look similar. 
  14359.  
  14360.      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
  14361.  
  14362. SOMBASE = /usr/lpp/som
  14363. SOMBASE should not be set to the base directory of the SOMObjects Toolkit Enablers.
  14364.  
  14365. Searching for important DLLs.....
  14366. /usr/lpp/som/lib/som.dll found.
  14367. /usr/lpp/som/lib/somd.dll found.
  14368. /usr/lpp/som/lib/soms.dll found.
  14369. /usr/lpp/som/lib/somst.dll found.
  14370.  
  14371. /usr/lpp/som/lib/somd.dll IS Workgroup Enabled.
  14372. Workgroup Enabled DLL permits inter-machine communication.
  14373.  
  14374. SOMSOCKETS  = TCPIPSockets
  14375. SOMSOCKETS must be set. Valid settings are:
  14376.    TCPIPSockets for TCPIP.
  14377.    IPXSockets for NetWare.
  14378.  
  14379. SOMDDIR    = /u/raviv/impl_rep/
  14380. Valid Implementation Repository found in /u/raviv/impl_rep/
  14381. SOMDDIR may be set to a valid directory in which the Implementation Repository
  14382. resides.
  14383.    Default is /usr/lpp/som/etc/dsom
  14384.  
  14385.  
  14386. SOMIR    = /u/raviv/raviv.ir
  14387. SOMIR may be set to a list of file names which together form the Interface
  14388. Repository.
  14389.    Default is ./som.ir
  14390. /u/raviv/raviv.ir found.
  14391.  
  14392. SOMDPORT   = 3001
  14393. SOMDPORT may be set to a 'well-known port'. Default value is 9393.
  14394.  
  14395. SOMDTIMEOUT  = (null).
  14396. SOMDTIMEOUT may be set to the number of seconds to timeout.
  14397.    Default value is 600.
  14398.  
  14399. SOMDDEBUG    = 2
  14400. SOMDDEBUG may be set to 1 to enable runtime error messages.
  14401.    Default value is 0.
  14402.  
  14403. SOMDMESSAGELOG    = (null).
  14404. SOMDMESSAGELOG may be set to the name of a file where messages may be logged.
  14405.    Default is stdout.
  14406.  
  14407.  
  14408. ΓòÉΓòÉΓòÉ 7.16.8. Freeing interprocess communication resources on AIX ΓòÉΓòÉΓòÉ
  14409.  
  14410. DSOM allocates interprocess communication (IPC) resources during execution. 
  14411. Normally, these resources are freed and returned to the system when SOMD_Uninit 
  14412. is called. On AIX, however, if a DSOM process terminates without calling 
  14413. SOMD_Uninit, the resources often remain allocated. 
  14414.  
  14415. DSOM offers two solutions for this problem. Either the somdclean or cleanipc 
  14416. command can be used, as you prefer. 
  14417.  
  14418.  
  14419. ΓòÉΓòÉΓòÉ 7.16.8.1. Using 'somdclean' ΓòÉΓòÉΓòÉ
  14420.  
  14421. As the first alternative, a DSOM kernel extension can be set up, which 
  14422. automatically frees the system resources used by DSOM when a process exits. The 
  14423. somdclean command is issued to load, unload or query a DSOM kernel extension, 
  14424. as follows: 
  14425.  
  14426.  somdclean -l                       Loads the kernel extension 
  14427.  somdclean -u                       Unloads the kernel extension 
  14428.  somdclean                          Queries the current state of the kernel 
  14429.                                     extension 
  14430.  
  14431.  The somdclean command can only be executed by a privileged user. Hence, you 
  14432.  must execute this command as "root". 
  14433.  
  14434.  The kernel extension is only aware of DSOM processes started after it has been 
  14435.  loaded. That is, if a DSOM process is started before the kernel extension is 
  14436.  loaded, the resources associated with the existing process will not be freed. 
  14437.  
  14438.  Before you unload the kernel extension, verify that there are no active DSOM 
  14439.  processes. If the kernel extension is unloaded while DSOM is using it, the 
  14440.  system will crash. 
  14441.  
  14442.  
  14443. ΓòÉΓòÉΓòÉ 7.16.8.2. Using 'cleanipc' ΓòÉΓòÉΓòÉ
  14444.  
  14445. As another alternative, the cleanipc script can be used to free the IPC 
  14446. resources allocated to a particular AIX user, as follows: 
  14447.  
  14448.  cleanipc [ userId ]                Frees resources for the specified user 
  14449.  
  14450.  If the userId parameter is not specified, cleanipc by default uses the 
  14451.  environment variable USER. 
  14452.  
  14453.  The cleanipc script should be run only after all DSOM processes have ended. A 
  14454.  limitation of cleanipc is that it is not able to distinguish between resources 
  14455.  that were created by DSOM and resources created by other products. As a 
  14456.  result, cleanipc may affect other applications. 
  14457.  
  14458.  
  14459. ΓòÉΓòÉΓòÉ 7.17. Running DSOM Applications ΓòÉΓòÉΓòÉ
  14460.  
  14461. Prior to starting the DSOM processes, the DSOM executables should be installed 
  14462. and the DSOM environment variables should be set appropriately, as discussed in 
  14463. the earlier section, "Configuring DSOM Applications." 
  14464.  
  14465.  
  14466. ΓòÉΓòÉΓòÉ 7.17.1. Running the DSOM daemon (somdd) ΓòÉΓòÉΓòÉ
  14467.  
  14468. To run a DSOM application, the DSOM daemon, somdd, must be started: 
  14469.  
  14470.      On AIX or OS/2, the daemon can be started manually from the command line, 
  14471.       or could be started automatically from a start-up script run at boot 
  14472.       time. It may be run in the background with the commands somdd& on AIX, 
  14473.       and start somdd on OS/2. (Thesomdd command has the following syntax: 
  14474.  
  14475.             somdd [-q]
  14476.  
  14477.       where the optional -q flag signifies "quiet" mode.  By default, somdd 
  14478.       will produce a" ready" message when the DSOM daemon is ready to process 
  14479.       requests, and it will produce diagnostic messages as errors are 
  14480.       encountered if the SOMDDEBUG environment variable is set to 1. In quiet 
  14481.       mode, however, the "ready" message will not appear, and diagnostic 
  14482.       messages will not appear even if SOMDEBUG is set. Alternatively, if the 
  14483.       SOMDMESSAGELOG environment variable is set, diagnostic error messages 
  14484.       will be sent directly to the specified message log file, regardless of 
  14485.       whether the -q flag is specified. 
  14486.  
  14487.      On Windows, the daemon can be started with the DSOM Daemon icon in the 
  14488.       SOM icon group or started in Windows from the Run option of the file 
  14489.       menu.  The DSOM Daemon icon will change colors to indicate that the 
  14490.       daemon is ready, after which client and server programs can be started. 
  14491.  
  14492.  The somdd daemon is responsible for "binding" a client process to a server 
  14493.  process and will activate the desired server if necessary. The binding 
  14494.  procedure is such that the client will consult the Implementation Repository 
  14495.  to find out which machine contains a desired server, and will then contact the 
  14496.  DSOM daemon on the server's machine to retrieve the server's communications 
  14497.  address (a port). Servers are activated dynamically as separate processes. 
  14498.  
  14499.  
  14500. ΓòÉΓòÉΓòÉ 7.17.2. Running DSOM servers ΓòÉΓòÉΓòÉ
  14501.  
  14502. Once the somdd daemon is running, application programs can be started. If the 
  14503. application uses the generic SOM server, somdsvr, it can be started either from 
  14504. the command line or automatically upon demand. When starting somdsvr from the 
  14505. command line, the server's implementation ID or alias must be supplied as an 
  14506. argument. The command syntax for starting a generic SOM server is: 
  14507.  
  14508.    somdsvr  [ impl_id  | -a alias ]
  14509.  
  14510. For example, the command 
  14511.  
  14512. $   somdsvr  2ad2688fb-00389c00-7f-00-10005ac900d8
  14513.  
  14514. would start a somdsvr for an implementation with the specified ID. Likewise, 
  14515. the command 
  14516.  
  14517. $   somdsvr  -a  myServer
  14518.  
  14519. would start a somdsvr that represents an implementation of "myServer". 
  14520.  
  14521. Servers can also be started from the command line using the "dsom start" 
  14522. command: 
  14523.  
  14524. dsom start {impl_alias1 [impl_alias2 ...] | -a}
  14525.  
  14526. or programmatically using the somdStartServer method of the SOMDServerMgr 
  14527. class. See the section entitled "The 'dsom' server manager utility" for more 
  14528. information on the dsom command-line utility. See the DSOM section of the 
  14529. SOMobjects Developer Toolkit Programmers Reference manual for a description of 
  14530. the SOMDServerMgr class and its methods. 
  14531.  
  14532.  
  14533. ΓòÉΓòÉΓòÉ 7.18. DSOM as a CORBA-compliant Object Request Broker ΓòÉΓòÉΓòÉ
  14534.  
  14535. The Object Management Group (OMG) consortium defines the notion of an Object 
  14536. Request Broker (ORB) that supports access to remote objects in a distributed 
  14537. environment. Thus, Distributed SOM is an ORB. SOM and DSOM together comply with 
  14538. the OMG's specification of the Common Object Request Broker Architecture 
  14539. (CORBA). 
  14540.  
  14541. Since the interfaces of SOM and DSOM are largely determined by the CORBA 
  14542. specification, the CORBA components and interfaces are highlighted in this 
  14543. section. 
  14544.  
  14545. The CORBA specification defines the components and interfaces that must be 
  14546. present in an ORB, including the: 
  14547.  
  14548.      Interface Definition Language (IDL) for defining classes (discussed in 
  14549.       Chapter 4, "SOM IDL and the SOM Compiler"). 
  14550.  
  14551.      C usage bindings (procedure-call formats) for invoking methods on remote 
  14552.       objects, 
  14553.  
  14554.      Dynamic Invocation Interface and an Interface Repository, which support 
  14555.       the construction of requests (method calls) at run time (for example, for 
  14556.       interactive desktop applications), and 
  14557.  
  14558.      Object Request Broker run-time programming interfaces. 
  14559.  
  14560.  SOM and DSOM were developed to comply with these specifications (with only 
  14561.  minor extensions to take advantage of SOM services). Although the capabilities 
  14562.  of SOM are integral to the implementation of DSOM, the application programmer 
  14563.  need not be aware of SOM as the implementation technology for the ORB. 
  14564.  
  14565.  This section assumes some familiarity with The Common Object Request Broker: 
  14566.  Architecture and Specification, Revision 1.1 (also referred to as "CORBA 
  14567.  1.1"). The specification is published jointly by the Object Management Group 
  14568.  and x/Open. The mapping of some CORBA 1.1 terms and concepts to D SOM terms 
  14569.  and concepts is described in the remainder of this section. 
  14570.  
  14571.  
  14572. ΓòÉΓòÉΓòÉ 7.18.1. Mapping OMG CORBA terminology onto DSOM ΓòÉΓòÉΓòÉ
  14573.  
  14574. This section discusses how various CORBA concepts and terms are defined in 
  14575. terms of DSOM's implementation of the CORBA 1.1 standard. 
  14576.  
  14577.  
  14578. ΓòÉΓòÉΓòÉ 7.18.1.1. Object Request Broker run-time interfaces ΓòÉΓòÉΓòÉ
  14579.  
  14580. In the previous sections, the SOMDObjectMgr and SOMDServer classes were 
  14581. introduced. These are classes defined by DSOM to provide basic support in 
  14582. managing objects in a distributed application. These classes are built upon 
  14583. Object Request Broker interfaces defined  by  CORBA for building and 
  14584. dispatching requests on objects. The ORB interfaces, SOMDObjectMgr and 
  14585. SOMDServer, together provide the support for implementing distributed 
  14586. applications in DSOM. 
  14587.  
  14588. CORBA 1.1 defines the interfaces to the ORB components in IDL. In DSOM, the ORB 
  14589. components are implemented as SOM classes whose interfaces are expressed using 
  14590. the same CORBA 1.1 IDL. Thus, an application can make calls to the DSOM run 
  14591. time using the SOM language bindings of its choice. 
  14592.  
  14593. Interfaces for the following ORB run-time components are defined in CORBA 1.1, 
  14594. and are implemented in DSOM. They are introduced briefly here, and discussed in 
  14595. more detail throughout this chapter. (See the SOMobjects Developer Toolkit: 
  14596. Programmers Reference Manual for the complete interface definitions.) 
  14597.  
  14598.  Object               The Object interface defines operations on an "object 
  14599.                       reference", which is the information needed to specify an 
  14600.                       object within the ORB. 
  14601.  
  14602.                       In DSOM, the class SOMDObject implements the CORBA 1.1 
  14603.                       Object interface. (The"SOMD" prefix was added to 
  14604.                       distinguish this class from SOMObject.) The subclass 
  14605.                       SOMDClientProxy extends SOMDObject with support for proxy 
  14606.                       objects. 
  14607.  
  14608.  ORB                  (Object Request Broker) The ORB interface defines utility 
  14609.                       routines for building requests and saving references to 
  14610.                       distributed objects. The global variable SOMD_ORBObject 
  14611.                       is initialized by SOMD_Init and provides the reference to 
  14612.                       the ORB object. 
  14613.  
  14614.  ImplementationDef    An ImplementationDef object is used to describe an 
  14615.                       object's implementation. Typically, the ImplementationDef 
  14616.                       describes the program that implements an object's server, 
  14617.                       how the program is activated, and so on. 
  14618.  
  14619.                       (CORBA 1.1 introduces ImplementationDef as the name of 
  14620.                       the interface, but leaves the remainder of the IDL 
  14621.                       specification to the particular ORB. DSOM defines an 
  14622.                       interface for ImplementationDef.) 
  14623.  
  14624.                       ImplementationDef objects are stored in the 
  14625.                       Implementation Repository (defined in DSOM by the 
  14626.                       ImplRepository class). 
  14627.  
  14628.  InterfaceDef         An InterfaceDef object is used to describe an IDL 
  14629.                       interface in a manner that can be queried and manipulated 
  14630.                       at run time when building requests dynamically, for 
  14631.                       example. 
  14632.  
  14633.                       InterfaceDef objects are stored in the Interface 
  14634.                       Repository (described fully in Chapter 7, "The Interface 
  14635.                       Repository Framework"). 
  14636.  
  14637.  Request              A Request object represents a specific request on an 
  14638.                       object, constructed at run-time. The Request object 
  14639.                       contains the target object reference, operation (method) 
  14640.                       name, a list of input and output arguments. A Request can 
  14641.                       be invoked synchronously (wait for the response), 
  14642.                       asynchronously (initiate the call, and later, get the 
  14643.                       response), or as a "oneway" call (no response expected). 
  14644.  
  14645.  NVList               An NVList is a list of NamedValue structures, used 
  14646.                       primarily in building Request objects. A NamedValue 
  14647.                       structure consists of a name, typed value, and some flags 
  14648.                       indicating how to interpret the value, how to 
  14649.                       allocate/free the value's memory, and so on. 
  14650.  
  14651.  Context              A Context object contains a list of "properties" that 
  14652.                       represent information about an application process's 
  14653.                       environment. Each Context property consists of a 
  14654.                       <name,string_value> pair,and is used by application 
  14655.                       programs or methods much like the "environment variables" 
  14656.                       commonly found in operating systems like AIX and OS/2 and 
  14657.                       Windows. IDL method interfaces can explicitly list which 
  14658.                       properties are queried by a method, and the ORB will pass 
  14659.                       those property values to a remote target object when 
  14660.                       making a request. 
  14661.  
  14662.  Principal            A Principal object identifies the principal ("user") on 
  14663.                       whose behalf a request is being performed. 
  14664.  
  14665.                       (CORBA 1.1 introduces the name of the interface, 
  14666.                       Principal, but leaves the remainder of the IDL 
  14667.                       specification to the particular ORB. DSOM defines an 
  14668.                       interface for Principal.) 
  14669.  
  14670.  BOA                  (Basic Object Adapter) An Object Adapter provides the 
  14671.                       primary interface between an implementation and the ORB 
  14672.                       "core". An ORB may have a number of Object Adapters, with 
  14673.                       interfaces that are appropriate for specific kinds of 
  14674.                       objects. 
  14675.  
  14676.  The Basic Object Adapter is intended to be a general-purpose Object Adapter 
  14677.  available on all CORBA-compliant Object Request Brokers. The BOA interface 
  14678.  provides support for generation of object references, identification of the 
  14679.  principal making a call, activation and deactivation of objects and 
  14680.  implementations, and method invocation on objects. 
  14681.  
  14682.  In DSOM, BOA is defined as an abstract class. The SOMOA (SOM Object Adapter) 
  14683.  class, derived from BOA, is DSOM's primary Object Adapter implementation. The 
  14684.  SOMOA interface extends the BOA interface with several of its own methods that 
  14685.  are not defined by CORBA 1.1. 
  14686.  
  14687.  
  14688. ΓòÉΓòÉΓòÉ 7.18.1.2. Object references and proxy objects ΓòÉΓòÉΓòÉ
  14689.  
  14690. CORBA 1.1 defines the notion of an object reference, which is the information 
  14691. needed to specify an object in the ORB. An object is defined by its 
  14692. ImplementationDef, InterfaceDef, and application-specific "reference data" used 
  14693. to identify or describe the object. An object reference is used as a handle to 
  14694. a remote object in method calls. When a server wants to export a reference to 
  14695. an object it implements, it supplies the object's ImplementationDef, 
  14696. InterfaceDef, and reference data to the Object Adapter, which returns the 
  14697. reference. 
  14698.  
  14699. The structure of an object reference is opaque to the application, leaving its 
  14700. representation up to the ORB. 
  14701.  
  14702. In DSOM, an object reference is represented as an object that can simply be 
  14703. used to identify the object on that server. The DSOM class that implements 
  14704. simple object references is called SOMDObject (corresponding to Object in CORBA 
  14705. 1.1.) However, in a client's address space, DSOM represents the remote object 
  14706. with a proxy object in order to allow the client to invoke methods on the 
  14707. target object as if it were local. When an object reference is passed from a 
  14708. server to a client, DSOM dynamically and automatically creates a proxy in the 
  14709. client for the remote object. Proxies are specialized forms of SOMDObject; 
  14710. accordingly, the base proxy class in DSOM SOMDClientProxy, is derived from 
  14711. SOMDObject. 
  14712.  
  14713. In order to create a proxy object, DSOM must first build a proxy class. It does 
  14714. so automatically using SOM facilities for building classes at run time. The 
  14715. proxy class is constructed using multiple inheritance: the proxy object 
  14716. functionality is inherited from SOMDClientProxy, while just the interface of 
  14717. the target class is inherited. 
  14718.  
  14719. In the newly derived proxy class, DSOM overrides each method inherited from the 
  14720. target class with a "remote dispatch" method that forwards an invocation 
  14721. request to the remote object. Consequently, the proxy object provides location 
  14722. transparency, and the client code invokes operations (methods) on the remote 
  14723. object using the same language bindings as if it were a local target object. 
  14724.  
  14725. For example, recall the "Stack" class used in the tutorial example given 
  14726. earlier. When a server returns a reference to a remote "Stack" object to the 
  14727. client, DSOM builds a "Stack_ _Proxy" class (note two underscores in the name), 
  14728. derived from SOMDClientProxy and "Stack", and creates a proxy object from that 
  14729. class.  When the client invokes the "push" method on the proxy, 
  14730.  
  14731.  
  14732. _push(stk, &ev, 100);
  14733.  
  14734. the method is redispatched using the remote-dispatch method of the 
  14735. SOMDClientProxy class, and the method is forwarded to the target object. 
  14736.  
  14737. CORBA defines several special operations on object references that operate on 
  14738. the local references (proxies) themselves, rather than on the remote objects. 
  14739. These operations are defined by the classes SOMOA (SOM Object Adapter), 
  14740. SOMDObject (which is DSOM's implementation of CORBA's Object "pseudo-class" and 
  14741. ORB (Object Request Broker class). Some of these operations are listed below, 
  14742. expressed in terms of their IDL definitions. 
  14743.  
  14744. SOMOA methods (inherited from BOA): 
  14745.  
  14746.  
  14747.             sequence <octet,1024> ReferenceData;
  14748.             SOMDObject  create (in ReferenceData id, in InterfaceDef intf
  14749.                                 in ImplementationDef impl);
  14750.  
  14751.  Creates and returns an object reference. 
  14752.  
  14753.  SOMDObject methods: 
  14754.  
  14755.             SOMDObject  duplicate ( );
  14756.  
  14757.       Creates and returns a duplicate object reference. 
  14758.  
  14759.             void  release ( );
  14760.  
  14761.       Destroys an object reference. 
  14762.  
  14763.             boolean  is_nil ( );
  14764.  
  14765.       Tests to see if the object reference is NULL. 
  14766.  
  14767.  ORB methods: 
  14768.  
  14769.             string  object_to_string ( SOMDObject obj );
  14770.  
  14771.       Converts an object reference to a (storable) string form. 
  14772.  
  14773.             SOMDObject  string_to_object ( string str );
  14774.  
  14775.       Converts a string form back to the original object reference. 
  14776.  
  14777.  
  14778. ΓòÉΓòÉΓòÉ 7.18.1.3. Creation of remote objects ΓòÉΓòÉΓòÉ
  14779.  
  14780. The OMG has standardized an "object lifecycle service," built on top of the 
  14781. ORB, for creating and destroying remote objects.  Currently, DSOM provides its 
  14782. own interface for creating and destroying objects (see "Basic Client 
  14783. Programming"), but a future release may provide an OMG-compliant lifecycle 
  14784. service as well. 
  14785.  
  14786.  
  14787. ΓòÉΓòÉΓòÉ 7.18.1.4. Interface definition language ΓòÉΓòÉΓòÉ
  14788.  
  14789. The CORBA specification defines an Interface Definition Language, IDL, for 
  14790. defining object interfaces. The SOM Compiler compiles standard IDL interface 
  14791. specifications, but it also allows the class implementer to include 
  14792. implementation information that will be used in the implementation bindings for 
  14793. a particular language. 
  14794.  
  14795. Note:  Before IDL, SOM (version 1.0) had its own Object Interface Definition 
  14796.        Language (OIDL). SOM classes specified using OIDL must be converted to 
  14797.        IDL before they can be used with DSOM. The SOMobjects Developer Toolkit 
  14798.        provides a migration tool for this purpose. 
  14799.  
  14800.  
  14801. ΓòÉΓòÉΓòÉ 7.18.1.5. C language mapping ΓòÉΓòÉΓòÉ
  14802.  
  14803. The CORBA specification defines the mapping of method interface definitions to 
  14804. C language procedure prototypes, hence SOM defines the same mapping. This 
  14805. mapping requires passing a reference to the target object and a reference to an 
  14806. implementation-specific Environment structure as the first and second 
  14807. parameters, respectively, in any method call. 
  14808.  
  14809. The Environment structure is primarily used for passing error information from 
  14810. a method back to its caller. See also the topic "Exceptions and Error Handling" 
  14811. in Chapter 3, "Using SOM Classes in Client Programs," for a description of how 
  14812. to "get" and "set" error information in the Environment structure. 
  14813.  
  14814.  
  14815. ΓòÉΓòÉΓòÉ 7.18.1.6. Dynamic Invocation Interface (DII) ΓòÉΓòÉΓòÉ
  14816.  
  14817. The CORBA specification defines a Dynamic Invocation Interface (DII) that can 
  14818. be used to dynamically build requests on remote objects. This interface is 
  14819. described in section 6 (page 105) of the CORBA 1.1 document, and is implemented 
  14820. in DSOM. The DSOM implementation of the DII is described later in this chapter, 
  14821. in the topic entitled "Dynamic Invocation Interface" under Section 6.9 
  14822. "Advanced topics." Note that, in DSOM, somDispatch is overridden so that method 
  14823. invocations on proxy objects are forwarded to the remote target object. SOM 
  14824. applications can use the SOM somDispatch method for dynamic method calls 
  14825. whether the object is local or remote. 
  14826.  
  14827.  
  14828. ΓòÉΓòÉΓòÉ 7.18.1.7. Implementations and servers ΓòÉΓòÉΓòÉ
  14829.  
  14830. The CORBA specification defines the term implementation as the code that 
  14831. implements an object. The implementation usually consists of a program and 
  14832. class libraries. 
  14833.  
  14834. Servers are processes that execute object implementations. CORBA 1.1 defines 
  14835. four activation policies for server implementations: shared, unshared, 
  14836. server-per-method, and persistent, as follows. 
  14837.  
  14838.      A shared server implements multiple objects (of arbitrary classes the 
  14839.       same time, and allows multiple methods to be invoked at the same time. 
  14840.  
  14841.      An unshared  server, conversely, implements only a single object and 
  14842.       handles one request at a time. 
  14843.  
  14844.      The server-per-method  policy requires a separate process to be created 
  14845.       for each request on an object and, usually, a separate program implements 
  14846.       each method. 
  14847.  
  14848.       Under the shared, unshared, and server-per-method activation policies, 
  14849.       servers are activated automatically (on demand). 
  14850.  
  14851.      A persistent  server, by contrast, is a shared server that is activated 
  14852.       "by hand" (for example, from the command shell or from a startup script), 
  14853.       vs. being activated automatically when the first method is dispatched to 
  14854.       it. 
  14855.  
  14856.  The term "persistent server" refers to the relative lifetime of the server: it 
  14857.  is "always running" when DSOM is running. (CORBA implies that persistent 
  14858.  servers are usually started at ORB boot time.) It should not be assumed, 
  14859.  however, that a "persistent" server necessarily implements persistent objects 
  14860.  (that persist between ORB reboots). 
  14861.  
  14862.  In DSOM, specific process models are implemented by the server program. That 
  14863.  is, DSOM simply starts a specified program when a client attempts to connect 
  14864.  to a server. The four CORBA activation policies, or any other policies, can be 
  14865.  implemented by the application as necessary. For example, 
  14866.  
  14867.      an object that requires a server-per-method implementation could itself 
  14868.       spawn a process at the beginning of each method execution. Alternatively, 
  14869.       the server object in the "main" server can spawn a process before each 
  14870.       method dispatch. 
  14871.  
  14872.      a dedicated server could be registered for each object that requires an 
  14873.       unshared server implementation (separate process). This may be done 
  14874.       dynamically (see the topic "Programmatic interface to the Implementation 
  14875.       Repository" earlier in this chapter). 
  14876.  
  14877.  An ImplementationDef object, as defined by the CORBA specification, describes 
  14878.  the characteristics of a particular implementation. In DSOM, an 
  14879.  ImplementationDef identifies an implementation's unique ID, the program name, 
  14880.  its location, and so forth. The ImplementationDef objects are stored in an 
  14881.  Implementation Repository, which is represented in DSOM by an ImplRepository 
  14882.  object. 
  14883.  
  14884.  A CORBA-compliant ORB must provide the mechanisms for a server program to 
  14885.  register itself with the ORB. To "register itself with the ORB" simply means 
  14886.  to tell the ORB enough information about the server process so that the ORB 
  14887.  will be able to locate, activate, deactivate, and dispatch methods to the 
  14888.  server process. DSOM supports these mechanisms, so that server programs 
  14889.  written in arbitrary languages can be used with DSOM. (See also the next 
  14890.  topic, "Object Adapters.") 
  14891.  
  14892.  In addition to the generic registration mechanisms provided by all 
  14893.  CORBA-compliant ORBs, DSOM provides extra support for using SOM-class DLLs. 
  14894.  DSOM provides a generic server  program that automatically registers itself 
  14895.  with DSOM, loads SOM-class DLLs on demand, and dispatches incoming requests on 
  14896.  SOM objects. Thus, by using the generic server program (when appropriate), a 
  14897.  user may be able to avoid writing any server program code. 
  14898.  
  14899.  
  14900. ΓòÉΓòÉΓòÉ 7.18.1.8. Object Adapters ΓòÉΓòÉΓòÉ
  14901.  
  14902. An Object Adapter (OA) provides the mechanisms that a server process uses to 
  14903. interact with DSOM, and vice versa. That is, an Object Adapter is responsible 
  14904. for server activation and deactivation, dispatching methods, activation and 
  14905. deactivation of individual objects, and providing the interface for 
  14906. authentication of the principal making a call. 
  14907.  
  14908. DSOM defines a Basic Object Adapter (BOA) interface, described in the CORBA 
  14909. specification, as an abstract class (a class having no implementation, only an 
  14910. interface specification). The BOA interface represents generic Object Adapter 
  14911. methods that a server written in an arbitrary language can use to register 
  14912. itself and its objects with the ORB. Because it is an abstract class having no 
  14913. implementation, however, the BOA class should not be directly instantiated. 
  14914.  
  14915. DSOM provides a SOM Object Adapter, SOMOA, derived from the BOA interface, that 
  14916. uses SOM Compiler and run-time support to accomplish dispatching of methods 
  14917. (that is, accepting messages, turning them into method invocations, and routing 
  14918. the invocations to the target object in the server process). SOMOA can be used 
  14919. to dispatch methods on either SOM or non-SOM object implementations, as 
  14920. described in the sections "Implementing Classes" and "Basic Server 
  14921. Programming." It is possible to use non-SOM based implementations with SOMOA, 
  14922. and often there is no additional programming required to use implementations 
  14923. (class libraries) already developed using SOM. 
  14924.  
  14925. The SOMOA works in conjunction with the application-defined server object to 
  14926. map between objects and object references, and to dispatch methods on objects. 
  14927. By partitioning out these mapping and dispatching functions into the server 
  14928. object, the application can more easily customize them, without having to build 
  14929. object adapter subclasses. 
  14930.  
  14931. SOMOA introduces two methods that handle execution of requests received by the 
  14932. server: 
  14933.  
  14934.       execute_request_loop 
  14935.  
  14936.       execute_next_request 
  14937.  
  14938.  Typically, execute_request_loop is used to receive and execute requests, 
  14939.  continuously, in the server's main thread. The execute_next_request method 
  14940.  allows a single request to be executed. Both methods have a non-blocking 
  14941.  option: when there are no messages pending, the method call will return 
  14942.  instead of wait. 
  14943.  
  14944.  On OS/2, if the server implementation has been registered as "multi-threaded" 
  14945.  (via an IMPLDEF_MULTI_THREAD flag in the ImplementationDef), SOMOA will 
  14946.  automatically run each request in a separate thread. If the "multi-thread" 
  14947.  flag is not set, the server implementation can still choose to manage its own 
  14948.  threads. 
  14949.  
  14950.  The generic server program provided by DSOM (described in the preceding topic) 
  14951.  uses execute_request_loop to receive and execute requests on SOM objects. 
  14952.  
  14953.  
  14954. ΓòÉΓòÉΓòÉ 7.18.1.9. Extensions and limitations ΓòÉΓòÉΓòÉ
  14955.  
  14956. The DSOM implementation has the following extensions and limitations in its 
  14957. implementation of the CORBA specification: 
  14958.  
  14959.      As just described, the current release of DSOM supports a simple server 
  14960.       activation policy, which is equivalent to the "shared" and "persistent" 
  14961.       policies defined by CORBA. DSOM does not explicitly support the 
  14962.       "unshared" or "server-per-method" server activation policies. Policies 
  14963.       other than the basic activation scheme must be implemented by the 
  14964.       application. 
  14965.  
  14966.      DSOM provides null implementations for the object_is_ready or 
  14967.       deactivate_obj methods, defined by the BOA interface for the unshared 
  14968.       server activation policy. 
  14969.  
  14970.      DSOM does not support the change_implementation method, defined by the 
  14971.       BOAinterface to allow an application to change the implementation 
  14972.       definition associated with an object. In DSOM, the ImplementationDef 
  14973.       identifies the server which implements an object.  In these terms, 
  14974.       changing an object's ImplementationDef would result in a change in the 
  14975.       object's server ID. Any existing object references that have the old 
  14976.       server ID would be rendered invalid. 
  14977.  
  14978.       It is possible, however, to change the program which implements an 
  14979.       object's server, or change the class library which implements an object's 
  14980.       class. To modify the program associated with an ImplementationDef, use 
  14981.       the update_impldef method defined on ImplRepository. To change the 
  14982.       implementation of an object's class, replace the corresponding class 
  14983.       library with a new (upward-compatible) one. 
  14984.  
  14985.      The OUT_list_MEMORY, IN_COPY_VALUE, and DEPENDENT_LIST flags, used with 
  14986.       the Dynamic Invocation Interface, are not yet supported. 
  14987.  
  14988.      The SOM Object Adapter (SOMOA) provides a method (change_id) to update 
  14989.       the ReferenceData  associated with an object reference created by the 
  14990.       create call This is useful if the information which describes the object 
  14991.       must be changed without invalidating copies of the existing object 
  14992.       reference. CORBA defines no such method;  change_id is an extension to 
  14993.       the standard BOA methods. 
  14994.  
  14995.      The SOMOA provides some specialized object reference types which, in 
  14996.       certain situations, are more efficient or easier-to-use than standard 
  14997.       object references. 
  14998.  
  14999.      DSOM supports the SOM extension to IDL that allows method parameters that 
  15000.       are pointers. Structure, sequence, and array parameters may only contain 
  15001.       pointers to objects (not arbitrary types). 
  15002.  
  15003.      The Context::get_values method currently does not support the 
  15004.       CTX_RESTRICT_SCOPE flag. 
  15005.  
  15006.  
  15007. ΓòÉΓòÉΓòÉ 7.19. Advanced Topics ΓòÉΓòÉΓòÉ
  15008.  
  15009. The following subjects are discussed in this section: 
  15010.  
  15011.      Peer vs. client/server processes 
  15012.      Dynamic Invocation Interface 
  15013.      Creating user-supplied proxies 
  15014.      Customizing the default base proxy class 
  15015.      Sockets class 
  15016.  
  15017.  
  15018. ΓòÉΓòÉΓòÉ 7.19.1. Peer vs. client/server processes ΓòÉΓòÉΓòÉ
  15019.  
  15020. The client/server model of distributed computing is appropriate when it is 
  15021. convenient (or necessary) to centralize the implementation and management of a 
  15022. set of shared objects in one or more servers. However, some applications 
  15023. require more flexibility in the distribution of objects among processes. 
  15024. Specifically, it is often useful to allow processes to manage and export some 
  15025. of their objects, as well as access remote objects owned by other processes. In 
  15026. these cases, the application processes do not adhere to a strict client/server 
  15027. relationship; instead, they cooperate as "peers", behaving both as clients and 
  15028. as servers. 
  15029.  
  15030. Peer applications must be written to respond to incoming asynchronous requests, 
  15031. in addition to performing their normal processing. In a multi-threaded system 
  15032. (like OS/2), this is best accomplished by dedicating a separate process thread 
  15033. that handles DSOM communications and dispatching. In systems that do not 
  15034. currently support multi-threading (like AIX), peer applications must be 
  15035. structured as event-driven programs. 
  15036.  
  15037.  
  15038. ΓòÉΓòÉΓòÉ 7.19.1.1. Multi-threaded DSOM programs ΓòÉΓòÉΓòÉ
  15039.  
  15040. In a system that supports multi-threading, like OS/2, the easiest way to write 
  15041. a peer DSOM program is to dedicate a separate thread to perform the usual 
  15042. "server" processing. This body of this thread would contain the same code as 
  15043. the simple servers described in section 6.4, "Basic Server Programming." 
  15044.  
  15045. DSOM_thread(void *params)
  15046. {
  15047.    Environment ev;
  15048.    SOM_InitEnvironment(&ev);
  15049.  
  15050. /* Initialize the DSOM run-time environment */
  15051.    SOMD_Init(&ev);
  15052.  
  15053. /* Retrieve its ImplementationDef from the Implementation
  15054.    Repository by passing its implementation ID as a key */
  15055.    SOMD_ImplDefObject =
  15056.       _find_impldef(SOMD_ImplRepObject, &ev, *(ImplId *)params);
  15057.  
  15058. /* Create SOM Object Adapter and begin executing requests */
  15059.    SOMD_SOMOAObject = SOMOANew();
  15060.    _impl_is_ready(SOMD_SOMOAObject, &ev, SOMD_ImplDefObject);
  15061.    _execute_request_loop(SOMD_SOMOAObject, &ev, SOMD_WAIT);
  15062. }
  15063.  
  15064. Note:  The DSOM run time is "thread safe"; that is, DSOM protects its own  data 
  15065.        structures and objects from race conditions and update conflicts. 
  15066.        However, it is the application's responsibility to implement its own 
  15067.        concurrency control for concurrent thread access to local shared 
  15068.        application objects. 
  15069.  
  15070.  
  15071. ΓòÉΓòÉΓòÉ 7.19.1.2. Event-driven DSOM programs using EMan ΓòÉΓòÉΓòÉ
  15072.  
  15073. EMan (see Chapter 9 on "The Event Management Framework") is not a replacement 
  15074. for threads, but it supports processing of asynchronous requests. EMan allows a 
  15075. program to handle events from multiple input sources; but the handlers run on a 
  15076. single thread, under control of EMan's main loop. 
  15077.  
  15078. DSOM provides a runtime function, SOMD_RegisterCallback, which is used by DSOM 
  15079. to associate user-supplied event handlers with DSOM's communications sockets 
  15080. and message queues with EMan. Example code is shown below. 
  15081.  
  15082. DSOM server programs which use EMan must be very careful not to get into 
  15083. deadlock situations. This is quite easy to do with DSOM, since method calls are 
  15084. synchronous. If two cooperating processes simultaneously make calls on each 
  15085. other, a deadlock could result. Likewise, if a method call on remote object B 
  15086. from A requires a method call back to A, a deadlock cycle will exist. (Of 
  15087. course, the number of processes and objects which create the cyclic dependency 
  15088. could be greater than two.) 
  15089.  
  15090. The application developer must be careful to avoid situations where cooperating 
  15091. processes are likely to make calls upon each other, creating a cyclic 
  15092. dependency. Some applications may find it appropriate to use oneway messages to 
  15093. avoid deadlock cycles, since oneway messages do not cause a process to block. 
  15094. It may also be possible for an application to defer the actual processing of a 
  15095. method that may "call back" an originating process, by scheduling work using 
  15096. EMan client events. 
  15097.  
  15098.  
  15099. ΓòÉΓòÉΓòÉ 7.19.1.3. Sample server using EMan ΓòÉΓòÉΓòÉ
  15100.  
  15101. The following server code has been distilled from one of the DSOM sample 
  15102. applications provided with SOMobjects Developer Toolkit. It is an example of a 
  15103. server which has an interval timer that signals another server (via DSOM) 
  15104. whenever its timer "pops". Thus, it is both a client (of the server it signals) 
  15105. and a server (because it can receive timer notifications from other servers). 
  15106.  
  15107. The IDL for the server object class to be used by this server program is as 
  15108. follows. Note that the "noteTimeout" method is oneway, in order to avoid 
  15109. deadlock. 
  15110.  
  15111. interface PeerServer :SOMDServer
  15112. { oneway void noteTimeout(in string serverName);
  15113.   // Notification that a timer event occurred in server serverName
  15114. };
  15115.  
  15116. The example server program is outlined as follows. It is assumed that "eman.h" 
  15117. has been included by the program. 
  15118.  
  15119.      Perform DSOM initialization up to, but not including, asking SOMOA to 
  15120.       start handling requests. 
  15121.  
  15122.             MyEMan = SOMEEManNew();
  15123.             SOM_InitEnvironment(&ev);
  15124.             SOM_InitEnvironment(&peerEv);
  15125.             SOMD_Init(&ev);
  15126.  
  15127.             somPrintf("What is the alias for this server? ");
  15128.             gets(thisServer);
  15129.  
  15130.             SOMD_ImplDefObject = _find_impldef_by_alias(SOMD_ImplRepObject,
  15131.                                                          &ev, thisServer);
  15132.             SOMD_SOMOAObject = SOMOANew();
  15133.             _impl_is_ready(SOMD_SOMOAObject, &ev, SOMD_ImplDefObject);
  15134.  
  15135.      Register a "DSOM event" with EMan, having EMan callback to a procedure 
  15136.       that asks the SOMOA to process any pending DSOM requests. 
  15137.  
  15138.             void SOMD_RegisterCallback(SOMEEman emanObj, EMRegProc *func);
  15139.  
  15140.             void DSOMEventCallBack (SOMEEvent event, void *eventData)
  15141.             {   Environment ev;
  15142.                 SOM_InitEnvironment(&ev);
  15143.                 _execute_request_loop(SOMD_SOMOAObject, &ev, SOMD_NO_WAIT);
  15144.             }
  15145.  
  15146.             SOMD_RegisterCallback (MyEMan, DSOMEventCallBack);
  15147.  
  15148.      Ask user to provide "target server's alias", where the target server is 
  15149.       that this server will signal when its timer "pops". Then get a proxy for 
  15150.       that server. 
  15151.  
  15152.             somPrintf("What is the alias for the target server? ");
  15153.             gets(inbuf);
  15154.             RemotePeer = _somdFindServerByName(SOMD_ObjectMgr, &ev, inbuf);
  15155.  
  15156.      Ask user to provide the timer's interval (in milliseconds) 
  15157.  
  15158.             somPrintf("What is the timer interval, in milliseconds? ");
  15159.             gets(inbuf);
  15160.             Interval = atoi(inbuf);
  15161.  
  15162.      Register a timer event with EMan, having EMan call back a procedure that 
  15163.       will invoke the notification method on the target server. 
  15164.  
  15165.             void TimerEventCallBack (SOMEEvent event, void *eventData)
  15166.             { Environment ev;
  15167.               SOM_InitEnvironment(&ev);
  15168.               /* call the peer, with a oneway message */
  15169.               _noteTimeout(RemotePeer, &ev, thisServer);
  15170.             }
  15171.  
  15172.             data = SOMEEMRegisterDataNew();
  15173.             _someClearRegData(data, &ev);
  15174.             _someSetRegDataEventMask(data, &ev, EMTimerEvent, NULL);
  15175.             _someSetRegDataTimerInterval(data, &ev, Interval);
  15176.             somPrintf("Type <Enter> key when ready to go: ");
  15177.             gets(inbuf);
  15178.             regId = _someRegisterProc(MyEMan, &ev, data, TimerEventCallBack,
  15179.                                        NULL);
  15180.  
  15181.       Important  Do not use someRegister or someRegisterEV to register 
  15182.                  "callback methods" that would be executed on proxy objects. 
  15183.                  Instead, write a callback routine that invokes the desired 
  15184.                  method on the proxy, like the one shown above, and register 
  15185.                  that routine using the method someRegisterProc. 
  15186.  
  15187.       Note:  EMan currently uses the methods someRegister and someRegisterEv to 
  15188.              obtain the address of a method-procedure to call when a specified 
  15189.              event occurs. If EMan directly calls the method-procedure versus 
  15190.              somDispatch, the method call will not be forwarded to the remote 
  15191.              object as desired. 
  15192.  
  15193.      Start the EMan event processing loop. 
  15194.  
  15195.             _someProcessEvents(MyEMan, &ev);
  15196.  
  15197.  Before the sample is run, two server implementations should be registered with 
  15198.  regimpl. The implementations are identical except for their aliases. One may 
  15199.  be called "peerServer1" and the other "peerServer2". The "PeerServer" class 
  15200.  should be specified as their server-object class. 
  15201.  
  15202.  Whenever peerServer1's timer pops, the Event Manager causes a method, 
  15203.  "noteTimeout", to be sent to the server object in peerServer2. PeerServer2's 
  15204.  server object executes this method by displaying a message on its window. 
  15205.  Whenever peerServer2's timer pops, a similar sequence occurs with peerServer1. 
  15206.  The two servers will run continuously until interrupted. 
  15207.  
  15208.  
  15209. ΓòÉΓòÉΓòÉ 7.19.2. Dynamic Invocation Interface ΓòÉΓòÉΓòÉ
  15210.  
  15211. DSOM supports the CORBA dynamic invocation interface (DII), which clients can 
  15212. use to dynamically build and invoke requests on objects. This section describes 
  15213. how to use the DSOM DII. Currently, DSOM supports dynamic request invocation 
  15214. only on objects outside the address space of the request initiator, via 
  15215. proxies. The somDispatch method (non-CORBA) can be used to invoke methods 
  15216. dynamically on either local or remote objects, however. 
  15217.  
  15218. To invoke a request on an object using the DII, the client must explicitly 
  15219. construct and initiate the request. A request is comprised of an object 
  15220. reference, an operation, a list of arguments for the operation, and a return 
  15221. value from the operation. A key to proper construction of the request is the 
  15222. correct usage of the NamedValue structure and the NVList object. The return 
  15223. value for an operation is supplied to the request in the form of a NamedValue 
  15224. structure. In addition, it is usually most convenient to supply the arguments 
  15225. for a request in the form of an NVList object, which is an ordered set of 
  15226. NamedValues. This section begins with a description of NamedValues and NVLists 
  15227. and then details the procedure for building and initiating requests. 
  15228.  
  15229.  
  15230. ΓòÉΓòÉΓòÉ 7.19.2.1. The NamedValue structure ΓòÉΓòÉΓòÉ
  15231.  
  15232. The NamedValue structure is defined in C as: 
  15233.  
  15234. typedef unsigned long Flags;
  15235.  
  15236. struct NamedValue {
  15237.         Identifier  name;         // argument name
  15238.         any         argument;     // argument
  15239.         long        len;          // length/count of arg value
  15240.         Flags       arg_modes;    // argument mode flags
  15241. };
  15242.  
  15243. where: name is an Identifier string as defined in the CORBA specification, and 
  15244. argument is an any structure with the following declaration: 
  15245.  
  15246.  
  15247.         struct any {
  15248.                 TypeCode        _type;
  15249.                 void*           _value;
  15250.         };
  15251.  
  15252. _type  is a TypeCode, which has an opaque representation with operations 
  15253. defined on it to allow access to its constituent parts. Essentially the 
  15254. Typecode is composed of a field specifying the CORBA type represented and 
  15255. possibly additional fields needed to fully describe the type. See Chapter 7 of 
  15256. this manual for a complete explanation of TypeCodes. 
  15257.  
  15258. _value  is a pointer to the value of the any structure. Important: The contents 
  15259. of "_value" should always be a pointer to the value, regardless of whether the 
  15260. value is a primitive, a structure, or is itself a pointer (as in the case of 
  15261. object references, strings and arrays). For object references, strings and 
  15262. arrays, _value should contain pointer to the pointer that references the value. 
  15263. For example: 
  15264.  
  15265.  
  15266.         string          testString;
  15267.         any             testAny;
  15268.  
  15269.         testAny._value = &testString;
  15270.  
  15271. len is the number of bytes that the argument value occupies. The following 
  15272. table gives the length of data values for the C language bindings. The value of 
  15273. len must be consistent with the TypeCode. 
  15274.  
  15275.  
  15276. Data type               Length
  15277. short                   sizeof(short)
  15278. unsigned short          sizeof(unsigned short)
  15279. long                    sizeof(long)
  15280. unsigned long           sizeof(unsigned long)
  15281. float                   sizeof(float)
  15282. double                  sizeof(double)
  15283. char                    sizeof(char)
  15284. boolean                 sizeof(boolean)
  15285. octet                   sizeof(octet)
  15286. string                  strlen(string) - does not include '\0' byte
  15287. enum E{}                sizeof(unsigned long)
  15288. union U                 sizeof(U)
  15289. struct S{}              sizeof(S)
  15290. Object                  1
  15291. array N of type T1      Length(T1)*N
  15292. sequence V of type T2   Length(T2)*V - V is the actual # of elements
  15293.  
  15294. The arg_modes field is a bitmask (unsigned long) and may contain the following 
  15295. flag values: 
  15296.  
  15297. ARG_IN              the associated value is an input-only argument
  15298. ARG_OUT             the associated value is an output-only argument
  15299. ARG_INOUT           the associated argument is an in/out argument
  15300.  
  15301. These flag values identify the parameter passing mode for the arguments. 
  15302. Additional flag values have specific meanings for Request and NVList methods 
  15303. and are listed with their associated methods. 
  15304.  
  15305.  
  15306. ΓòÉΓòÉΓòÉ 7.19.2.2. The NVList class ΓòÉΓòÉΓòÉ
  15307.  
  15308. An NVList contains an ordered set of NamedValues. The CORBA specification 
  15309. defines several operations that the NVList supports. The IDL prototypes for 
  15310. these methods are as follows: 
  15311.  
  15312.  
  15313. // get the number of elements in the NVList
  15314. ORBStatus get_count(
  15315.                 out  long count );
  15316.  
  15317. // add an element to an NVList
  15318. ORBStatus add_item(
  15319.                 in  Identifier      item_name,
  15320.                 in  TypeCode    item_type,
  15321.                 in  void* value,
  15322.                 in  Flags item_flags );
  15323.  
  15324. // frees the NVList and any associated memory
  15325. ORBStatus free();
  15326.  
  15327.  
  15328. // frees dynamically allocated memory associated with the list
  15329. ORBStatus free_memory();
  15330.  
  15331. In DSOM, the NVList is a full-fledged object with methods for getting and 
  15332. setting elements: 
  15333.  
  15334.  
  15335. //set the contents of an element in an NVList
  15336. ORBStatus set_item(
  15337.                 in  long            item_number, /* element # to set */
  15338.                 in  Identifier      item_name,
  15339.                 in  TypeCode        item_type,
  15340.                 in  void*           item_value,
  15341.                 in  long            value_len,
  15342.                 in  Flags           item_flags );
  15343.  
  15344.  
  15345. // get the contents of an element in an NVList
  15346. ORBStatus get_item(
  15347.                 in  long            item_number, /* element # to get */
  15348.                 out Identifier      item_name,
  15349.                 out TypeCode        item_type,
  15350.                 out void*           item_value,
  15351.                 out long            value_len,
  15352.                 out Flags           item_flags );
  15353.  
  15354.  
  15355. ΓòÉΓòÉΓòÉ 7.19.2.3. Creating argument lists ΓòÉΓòÉΓòÉ
  15356.  
  15357. A very important use of the NVList is to pass the argument list for an 
  15358. operation when creating a request. CORBA 1.1 specifies two methods, defined in 
  15359. the ORB class, to build an argument list: create_list and 
  15360. create_operation_list. The IDL prototypes for these methods are as follows: 
  15361.  
  15362. ORBStatus create_list(
  15363.                         in  long        count,        /* # of items */
  15364.                         out NVList      new_list );
  15365.  
  15366. ORBStatus create_operation_list(
  15367.                         in  OperationDef oper,
  15368.                         out NVList       new_list );
  15369.  
  15370. The create_list method returns an NVList with the specified number of elements. 
  15371. Each of the elements is empty. It is the client's responsibility to fill the 
  15372. elements in the list with the correct information using the set_item method. 
  15373. Elements in the NVList must contain the arguments in the same order as they 
  15374. were defined for the operation. Elements are numbered from 0 to count-1. 
  15375.  
  15376. The create_operation_list method returns an NVList initialized with the 
  15377. argument descriptions for a given operation (specified by the OperationDef). 
  15378. The arguments are returned in the same order as they were defined for the 
  15379. operation. The client only needs to fill in the item_value and value_len in the 
  15380. elemens of the NVList. 
  15381.  
  15382. In addition to these CORBA-defined methods, DSOM provides a third version, 
  15383. defined in the SOMDObject class. The IDL prototype for this method is as 
  15384. follows: 
  15385.  
  15386.  
  15387. ORBStatus create_request_args(
  15388.                         in Identifier operation,
  15389.                         out NVList arg_list,
  15390.                         out NamedValue result );
  15391.  
  15392. Like create_operation_list, the create_request_args method creates the 
  15393. appropriate NVList for the specified operation.  In addition, 
  15394. create_request_args initializes the NamedValue that will hold the result with 
  15395. the expected return type. The create_request_args method is defined as a 
  15396. companion to the create_request method, and has the advantage that the 
  15397. InterfaceDef for the operation does not have to be retrieved from the Interface 
  15398. Repository. 
  15399.  
  15400. Note:  The create_request_args method is not  defined in CORBA 1.1. Hence, the 
  15401.        create_operation_list method, defined on the ORB class, should be used 
  15402.        instead when writing portable CORBA-compliant programs. 
  15403.  
  15404.  
  15405. ΓòÉΓòÉΓòÉ 7.19.2.4. Building a Request ΓòÉΓòÉΓòÉ
  15406.  
  15407. There are two ways to build a Request object. Both begin by calling the 
  15408. create_request method defined by the SOMDObject class. The IDL prototype for 
  15409. create_request is as follows: 
  15410.  
  15411. ORBStatus create_request(
  15412.                 in  Context            ctx,
  15413.                 in  Identifier         operation,
  15414.                 in  NVList             arg_list,
  15415.                 inout NamedValue       result,
  15416.                 out Request            request,
  15417.                 in  Flags              req_flags );
  15418.  
  15419. The arg_list can be constructed using the procedures described above and is 
  15420. passed to the Request object in the create_request call. Alternatively, 
  15421. arg_list can be specified as NULL and repetitive calls to add_arg  can be used 
  15422. to specify the argument list. The add_arg method, defined by the Request class, 
  15423. has the following IDL prototype: 
  15424.  
  15425. ORBStatus add_arg(
  15426.                 in  Identifier  name,
  15427.                 in  TypeCode    arg_type,
  15428.                 in  void*       value,
  15429.                 in  long        len,
  15430.                 in  Flags       arg_flags );
  15431.  
  15432.  
  15433. ΓòÉΓòÉΓòÉ 7.19.2.5. Initiating a Request ΓòÉΓòÉΓòÉ
  15434.  
  15435. There are two ways to initiate a request, using either the invoke or send 
  15436. method defined by the Request class. The IDL prototypes for these two 
  15437. operations ar as follows: 
  15438.  
  15439.  
  15440. ORBStatus invoke(
  15441.                 in Flags        invoke_flags );
  15442.  
  15443. ORBStatus send(
  15444.                 in Flags        send_flags );
  15445.  
  15446. The invoke method calls the ORB, which handles the remote method invocation and 
  15447. returns the result. This method will block while awaiting return of the result. 
  15448.  
  15449. The send method calls the ORB but does not wait for the operation to complete 
  15450. before returning. To determine when the operation is complete, the client must 
  15451. call the get_response method (also defined by the Request class), which has 
  15452. this IDL prototype: 
  15453.  
  15454.  
  15455. ORBStatus get_response(
  15456.                 in Flags        response_flags );
  15457.  
  15458. The following flag is defined for get_response: 
  15459.  
  15460.  
  15461. RESP_NO_WAIT       Means that the caller does not want to wait for a 
  15462.  
  15463.                  response.
  15464.  
  15465. get_response determines whether a request has competed. If the RESP_NO_WAIT 
  15466. flag is set, get_response returns immediately even if the request is still in 
  15467. progress. If RESP_NO_WAIT is not set, get_response waits until the request is 
  15468. done before returning. 
  15469.  
  15470.  
  15471. ΓòÉΓòÉΓòÉ 7.19.2.6. Example code ΓòÉΓòÉΓòÉ
  15472.  
  15473. Following is an incomplete example showing how to use the DII to invoke a 
  15474. request having the method procedure prototype shown here: 
  15475.  
  15476.  
  15477. string _testMethod( testObject              obj,
  15478.                     Environment             *ev,
  15479.                     long                    input_value,
  15480. );
  15481.  
  15482. main()
  15483. {
  15484.    ORBStatus rc;
  15485.    Environment ev;
  15486.    SOMDObject obj;
  15487.    NVList arglist;
  15488.    NamedValue result;
  15489.    Context ctx;
  15490.    Request reqObj;
  15491.    OperationDef opdef;
  15492.    Description desc;
  15493.    OperationDescription opdesc;
  15494.    static long input_value = 999;
  15495.  
  15496.    SOM_InitEnvironment(&ev);
  15497.    SOMD_Init(&ev);
  15498.  
  15499. /* create the argument list */
  15500. /* get the operation description from the interface repository */
  15501.    opdef = _lookup_id(SOM_InterfaceRepository, *ev,
  15502.                   "testObject::testMethod");
  15503.    desc = _describe(opdef, &ev);
  15504.    opdesc = (OperationDescription *) desc.value._value;
  15505.  
  15506. /* fill in the TypeCode field for the result */
  15507.    result.argument._type = opdesc->result;
  15508.  
  15509. /* Initialize the argument list */
  15510.    rc = _create_operation_list(SOMD_ORBObject, &ev, opdef,
  15511.                                &arglist);
  15512.  
  15513. /* get default context */
  15514.    rc = _get_default_context(SOMD_ORBObject, &ev, &ctx);
  15515.  
  15516. /* put value and length into the NVList */
  15517.    _get_item(arglist, &ev, 0, &name, &tc, &dummy, &dummylen,
  15518.              &flags);
  15519.  
  15520.    _set_item(arglist, &ev, 0, name, tc, &input_value,
  15521.              sizeof(input_value),flags);
  15522.     ...
  15523. /* create the request - assume the object reference came from
  15524.    somewhere -- from a file or returned by a previous request*/
  15525.    rc = _create_request(obj, &ev, ctx,
  15526.                         "testMethod", arglist, &result, &reqObj,
  15527.                         (Flags)0);
  15528.  
  15529. /* invoke request */
  15530.    rc = invoke(reqObj, &ev, (Flags)0);
  15531.  
  15532. /* print result */
  15533.    printf("result: %s\n",*(string*)(result.argument._value));
  15534.    return(0);
  15535. }
  15536.  
  15537.  
  15538. ΓòÉΓòÉΓòÉ 7.19.3. Creating user-supplied proxies ΓòÉΓòÉΓòÉ
  15539.  
  15540. DSOM uses a proxy object in the client's address space to represent the remote 
  15541. object. As mentioned earlier in this chapter, the proxy object encapsulates the 
  15542. operations necessary to forward and invoke methods on the remote object and 
  15543. return the results. By default, proxy generation is done automatically by the 
  15544. DSOM run time. However, if desired, the programmer can cause a user-supplied 
  15545. proxy class to be loaded instead of letting the run time dynamically generate a 
  15546. default proxy class. User-supplied proxies can be useful in specialized 
  15547. circumstances when local processing or data caching is desired. 
  15548.  
  15549. To build a user-supplied proxy class, it is necessary to understand a bit about 
  15550. how dynamic proxy classes are constructed by the DSOM run time. The DSOM run 
  15551. time constructs a proxy class by creating an instance of a class that inherits 
  15552. the interface and implementation of SOMDClientProxy, and the interface (but not 
  15553. the implementation) of the target class. The methods in the interface of the 
  15554. target object are all overridden to call the somDispatch method (For more 
  15555. details, see "Object references and proxy objects" in section 6.8.) 
  15556.  
  15557. Every SOM object contains the somDispatch method, inherited from SOMObject. 
  15558. This method is used to dynamically dispatch a method on an object, and can be 
  15559. overridden with application-specific dispatching mechanisms. In 
  15560. SOMDClientProxy, the somDispatch method is overridden to forward method calls 
  15561. to the corresponding remote target object. 
  15562.  
  15563. So, in effect, when a method is called on a default proxy object created by the 
  15564. DSOM run time, it redispatches the method to the remote object using DSOM's 
  15565. version of somDispatch. 
  15566.  
  15567. Below is a simple example of a user-supplied proxy class. In this particular 
  15568. example, the proxy object maintains a local, unshared copy of an attribute 
  15569. ("attribute_long") defined in the remote object ("Foo"), while forwarding 
  15570. method invocations ("method1") on to the remote object. The result is that, 
  15571. when multiple clients are talking to the same remote "Foo" object, each client 
  15572. has a local copy of the attribute but all clients share the "Foo" object's 
  15573. implementation of "method1". 
  15574.  
  15575. Note:  It is important to understand that simply setting the attribute in one 
  15576.        client's proxy does not affect the value of the attribute in other 
  15577.        proxies. Maintaining consistency of the cached data values, if desired, 
  15578.        is the responsibility of the user-supplied proxy class. 
  15579.  
  15580.  Following is the IDL file for the "Foo" class: 
  15581.  
  15582.  
  15583.   // foo.idl
  15584.  
  15585.  
  15586.   #include <somdtype.idl>
  15587.   #include <somobj.idl>
  15588.  
  15589.  
  15590.   interface Foo : SOMObject
  15591.   {
  15592.           string  method1(out string a, inout long b,
  15593.                           in ReferenceData c);
  15594.           attribute long attribute_long;
  15595.  
  15596.  
  15597.     implementation
  15598.     {
  15599.        releaseorder: method1, _set_attribute_long,
  15600.                      _get_attribute_long;
  15601.        dllname="foo.dll";
  15602.        somDefaultInit: override;
  15603.     };
  15604.   };
  15605.  
  15606.  The user-supplied proxy class is created by using multiple inheritance between 
  15607.  SOMDClientProxy and the target object (in this case "Foo"). Thus, the IDL file 
  15608.  for the user-supplied proxy class "Foo__Proxy" (note the two underscores) is 
  15609.  as follows: 
  15610.  
  15611.  
  15612.   // fooproxy.idl
  15613.  
  15614.  
  15615.   #include <somdcprx.idl>
  15616.   #include <foo.idl>
  15617.  
  15618.  
  15619.   interface Foo__Proxy : SOMDClientProxy, Foo
  15620.   {
  15621.     implementation
  15622.     {
  15623.        dllname="fooproxy.dll";
  15624.        method1: override;
  15625.     };
  15626.   };
  15627.  
  15628.  When a dynamic proxy class is created by the DSOM run time, the methods 
  15629.  inherited from the target class are automatically overridden to use 
  15630.  somDispatch. When you build a user-supplied proxy, you need to do this 
  15631.  explicitly. This is why "method1" is overridden in the implementation section 
  15632.  of the "fooproxy.idl" file. 
  15633.  
  15634.  The implementation of "method1", which was added to the template produced by 
  15635.  the SOM Compiler, simply calls the somDispatch method on "somSelf" Because 
  15636.  "Foo__Proxy" has inherited the implementation of SOMDClientProxy, calling 
  15637.  somDispatch within "method1" sends the method to the remote "Foo" object. 
  15638.  
  15639.   /* fooproxy.c */
  15640.  
  15641.   #include <somdtype.h>
  15642.   #include <fooproxy.ih>
  15643.  
  15644.   SOM_Scope string  SOMLINK method1(Foo__Proxy somSelf,
  15645.                                     Environment *ev,
  15646.                                     string* a, long* b,
  15647.                                     ReferenceData* c)
  15648.   {
  15649.       string ret_str;
  15650.       somId  methodId;
  15651.  
  15652.  
  15653.   /*  Foo__ProxyData *somThis = Foo__ProxyGetData(somSelf); */
  15654.       Foo__ProxyMethodDebug("Foo__Proxy","method1");
  15655.  
  15656.  
  15657.       /* redispatch method, remotely */
  15658.       methodId = somIdFromString("method1");
  15659.       _somDispatch(somSelf, (void**)&ret_str,
  15660.                    methodId, somSelf, ev, a, b, c);
  15661.       SOMFree(methodId);
  15662.  
  15663.  
  15664.       return ret_str;
  15665.   }
  15666.  
  15667.  In summary, to build a user-supplied proxy class: 
  15668.  
  15669.      Create the .idl file with the proxy class inheriting from both 
  15670.       SOMDClientProxy and from the target class. Important: The user-supplied 
  15671.       proxy class must be named "<targetClassName>_ _Proxy" (with two 
  15672.       underscores in the name) and SOMDClientProxy must be the first class in 
  15673.       the list of parent classes; for example, 
  15674.  
  15675.  
  15676.                     interface Foo_ _Proxy : SOMDClientProxy, Foo
  15677.  
  15678.       Putting SOMDClientProxy first ensures that its version of somDispatch 
  15679.       will be used to dispatch remote method calls. 
  15680.  
  15681.       In the implementation section of the .idl file, override all methods that 
  15682.       are to be invoked on the target class. Do not override methods that are 
  15683.       to be invoked on the local proxy. 
  15684.  
  15685.      Compile the .idl file. Be sure the Interface Repository gets updated with 
  15686.       the .idl file. In the implementation file, for each overridden method, 
  15687.       call somDispatch with the method name and parameters passed into the 
  15688.       overridden method. If the proxy class provides an implementation for the 
  15689.       somInit or somDefaultInit method, then it is important to ensure that 
  15690.       calling that method more than once on the same proxy object has no 
  15691.       negative effect. 
  15692.  
  15693.      Build the DLL and place it the LIBPATH for AIX and OS/2, or listed in 
  15694.       PATH for Windows. Before creating the default proxy, the DSOM run time 
  15695.       checks the LIBPATH for a DLL containing the class named 
  15696.       "<targetClassName>_ _Proxy" If such a DLL is found, DSOM loads it instead 
  15697.       of dynamically generating a proxy class. 
  15698.  
  15699.  
  15700. ΓòÉΓòÉΓòÉ 7.19.4. Customizing the default base proxy class ΓòÉΓòÉΓòÉ
  15701.  
  15702. Continuing the example from the previous topic, imagine that an application 
  15703. derives 100 subclasses from the "Foo" class. If the application wishes to cache 
  15704. the "Foo::attribute_long" attribute in the proxies for all remote Foo-based 
  15705. objects, the application could supply 100 user-supplied proxy classes, 
  15706. developed in the manner described above. However, this would become a very 
  15707. tedious and repetitive task! 
  15708.  
  15709. Alternatively, it is possible to provide a customized base proxy class for use 
  15710. in the dynamic generation of DSOM proxy classes. This allows an application to 
  15711. provide a customized base proxy class, from which other dynamic DSOM proxy 
  15712. classes can be derived. This is particularly useful in situations where an 
  15713. application would like to enhance many or all dynamically generated proxy 
  15714. classes with a common feature. 
  15715.  
  15716. As described in the previous topic, proxy classes are derived from the 
  15717. SOMDClientProxy class by default. It is the SOMDClientProxy class that 
  15718. overrides somDispatch in order to forward method calls to remote objects. 
  15719.  
  15720. The SOMDClientProxy class can be customized by deriving a subclass in the usual 
  15721. way (being careful not to replace somDispatch or other methods that are 
  15722. fundamental to implementing the proxy's behavior). To extend the above example 
  15723. further, the application might define a base proxy class called "MyClientProxy" 
  15724. that defines a long attribute called "attribute_long," which will be inherited 
  15725. by Foo-based proxy classes. 
  15726.  
  15727. The SOM IDL modifier baseproxyclass can be used to specify which base proxy 
  15728. class DSOM should use during dynamic proxy-class generation. To continue the 
  15729. example, if the class "MyClientProxy" were used to construct the proxy class 
  15730. for a class "XYZ," then the baseproxyclass modifier would be specified s 
  15731. follows: 
  15732.  
  15733. // xyz.idl
  15734.  
  15735. #include <somdtype.idl>
  15736. #include <foo.idl>
  15737.  
  15738. interface XYZ : Foo
  15739. {
  15740.   ...
  15741.   implementation
  15742.   {
  15743.      ...
  15744.      baseproxyclass = MyClientProxy;
  15745.   };
  15746. };
  15747.  
  15748. It should be noted that: 
  15749.  
  15750.      Base proxy classes must be derived from SOMDClientProxy. 
  15751.  
  15752.      If a class "XYZ" specifies a custom base-proxy class, as in the above 
  15753.       example, subclasses of "XYZ" do not  inherit the value of the 
  15754.       baseproxyclass modifier. If needed, the  baseproxyclass modifier must be 
  15755.       specified explicitly in each class. 
  15756.  
  15757.  
  15758. ΓòÉΓòÉΓòÉ 7.19.5. Sockets class ΓòÉΓòÉΓòÉ
  15759.  
  15760. To aid in portability, DSOM has been written to use a common communications 
  15761. interface, which is implemented by one or more available local protocols. 
  15762.  
  15763. The common communications interface is represented as an abstract class, called 
  15764. Sockets, and is based on the familiar "sockets" interface. Several protocol 
  15765. implementations are supported as Sockets subclasses: TCPIPSockets (and 
  15766. TCPIPSockets32 for OS/2) for TCP/IP, the class NBSockets for Netbios, and the 
  15767. class IPXSockets for Netware IPX/SPX. (The libraries included in a particular 
  15768. SOMobjects run-time package will vary.) 
  15769.  
  15770. There is one case where a Sockets subclass is not required: the DSOM 
  15771. Workstation run-time package uses shared memory to pass messages within a 
  15772. single machine, and bypasses the use of a Sockets subclass. (The SOMSOCKETS 
  15773. environment variable is ignored.) 
  15774.  
  15775. When the Event Management Framework (EMan) is used with DSOM, a Sockets 
  15776. subclass will be needed to support EMan, whether or not the application runs 
  15777. completely within a single machine. 
  15778.  
  15779. Appendix C, "Implementing Sockets Subclasses," describes how an application 
  15780. might provide its own Sockets subclass implementation, for special 
  15781. circumstances. 
  15782.  
  15783.  
  15784. ΓòÉΓòÉΓòÉ 7.20. Error Reporting and Troubleshooting ΓòÉΓòÉΓòÉ
  15785.  
  15786. When the DSOM run-time environment encounters an error during execution of a 
  15787. method or procedure, a SYSTEM_EXCEPTION will be raised. The standard system 
  15788. exceptions are discussed in the topic "Exceptions and Error Handling" in 
  15789. Chapter 3 "Using SOM Classes in Client Programs." The "minor" field of the 
  15790. returned exception value will contain a DSOM error code. The DSOM error codes 
  15791. are listed below. 
  15792.  
  15793. Although a returned exception value can indicate that a DSOM run-time error 
  15794. occurred, it may be difficult for the user or application to determine what 
  15795. caused the error. Consequently, DSOM has been enabled to report run-time error 
  15796. information, for interpretation by IBM support personnel. These error messages 
  15797. take the following form: 
  15798.  
  15799.  
  15800. DSOM <type> error:  <code> [<name>] at  <file>:<line>
  15801.  
  15802. where the arguments are as follows: 
  15803.  
  15804.  
  15805. type    SYSTEM_EXCEPTION type,
  15806. code    DSOM error code,
  15807. name symbol for DSOM error code (from "somderr.h"),
  15808. file    source-file name where the error occurred, and
  15809. line    line number where the error occurred.
  15810.  
  15811. For example, 
  15812.  
  15813.  
  15814. DSOM NO_MEMORY error: 30001 [SOMDERROR_NoMemory] at somdobj.c:250
  15815.  
  15816. indicates that a "NO_MEMORY" error (error code 30001) occurred in file 
  15817. "somdobj.c" at line 250. This information is not usually meaningful to the 
  15818. user; it provides IBM support personnel with a starting point for problem 
  15819. analysis. There will often be a sequence of error messages; together they 
  15820. indicate the context in which the error occurred. It is important to give all 
  15821. reported messages to IBM support personnel for analysis. 
  15822.  
  15823. There is an environment variable, SOMDDEBUG, which is used to activate error 
  15824. reporting. There is a corresponding global variable that can be set by an 
  15825. application program; it is declared as: 
  15826.  
  15827. extern long SOMD_DebugFlag;
  15828.  
  15829. Error reporting is normally disabled. To enable error reporting, the 
  15830. environment variable SOMDDEBUG should be set to a value greater than 0. To 
  15831. disable error reporting, SOMDDEBUG should be set to a value less than or equal 
  15832. to 0. 
  15833.  
  15834. By default, error messages will display on the standard output device. Error 
  15835. messages can also be redirected to a log file. For this, the environment 
  15836. variable SOMDMESSAGELOG should be set to the pathname of the log file. The 
  15837. SOMD_ Init procedure opens the file named in SOMDMESSAGELG (if any), during 
  15838. process initialization. 
  15839.  
  15840.  
  15841. ΓòÉΓòÉΓòÉ 7.20.1. Error codes ΓòÉΓòÉΓòÉ
  15842.  
  15843. The error codes that may be encountered when using DSOM are listed in Appendix 
  15844. A, "SOMobjects Error Codes," which contains the codes for the entire SOMobjects 
  15845. Toolkit. 
  15846.  
  15847.  
  15848. ΓòÉΓòÉΓòÉ 7.20.2. Troubleshooting hints ΓòÉΓòÉΓòÉ
  15849.  
  15850. The following hints may prove helpful as you develop and test your DSOM 
  15851. application. 
  15852.  
  15853.  
  15854. ΓòÉΓòÉΓòÉ 7.20.2.1. Checking the DSOM setup ΓòÉΓòÉΓòÉ
  15855.  
  15856. This checklist will help you make certain that the DSOM environment is set up 
  15857. correctly. 
  15858.  
  15859.    1. Use the somdchk tool to verify the settings of various DSOM environment 
  15860.       variables.  Note that if the SOMIR environment variable contains relative 
  15861.       pathnames, the client programs, server programs, and somdd daemon must be 
  15862.       started from the same directory. (Instead, it is recommended that SOMIR 
  15863.       contain full pathnames.) 
  15864.  
  15865.    2. For all application classes, IDL must be compiled into the Interface 
  15866.       Repository.  You can verify that a class exists in the Interface 
  15867.       Repository by executing "irdump<class>" on AIX or OS/2, or, on Windows, 
  15868.       click on the IRDUMP icon and browse for the appropriate class.  See 
  15869.       "Registering class interfaces" for more information. 
  15870.  
  15871.    3. An implementation (a server program and class libraries) must be 
  15872.       registered with DSOM by running the regimpl utility. See "Registering 
  15873.       servers and classes" for more information. 
  15874.  
  15875.    4. Verify that all class libraries and networking libraries are in 
  15876.       directories specified in LIBPATH. 
  15877.  
  15878.  
  15879. ΓòÉΓòÉΓòÉ 7.20.2.2. Analyzing problem conditions ΓòÉΓòÉΓòÉ
  15880.  
  15881. The DSOM error codes mentioned below can be obtained directly by the 
  15882. application from the "minor" field of the exception data returned in a system 
  15883. exception, or from an error report message when SOMDDEBUG is set to a positive 
  15884. integer value (see the previous topic, "Error reporting"). 
  15885.  
  15886. Symptom:  When running regimpl, a "PERSIST_STORE" or "NO_IMPLEMENT" exception 
  15887. is returned. The DSOM error code is SOMDERROR_IO or SOMDERROR_NoImplDatabase. 
  15888.  
  15889.      This may indicate that the Implementation Repository files are not found 
  15890.       or cannot be accessed. Verify that SOMDDIR is set correctly, to a 
  15891.       directory that has granted read/write permission to the DSOM user. (It is 
  15892.       best if the directory name is fully qualified.) If the SOMDDIR variable 
  15893.       is not set, verify that the default directory ($SOMBASE/etc/dsom on AIX, 
  15894.       and %SOMBASE%\etc\dsom on OS/2 or Windows) has been set up with the 
  15895.       correct permissions. Ensure that the the files contained in the directory 
  15896.       all have read/write permission granted to the DSOM user. 
  15897.  
  15898.  Symptom:  When starting somdd, an "INITIALIZE" exception is returned with 
  15899.  error code SOMDAlreadyRunning. 
  15900.  
  15901.      This indicates that there is already an instance of somdd running.  If 
  15902.       the current instance of somdd does not seem to be responding properly, 
  15903.       delete all instances of somdd and restart a new copy of somdd. 
  15904.  
  15905.  Symptom:  When starting up a server program, an exception is returned with a 
  15906.  DSOM error code of SOMDERROR_ServerAlreadyExists. 
  15907.  
  15908.      This may indicate that a server process that is already running has 
  15909.       already registered itself with the DSOM daemon, somdd, using the 
  15910.       implementation ID of the desired server program. 
  15911.  
  15912.  Symptom: On OS/2, an operating system error occurs indicating a "stack 
  15913.  overflow" condition soon after a the first call to a class DLL. Rebuilding the 
  15914.  DLL with a larger stack size does not help. 
  15915.  
  15916.      This sometimes occurs when a DLL uses, but does not initialize, the  run 
  15917.       time for OS/2. To perform the proper initialization, a function named 
  15918.       "_DLL_InitTerm" must be included in the DLL, and it must invoke the C 
  15919.       Set/2 initialization function, "_CRT_Init."  The _DLL_InitTerm function 
  15920.       is invoked automatically when the DLL is loaded. 
  15921.  
  15922.       An example _DLL_InitTerm function is included in the DSOM sample code 
  15923.       shipped with the SOMobjects Developer Toolkit for OS/2, in the file 
  15924.       "initterm.c". 
  15925.  
  15926.  Symptom: When running a DSOM application that uses EMan, an error message is 
  15927.  displayed asking that the SOMSOCKETS be set. 
  15928.  
  15929.      This may indicate a need to specify the Sockets subclass to be used with 
  15930.       the application. Current choices are TCPIPSockets for TCP/IP (and 
  15931.       TCPIPSockets32 on OS/2), NBSockets for NetBios and IPXSockets for Netware 
  15932.       IPX/SPX. Note:Each SOMobjects package will contain an appropriate subset 
  15933.       of Sockets subclasses. Workstation DSOM includes TCPIPSockets (and 
  15934.       TCPIPSockets32 onOS/2 ) for TCP/IP. Workgroup DSOM also includes 
  15935.       NBSockets for NetBios and IPXSockets for Netware. 
  15936.  
  15937.  Symptom:  A remote method invocation fails and an "INTF_REPOS" exception is 
  15938.  returned. The DSOM error code is SOMDERROR_BadDescriptor or 
  15939.  SOMDERROR_ClassNotlnIR. 
  15940.  
  15941.      This may indicate that the interface describing the method or the method 
  15942.       itself cannot be found in the Interface Repository. Verify that SOMIR is 
  15943.       set correctly, and that the IR contains all interfaces used by your 
  15944.       application. 
  15945.  
  15946.       If the default SOM IR (supplied with the SOMobjects Toolkit and Runtimes) 
  15947.       is not used by the application, the user's IR must include the interface 
  15948.       definitions for the appropriate Sockets class, server class (derived from 
  15949.       SOMDServer), and the definitions of the standard DSOM exceptions (found 
  15950.       in file "stexcep.idl") that may be returned by a method call. 
  15951.  
  15952.  Symptom:  A SOMDERROR_ClassNotFound error is returned by a client either when 
  15953.  creating a remote object using somdNewObject, or when finding a server object 
  15954.  using somdFindAnyServerByClass. (The methods are defined on the SOMDObjectMgr 
  15955.  class.) 
  15956.  
  15957.      This occurs when the class name specified in calls to somdNewObject or 
  15958.       somdFindAnyServerByClass cannot be found in the Implementation 
  15959.       Repository. Make sure that the class name has been associated with at 
  15960.       least one of the server implementations. 
  15961.  
  15962.  Symptom:  A SOMDERROR_ClassNotlnlR error is returned by a server when creating 
  15963.  a new object using somdNewObject, somdCreateObj, or somdGetClassObj. 
  15964.  
  15965.      This error may result if the DLL for the class cannot be found. Verify 
  15966.       hat: 
  15967.  
  15968.            -the interface of the object can be found in the IR; 
  15969.  
  15970.            -the class name is spelled correctly and is appropriately scoped 
  15971.            (for example, the "Printer" class in the "PrintServer" module must 
  15972.            have the identifier "PrintServer:: Printer"). 
  15973.  
  15974.      This error can also result when the shared library is statically linked 
  15975.       to the server program, but the <className>NewClass procedures have not 
  15976.       been called to initialize the classes. 
  15977.  
  15978.  Symptom: When invoking a method returns a proxy for a remote object in the 
  15979.  client, a SOMDERROR_NoParentClass error occurs. 
  15980.  
  15981.      This error may result when the class libraries used to build the proxy 
  15982.       class are statically linked to the program, but the <className>NewClass 
  15983.       procedure have not been called to initialize the classes. 
  15984.  
  15985.  Symptom:  Following a method call, the SOM run-time error message, "A target 
  15986.  object failed basic validity checks during method resolution" is displayed. 
  15987.  
  15988.      Usually this means that the method call was invoked using a bad object 
  15989.       pointer, or the object has been corrupted. 
  15990.  
  15991.  Symptom:  A remote object has an attribute or instance variable that is, or 
  15992.  contains, a pointer to a value in memory (for example, a string, a sequence, 
  15993.  an "any"). The attribute or instance variable value is set by the client with 
  15994.  one method call. When the attribute or instance variable is queried in a 
  15995.  subsequent method call, the value referenced by the pointer is "garbage". 
  15996.  
  15997.      This may occur because DSOM makes a copy  of argument values in a client 
  15998.       call, for use in the remote call. The argument values are valid for the 
  15999.       duration of that call. When the remote call is completed, the copies of 
  16000.       the argument values are freed. 
  16001.  
  16002.       In a DSOM application, a class should not assume ownership of memory 
  16003.       passed to it in a method parameter unless the IDL description of the 
  16004.       method includes the SOM IDL modifier object_owns_parameters.  Otherwise, 
  16005.       if a parameter value is meant to persist between method invocations, then 
  16006.       the object is responsible for making a copy of the parameter value. 
  16007.  
  16008.  Symptom:  A method defines a (char *) parameter that is used to pass a string 
  16009.  input value to an object. The object attempts to print the string value, but 
  16010.  it appears to be "garbage". 
  16011.  
  16012.      DSOM will support method arguments that are of type "pointer-to-X" 
  16013.       (pointer types are a SOM extension), by dereference the pointer in the 
  16014.       call, and copying the base value. The pointer-to-value is reconstructed 
  16015.       on the server before the actual method call is made. 
  16016.  
  16017.       While (char *) is commonly used to refer to NULL-terminated strings in C 
  16018.       programs, (char *) could also be a pointer to a single character or to an 
  16019.       array of characters. Thus, DSOM interprets the argument type literally as 
  16020.       a pointer-to-one-character. 
  16021.  
  16022.       To correctly pass strings or array arguments, the appropriate CORBA type 
  16023.       should be used (for example, "string" or "char foo[4 ]"). 
  16024.  
  16025.  Symptom:  A segmentation violation occurs when passing an "any" argument to a 
  16026.  method call, where the "any" value is a string, array, or object reference. 
  16027.  Note: The NamedValues used in DII calls use "any" fields for the argument 
  16028.  values. 
  16029.  
  16030.      This error may occur because the  "_value"  field of the "any" structure 
  16031.       does not contain the address of a pointer to the target string, array, or 
  16032.       object reference, as it should. (A common mistake is to set the "_value" 
  16033.       field to the address of the string, array, or object reference itself.) 
  16034.  
  16035.  Symptom:  When a server program or a server object makes a call to get_id or 
  16036.  to get_SOM_object on a SOMDObject, a "BAD_OPERATION" exception is returned 
  16037.  with an error code of SOMDERROR_WrongRefType. 
  16038.  
  16039.      This error may occur when the operation get_id is called on a SOMDObject 
  16040.       that does not have any user-supplied ReferenceData (that is, the 
  16041.       SOMDObject is a proxy, is nil, or is a simple "SOM ref" created by 
  16042.       create_SOM_ref). Likewise, this error may occur when the operation 
  16043.       get_SOM_object is called on a SOMDObject that was not created by the 
  16044.       create_SOM_ref method. 
  16045.  
  16046.  Symptom:  A segmentation fault occurs when a SOMD_Uninit call is executed. 
  16047.  
  16048.      This error could occur if the application has already freed any of the 
  16049.       DSOM run-time objects that were allocated by the SOMD_Init call, 
  16050.       including SOMD_ObjectMgr, SOMD_ImplRepObject and SOMD_ORBObject. 
  16051.  
  16052.  Symptom:  Unexplained program crashes. 
  16053.  
  16054.      Verify that all DSOM environment variables are set, as described in the 
  16055.       earlier section "Configuring DSOM Applications". Verify that all class 
  16056.       libraries are in directories specified in LIBPATH for AIX and OS/2, or 
  16057.       specified in PATH for Windows. Verify that the contents of the Interface 
  16058.       Repository, specified by SOMIR, are correct. Verify that the contents of 
  16059.       the Implementation Repository, specified by SOMDDIR, are correct. Verify 
  16060.       that somdd is running. Set SOMDDEBUG to 1 to obtain additional DSOM error 
  16061.       messages. 
  16062.  
  16063.  Symptom:  When starting somdd, an "INITIALIZE" error is returned with error 
  16064.  code SOMDERROR_NoSocketsClass. 
  16065.  
  16066.      If SOMSOCKETS is set, verify that the IR contains the appropriate Sockets 
  16067.       interface definition. 
  16068.  
  16069.  
  16070. ΓòÉΓòÉΓòÉ 7.21. Limitations ΓòÉΓòÉΓòÉ
  16071.  
  16072. The following list indicates known limitations of Distributed SOM at the time 
  16073. of this release. 
  16074.  
  16075.    1. Currently, objects cannot be moved from one server to another without 
  16076.       changing the object references (i.e., deleting the object, and creating 
  16077.       it anew in another server). This yields all copies of the previous 
  16078.       reference invalid. 
  16079.  
  16080.    2. The change_implementation method is not supported. This method, defined 
  16081.       by the BOA interface, is intended to allow an application to change the 
  16082.       implementation definition associated with an object. However, in DSOM, 
  16083.       changing the server implementation definition may render existing object 
  16084.       references (which contain the old server ID) invalid. 
  16085.  
  16086.    3. Currently, DSOM has a single server activation policy, which corresponds 
  16087.       to CORBA's "shared" activation policy for dynamic activation, and 
  16088.       "persistent" activation policy for manual activation. Other activation 
  16089.       policies, such as "server-per-method" and "unshared" are not directly 
  16090.       supported, and must be implemented by the application. 
  16091.  
  16092.       Since the unshared server policy is not directly supported, the 
  16093.       object_is_ready and deactivate_obj methods, defined in the BOA interface 
  16094.       have null implementations. 
  16095.  
  16096.    4. If a server program terminates without calling deactivate_impl, 
  16097.       subsequent attempts to start that server may fail. The DSOM daemon 
  16098.       believes the server is still running until it is told it has stopped. 
  16099.       Attempts to start a server that is believed to be exist results in an 
  16100.       error (SOMDERROR_ServerAlreadyExists). 
  16101.  
  16102.    5. Currently, file names used in ImplementationDefs are limited to 255 
  16103.       bytes. Implementations aliases used in ImplementationDefs are limited to 
  16104.       50 bytes. Class names used in the Implementation Repository are limited 
  16105.       to 50 bytes. Hostnames are limited to 32 bytes. 
  16106.  
  16107.    6. The OUT_LIST_MEMORY, IN_COPY_VALUE, and DEPENDENT_LIST flags, used with 
  16108.       Dynamic Invocation Interface, are not yet supported. 
  16109.  
  16110.    7. The Context::get_values method currently does not support the flag 
  16111.       CTX_RESTRICT_SCOPE. 
  16112.  
  16113.  Other important notes concerning DSOM are documented in the "README" file in 
  16114.  the SOMBASE root directory ($SOMBASE on AIX, and %SOMBASE% on OS/2 or 
  16115.  Windows). 
  16116.  
  16117.  
  16118. ΓòÉΓòÉΓòÉ 8. The SOM Interface Repository Framework ΓòÉΓòÉΓòÉ
  16119.  
  16120. This section covers the following subjects: 
  16121.  
  16122.      Introduction 
  16123.      Using the SOM Compiler to Build an Interface Repository 
  16124.      Managing Interface Repository files 
  16125.      Programming with the Interface Repository Objects 
  16126.  
  16127.  
  16128. ΓòÉΓòÉΓòÉ 8.1. Introduction ΓòÉΓòÉΓòÉ
  16129.  
  16130. The SOM Interface Repository (IR) is a database that the SOM Compiler 
  16131. optionally creates and maintains from the information supplied in IDL source 
  16132. files. The Interface Repository contains persistent objects that correspond to 
  16133. the major elements in IDL descriptions. The SOM Interface Repository Framework 
  16134. is a set of classes that provide methods whereby executing programs can access 
  16135. these objects to discover everything known about the programming interfaces of 
  16136. SOM classes. 
  16137.  
  16138. The programming interfaces used to interact with Interface Repository objects, 
  16139. as well as the format and contents of the information they return, are 
  16140. architected and defined as part of the Object Management Group's CORBA 
  16141. standard. The classes composing the SOM Interface Repository Framework 
  16142. implement the programming interface to the CORBA Interface Repository. 
  16143. Accordingly, the SOM Interface Repository Framework supports all of the 
  16144. interfaces described in The Common Object Request Broker: Architecture and 
  16145. Specification (OMG Document Number 91.12.1, Revision 1.1, chapter 7). 
  16146.  
  16147. As an extension to the CORBA standard, the SOM Interface Repository Framework 
  16148. permits storage in the Interface Repository of arbitrary information in the 
  16149. form of SOM IDL modifiers. That is, within the SOM-unique implementation 
  16150. section of an IDL source file or through the use of the #pragma modifier 
  16151. statement, user-defined modifiers can be associated with any element of an IDL 
  16152. specification. (See the section entitled "SOM Interface Definition Language" in 
  16153. Chapter 4, "SOM IDL and the SOM Compiler.") When the SOM Compile creates the 
  16154. Interface Repository from an IDL specification, these potentially arbitrary 
  16155. modifiers are stored in the IR and can then be accessed via the methods 
  16156. provided by the Interface Repository Framework. 
  16157.  
  16158. This chapter describes, first, how to build and manage interface repositories, 
  16159. and second, the programming interfaces embodied in the SOM Interface Repository 
  16160. Framework. 
  16161.  
  16162.  
  16163. ΓòÉΓòÉΓòÉ 8.2. Using the SOM Compiler to Build an Interface Repository ΓòÉΓòÉΓòÉ
  16164.  
  16165. The SOMobjects Toolkit includes an Interface Repository emitter that is invoked 
  16166. whenever the SOM Compiler is run using an sc command with the -u option (which 
  16167. "updates" the interface repository). The IR emitter can be used to create or 
  16168. update an Interface Repository file. The IR emitter expects that an environment 
  16169. variable, SOMIR, was first set to designate a file name for the Interface 
  16170. Repository. For example, to compile an IDL source file named "newcls.idl" and 
  16171. create an Interface Repository named "newcls.ir", use a command sequence 
  16172. similar to the following: 
  16173.  
  16174. For OS/2: 
  16175.  
  16176. set SOMIR=c:\myfiles\newcls.ir
  16177. sc -u newcls
  16178.  
  16179. For AIX: 
  16180.  
  16181. export SOMIR=~/newcls.ir
  16182. sc -u newcls
  16183.  
  16184. If the SOMIR environment variable is not set, the Interface Repository emitter 
  16185. creates a file named "som.ir" in the current directory. 
  16186.  
  16187. The sc or somc command runs the Interface Reposito emitter plus any other 
  16188. emitters indicated by the environment variable SMEMIT (described in the topic 
  16189. "Running the SOM Compiler" in Chapter 4, "Implementing SOM Classes"). To run 
  16190. the Interface Repository emitter by itself, issue the sc command with the -s 
  16191. option (which overrides SMEMIT) set to "ir". For example: 
  16192.  
  16193. sc -u -sir newcls        (ON OS/2 or AIX)
  16194. somc -u -sir newcls      (On Windows)
  16195. or equivalently, 
  16196.  
  16197. sc -usir newcls          (On OS/2 or AIX)
  16198. somc -usir newcls        (On Windows)
  16199.  
  16200. The Interface Repository emitter uses the SOMIR environment variable to locate 
  16201. the designated IR file. If the file does not exist, the IR emitter creates it. 
  16202. If the named interface repository already exists, the IR emitter checks all of 
  16203. the "type" information in the IDL source file being compiled for internal 
  16204. consistency, and then changes the contents of the interface repository file to 
  16205. agree with with the new IDL definition. For this reason, the use of the -u 
  16206. compiler flag requires that all of the types mentioned in the IDL source file 
  16207. must be fully defined within the scope of the compilation. Warning messages 
  16208. from the SOM Compiler about undefined types result in actual error messages 
  16209. when using the -u flag. 
  16210.  
  16211. The additional type checking and file updating activity implied by the -u flag 
  16212. increases the time it takes to run the SOM Compiler. Thus, when developing an 
  16213. IDL class description from scratch, where iterative changes are to be expected, 
  16214. it may be preferable not to use the -u compiler option until the class 
  16215. definition has stabilized. 
  16216.  
  16217.  
  16218. ΓòÉΓòÉΓòÉ 8.3. Managing Interface Repository files ΓòÉΓòÉΓòÉ
  16219.  
  16220. Just as the number of interface definitions contained in a single IDL source 
  16221. file is optional, similarly, the number of IDL files compiled into one 
  16222. interface repository file is also at the programmer's discretion. Commonly, 
  16223. however, all interfaces needed for a single project or class framework are kept 
  16224. in one interface repository. 
  16225.  
  16226.  
  16227. ΓòÉΓòÉΓòÉ 8.3.1. The SOM  IR file "som.ir" ΓòÉΓòÉΓòÉ
  16228.  
  16229. The SOMobjects Toolkit includes an Interface Repository file ("som.ir") that 
  16230. contains objects describing all of the types, classes, and methods provided by 
  16231. the various frameworks of the SOMobjects Toolkit. Since all new classes will 
  16232. ultimately be derived from these predefined SOM classes, some of this 
  16233. information also needs to be included in a programmer's own interface 
  16234. repository files. 
  16235.  
  16236. For example, suppose a new class, called "MyClass", is derived from SOMObject. 
  16237. When the SOM Compiler builds an Interface Repository for "MyClass", that IR 
  16238. will also include all of the information associated with the SOMObject class. 
  16239. This happens because the SOMObject class definition is inherited by each new 
  16240. class; thus, all of the SOMObject methods and typedefs are implicitly contained 
  16241. in the new class as well. 
  16242.  
  16243. Eventually, the process of deriving new classes from existing ones would lead 
  16244. to a great deal of duplication of information in separate interface repository 
  16245. files. This would be inefficient, wasteful of space, and extremely difficult to 
  16246. manage. For example, to make an evolutionary change to some class interface, a 
  16247. programmer would need to know about and subsequently update all of the 
  16248. interface repository files where information about that interface occurred. 
  16249.  
  16250. One way to avoid this dilemma would be to keep all interface definitions in a 
  16251. single interface repository (such as "som.ir"). This is not recommended, 
  16252. however. A single interface repository would soon grow to be unwieldy in size 
  16253. and become a source of frequent access contention. Everyone involved in 
  16254. developing class definitions would need update access to this one file, and 
  16255. simultaneous uses might result in longer compile times. 
  16256.  
  16257.  
  16258. ΓòÉΓòÉΓòÉ 8.3.2. Managing IRs via the SOMIR environment variable ΓòÉΓòÉΓòÉ
  16259.  
  16260. The SOMobjects Toolkit offers a more flexible approach to managing interface 
  16261. repositories. The SOMIR environment variable can reference an ordered list of 
  16262. separate IR files, which process from left to right. Taken as a whole, however, 
  16263. this gives the appearance of a single, logical interface repository. A 
  16264. programmer accessing the contents of "the interface repository" through the SOM 
  16265. Interface Repository framework would not be aware of the division of 
  16266. information across separate files. It would seem as though all of the objects 
  16267. resided in a single interface repository file. 
  16268.  
  16269. A typical way to utilize this capability is as follows: 
  16270.  
  16271.      The first (leftmost) Interface Repository in the SOMIR list would be 
  16272.       "som.ir". This file contains the basic interfaces and types needed in all 
  16273.       SOM classes. 
  16274.  
  16275.      The second file in the list might contain interface definitions that are 
  16276.       used globally across a particular enterprise. 
  16277.  
  16278.      A third interface repository file would contain definitions that are 
  16279.       unique to a particular department, and so on. 
  16280.  
  16281.      The final interface repository in the list should be set aside to hold 
  16282.       the interfaces needed for the project currently under development. 
  16283.  
  16284.  Developers working on different projects would each set their SOMIR 
  16285.  environment variables to hold slightly different lists. For the most part, the 
  16286.  leftmost portions of these lists would be the same, but the rightmost 
  16287.  interface repositories would differ. When any given developer is ready to 
  16288.  share his/her interface definitions with other people outside of the immediate 
  16289.  work group, that person's interface repository can be promoted to inclusion in 
  16290.  the master list. 
  16291.  
  16292.  With this arrangement of IR files, the more stable repositories are found at 
  16293.  the left end of the list. For example, a developer should never need to make 
  16294.  any significant changes to "som.ir", because these interfaces are defined by 
  16295.  IBM and would only change with a new release of the SOMobjects Toolkit. 
  16296.  
  16297.  The Interface Repository Framework only permits updates in the rightmost file 
  16298.  of the SOMIR interface repository list. That is, when the SOM Compiler -u flag 
  16299.  is used to update the Interface Repository, only the final file on the IR list 
  16300.  will be affected. The information in all preceding interface repository files 
  16301.  is treated as "read only".  Therefore, to change the definition of an 
  16302.  interface in one of the more global interface repository files, a developer 
  16303.  must overtly construct a special SOMIR list that omits all subsequent (that 
  16304.  is, further to the right) interface repository files, or else petition the 
  16305.  owner of that interface to make the change. 
  16306.  
  16307.  It is important the the rightmost filename in the SOMIR interface repository 
  16308.  list not appear elsewhere in the list.  For Example, the following setting for 
  16309.  SOMIR: 
  16310.  
  16311.        %SOMBASE5\ETC\SOM.IR;SOM.IR;C:\IR\COMPANY.IR;SOM.IR
  16312.  
  16313.  would cause problems when attempting to update the SOM.IR file, because SOM.IR 
  16314.  appears twice in the list. 
  16315.  
  16316.  Here is an example that illustrates the use of multiple IR files with the 
  16317.  SOMIR environment variable. In this example, the SOMBASE environment variable 
  16318.  represents the directory in which the SOMobjects Toolkit files have been 
  16319.  installed. Only the "myown.ir" interface repository file will be updated with 
  16320.  the interfaces found in files "myclass1.idl", "myclass2.idl", and 
  16321.  "myclass3.idl". 
  16322.  
  16323.  For OS/2: 
  16324.  
  16325.   set BASE_IRLIST=%SOMBASE%\IR\SOM.IR;C:\IR\COMPANY.IR;C:\IR\DEPT10.IR
  16326.   set SOMIR=%BASE_IRLIST%;D:\MYOWN.IR
  16327.   set SMINCLUDE=.;%SOMBASE%\INCLUDE;C:\COMPANY\INCLUDE;C:\DEPT10\INCLUDE
  16328.   sc -usir myclass1
  16329.   sc -usir myclass2
  16330.   sc -usir myclass3
  16331.  
  16332.  For AIX: 
  16333.  
  16334.   export BASE_IRLIST=$SOMBASE/ir/som.ir:/usr/local/ir/comany.ir:\
  16335.       /usr/local/ir/dept10.ir
  16336.   export SOMIR=$BASE_IRLIST:~/myown.ir
  16337.   export SMINCLUDE=.:$SOMBASE/INCLUDE:/usr/local/company/include:\
  16338.       /usr/local/dept10/include
  16339.   sc -usir myclass1
  16340.   sc -usir myclass2
  16341.   sc -usir myclass3
  16342.  
  16343.  
  16344. ΓòÉΓòÉΓòÉ 8.3.3. Placing 'private' information in the Interface Repository ΓòÉΓòÉΓòÉ
  16345.  
  16346. When the SOM Compiler updates the Interface Repository in response to the -u 
  16347. flag, it uses all of the information available from the IDL source file. 
  16348. However, if the __PRIVATE__ preprocessor variable is used to designate certain 
  16349. portions of the IDL file as private, the preprocessor actually removes that 
  16350. information before the SOM Compiler sees it. Consequently, private information 
  16351. will not appear in the Interface Repository unless the -p compiler option is 
  16352. also used in conjunction with -u. For example: 
  16353.  
  16354. sc -up myclass1          (On AIX or OS/2)
  16355. somc -up myclass1        (On Windows)
  16356.  
  16357. This command will place all of the information in the "myclass1.idl" file, 
  16358. including the private portions, in the Interface Repository. 
  16359.  
  16360. If you are using tools that understand SOM and rely on the Interface Repository 
  16361. to describe the types and instance data in your classes, you may need to 
  16362. include the private sections from your IDL source files when building the 
  16363. Interface Repository. 
  16364.  
  16365.  
  16366. ΓòÉΓòÉΓòÉ 8.4. Programming with the Interface Repository Objects ΓòÉΓòÉΓòÉ
  16367.  
  16368. The SOM Interface Repository Framework provides an object-oriented programming 
  16369. interface to the IDL information processed by the SOM Compiler. Unlike many 
  16370. frameworks that require you to inherit their behavior in order to use it, the 
  16371. Interface Repository Framework is useful in its own right as a set of 
  16372. predefined objects that you can access to obtain information. Of course, if you 
  16373. need to subclass a class to modify its behavior, you can certainly do so; but 
  16374. typically this is not necessary. 
  16375.  
  16376. The SOM Interface Repository contains the fully-analyzed (compiled) contents of 
  16377. all information in an IDL source file. This information takes the the form of 
  16378. persistent objects that can be accessed from a running program. There are ten 
  16379. classes of objects in the Interface Repository that correspond directly to the 
  16380. major elements in IDL source files; in addition, one instance of another class 
  16381. exists outside of the IR itself, as follows: 
  16382.  
  16383.  Contained                All objects in the Interface Repository are instances 
  16384.                           of classes derived from this class and exhibit the 
  16385.                           common behavior defined in this interface. 
  16386.  
  16387.  Container                Some objects in the Interface Repository hold (or 
  16388.                           contain) other objects. (For example, a module 
  16389.                           [ModuleDef] can contain an interface [InterfaceDef].) 
  16390.                           All Interface Repository objects that hold other 
  16391.                           objects are instances of classes derived from this 
  16392.                           class and exhibit the common behavior defined by this 
  16393.                           class. 
  16394.  
  16395.  ModuleDef                An instance of this class exists for each module 
  16396.                           defined in an IDL source file. ModuleDefs are 
  16397.                           Containers, and they can  hold ConstantDefs, 
  16398.                           TypeDefs,  ExceptionDefs, InterfaceDefs, and other 
  16399.                           ModuleDefs. 
  16400.  
  16401.  InterfaceDef             An instance of this class exists for each interface 
  16402.                           named in an IDL source file. (One InterfaceDef 
  16403.                           corresponds to one SOM class.)  InterfaceDefs are 
  16404.                           Containers, and they can hold ConstantDefs, TypeDefs, 
  16405.                           ExceptionDefs, AttributeDefs, and OperationDefs. 
  16406.  
  16407.  AttributeDef             An instance of this class exists for each attribute 
  16408.                           defined in an IDL source file. AttributeDefs are 
  16409.                           found only inside of (contained by) InterfaceDefs. 
  16410.  
  16411.  OperationDef             An instance of this class exists for each operation 
  16412.                           (method, _set_method, and _get_method) defined in an 
  16413.                           IDL source file. OperationDefs are Containers that 
  16414.                           can hold ParameterDefs. OperationDefs are found only 
  16415.                           inside of (contained by) InterfaceDefs. 
  16416.  
  16417.  ParameterDef             An instance of this class exists for each parameter 
  16418.                           of each operation (method) defined in an IDL source 
  16419.                           file. ParameterDefs are found only inside of 
  16420.                           (contained by) OperationDefs. 
  16421.  
  16422.  TypeDef                  An instance of this class exists for each typedef, 
  16423.                           struct, union, or enum defined in an IDL source file. 
  16424.                           TypeDefs may be found inside of (contained by) any 
  16425.                           Interface Repository Container except an 
  16426.                           OperationDef. 
  16427.  
  16428.  ConstantDef              An instance of this class exists for each constant 
  16429.                           defined in an IDL source file. ConstantDefs may be 
  16430.                           found inside (contained by) of any Interface 
  16431.                           Repository Container except an OperationDef. 
  16432.  
  16433.  ExceptionDef             An instance of this class exists for each exception 
  16434.                           defined in an IDL source file. ExceptionDefs may be 
  16435.                           found inside of (contained by) any Interface 
  16436.                           Repository Container except an OperationDef. 
  16437.  
  16438.  Repository               One instance of this class exists for the entire SOM 
  16439.                           Interface Repository, to hold IDL elements that are 
  16440.                           global in scope. The instance of this class does not, 
  16441.                           however, reside within the IR itself. 
  16442.  
  16443.  
  16444. ΓòÉΓòÉΓòÉ 8.4.1. Methods introduced by Interface Repository classes ΓòÉΓòÉΓòÉ
  16445.  
  16446. The Interface Repository classes introduce nine new methods, which are briefly 
  16447. described below. Many of the classes simply override methods to customize them 
  16448. for the corresponding IDL element; this is particularly true for classes 
  16449. representing IDL elements that are only contained within another syntactic 
  16450. element. Full descriptions of each method are found in the SOMobjects Developer 
  16451. Toolkit: Programmers Reference Manual. 
  16452.  
  16453.      Contained class methods (all IR objects are instances of this class and 
  16454.       exhibit this behavior): 
  16455.  
  16456.       describe                      Returns a structure of type Description 
  16457.                                     containing all information defined in the 
  16458.                                     IDL specification of the syntactic element 
  16459.                                     corresponding to the target Contained 
  16460.                                     object. For example, for a target 
  16461.                                     InterfaceDef object, the describe method 
  16462.                                     returns information about the IDL interface 
  16463.                                     declaration. The Description structure 
  16464.                                     contains a "name" field with an identifier 
  16465.                                     that categorizes the description (such as, 
  16466.                                     "InterfaceDescription") and a "value" field 
  16467.                                     holding an "any" structure that points to 
  16468.                                     another structure containing the IDL 
  16469.                                     information for that particular element (in 
  16470.                                     this example, the interface's IDL 
  16471.                                     specifications). 
  16472.  
  16473.       within                        Returns a sequence designating the 
  16474.                                     object(s) of the IR within which the target 
  16475.                                     Contained object is contained. For example, 
  16476.                                     for a target TypeDef object, it might be 
  16477.                                     contained within any other IR object(s) 
  16478.                                     except an OperationDef object. 
  16479.  
  16480.      Container class methods (some IR objects contain other objects and 
  16481.       exhibit this behavior): 
  16482.  
  16483.       contents                      Returns a sequence of pointers to the 
  16484.                                     object(s) of the IR that the target 
  16485.                                     Container object contains. (For example, 
  16486.                                     for a target InterfaceDef object, the 
  16487.                                     contents method returns a pointer to each 
  16488.                                     IR object that corresponds to a part of the 
  16489.                                     IDL interface declaration.) The method 
  16490.                                     provides options for excluding inherited 
  16491.                                     objects or for limiting the search to only 
  16492.                                     a specified kind of object (such as 
  16493.                                     AttributeDefs). 
  16494.  
  16495.       describe_contents             Combines the describe and contents methods; 
  16496.                                     returns a sequence of ContainerDescription 
  16497.                                     structures, one for each object contained 
  16498.                                     by the target Container object. Each 
  16499.                                     structure has a pointer to the related 
  16500.                                     object, as well as "name" and "value" 
  16501.                                     fields resulting from the describe method. 
  16502.  
  16503.       lookup_name                   Returns a sequence of pointers to objects 
  16504.                                     of a given name contained within a 
  16505.                                     specified Container object, or within 
  16506.                                     (sub)objects contained in the specified 
  16507.                                     Container object. 
  16508.  
  16509.      ModuleDef class methods: 
  16510.  
  16511.                                     Override describe and within. 
  16512.  
  16513.      InterfaceDef class methods: 
  16514.  
  16515.       describe_interface            Returns a description of all methods and 
  16516.                                     attributes of a given interface definition 
  16517.                                     object that are held in the Interface 
  16518.                                     Repository. 
  16519.  
  16520.                                     Also overrides describe and within. 
  16521.  
  16522.      AttributeDef class method: 
  16523.  
  16524.                                     Overrides describe. 
  16525.  
  16526.      OperationDef class method: 
  16527.  
  16528.                                     Overrides describe. 
  16529.  
  16530.      ParameterDef class method: 
  16531.  
  16532.                                     Overrides describe. 
  16533.  
  16534.      TypeDef  class method: 
  16535.  
  16536.                                     Overrides describe. 
  16537.  
  16538.      ConstantDef class method: 
  16539.  
  16540.                                     Overrides describe. 
  16541.  
  16542.      ExceptionDef class method: 
  16543.  
  16544.                                     Overrides describe. 
  16545.  
  16546.      Repository class methods: 
  16547.  
  16548.       lookup_id                     Returns the Contained object that has a 
  16549.                                     specified RepositoryId. 
  16550.  
  16551.       lookup_modifier               Returns the string value held by a SOM or 
  16552.                                     user-defined modifier, given the name and 
  16553.                                     type of the modifier, and the name of the 
  16554.                                     object that contains the modifier. 
  16555.  
  16556.       release_cache                 Releases, from the internal object cache, 
  16557.                                     the storage used by all currently 
  16558.                                     unreferenced Interface Repository objects. 
  16559.  
  16560.  
  16561. ΓòÉΓòÉΓòÉ 8.4.2. Accessing objects in the Interface Repository ΓòÉΓòÉΓòÉ
  16562.  
  16563. As mentioned above, one instance of the Repository  class exists for the entire 
  16564. SOM Interface Repository. This object does not, itself, reside in the Interface 
  16565. Repository (hence it does not exhibit any of the behavior defined by the 
  16566. Contained class). It is, however, a Container, and it holds all ConstantDefs, 
  16567. TypeDefs, ExceptionDefs, InterfaceDefs, and ModuleDefs that are global in scope 
  16568. (that is, not contained inside of any other Containers). 
  16569.  
  16570. When any method provided by the Repository class is used to locate other 
  16571. objects in the Interface Repository, those objects are automatically 
  16572. instantiated and activated. Consequently, when the program is finished using an 
  16573. object from the Interface Repository, the client code should release the object 
  16574. using the somFree method. 
  16575.  
  16576. All objects contained in the Interface Repository have both a "name" and a 
  16577. "Repository ID" associated with them. The name is not guaranteed to be unique, 
  16578. but it does uniquely identify an object within the context of the object that 
  16579. contains it. The Repository ID of each object is guaranteed to uniquely 
  16580. identify that object, regardless of its context. 
  16581.  
  16582. For example, two TypeDef objects may have the same name, provided they occur in 
  16583. separate name scopes (ModuleDefs or InterfaceDefs). In this case, asking the 
  16584. Interface Repository to locate the TypeDef object based on its name would 
  16585. result in both TypeDef objects being returned. On the other hand, if the name 
  16586. is looked up from a particular  ModuleDef or InterfaceDef object, only the 
  16587. TypeDef object within the scope of that ModuleDef or InterfaceDef would be 
  16588. returned. By contrast, once the Repository ID of an object is known, that 
  16589. object can always be directly obtained from the Repository object via its 
  16590. Repository ID. 
  16591.  
  16592. C or C++ programmers can obtain an instance of the Repository class using the 
  16593. RepositoryNew macro. Programmers using other languages (and C/C++ programmers 
  16594. without static linkage to the Repository class) should invoke the method 
  16595. somGetInterfaceRepository on the SOMClassMgrObject . For example, 
  16596.  
  16597. For C or C++ (static linkage): 
  16598.  
  16599. #include <repostry.h>
  16600. Repository repo;
  16601.  
  16602. repo = RepositoryNew();
  16603.  
  16604. From other languages (and for dynamic linkage in C/C++): 
  16605.  
  16606.    1. Use the somEnvironmentNew function to obtain a pointer to the 
  16607.       SOMClassMgrObject, as described in Chapter 3, "Using SOM Classes." 
  16608.  
  16609.    2. Use the somResolve or somResolveByName function to obtain a pointer to 
  16610.       the somGetInterfaceRepository method procedure. 
  16611.  
  16612.    3. Invoke the method procedure on the SOMClassMgrObject, with no additional 
  16613.       arguments, to obtain a pointer to the Repository object. 
  16614.  
  16615.  After obtaining a pointer to the Repository object, use the methods it 
  16616.  inherits from Container or its own lookup_id method to instantiate objects in 
  16617.  the Interface Repository. As an example, the contents method shown in the C 
  16618.  fragment below activates every object with global scope in the Interface 
  16619.  Repository and returns a sequence containing a pointer to every global object: 
  16620.  
  16621.   #include <containd.h>      /* Behavior common to all
  16622.   IR objects */
  16623.   Environment *ev;
  16624.   int i;
  16625.   sequence(Contained) everyGlobalObject;
  16626.  
  16627.   ev = SOM_CreateLocalEnvironment(); /* Get an environment to use */
  16628.   printf ("Every global object in the Interface Repository:\n");
  16629.  
  16630.   everyGlobalObject = Container_contents (repo, ev, "all", TRUE);
  16631.  
  16632.   for (i=0; i < everyGlobalObject._length; i++) {
  16633.       Contained aContained;
  16634.  
  16635.       aContained = (Contained) everyGlobalObject._buffer[i];
  16636.       printf ("Name: %s, Id: %s\n",
  16637.           Contained__get_name (aContained, ev),
  16638.           Contained__get_id (aContained, ev));
  16639.       SOMObject_somFree (aContained);
  16640.   }
  16641.  
  16642.  Taking this example one step further, here is a complete program that accesses 
  16643.  every object in the entire Interface Repository. It, too, uses the contents 
  16644.  method, but this time recursively calls the contents method until every object 
  16645.  in every container has been found: 
  16646.  
  16647.   #include <stdio.h>
  16648.   #include <containd.h>
  16649.   #include <repostry.h>
  16650.  
  16651.   void showContainer (Container c, int *next);
  16652.  
  16653.   main ()
  16654.   {
  16655.       int count = 0;
  16656.       Repository repo;
  16657.  
  16658.       repo = RepositoryNew ();
  16659.       printf ("Every object in the Interface Repository:\n\n");
  16660.       showContainer ((Container) repo, &count);
  16661.       SOMObject_somFree (repo);
  16662.       printf ("%d objects found\n", count);
  16663.       exit (0);
  16664.   }
  16665.  
  16666.   void showContainer (Container c, int *next)
  16667.   {
  16668.       Environment *ev;
  16669.       int i;
  16670.       sequence(Contained) everyObject;
  16671.  
  16672.       ev = SOM_CreateLocalEnvironment (); /* Get an environment */
  16673.       everyObject = Container_contents (c, ev, "all", TRUE);
  16674.  
  16675.       for (i=0; i<everyObject._length; i++) {
  16676.           Contained aContained;
  16677.  
  16678.           (*next)++;
  16679.           aContained = (Contained) everyObject._buffer[i];
  16680.           printf ("%6d. Type: %-12s id: %s\n", *next,
  16681.               SOMObject_somGetClassName (aContained),
  16682.               Contained__get_id (aContained, ev));
  16683.           if (SOMObject_somIsA (aContained, _Container))
  16684.               showContainer ((Container) aContained, next);
  16685.           SOMObject_somFree (aContained);
  16686.       }
  16687.   }
  16688.  
  16689.  Once an object has been retrieved, the methods and attributes appropriate for 
  16690.  that particular object can then be used to access the information contained in 
  16691.  the object. The methods supported by each class of object in the Interface 
  16692.  Repository, as well as the classes themselves, are documented in the 
  16693.  SOMobjects Developer Toolkit: Programmers Reference Manual. 
  16694.  
  16695.  
  16696. ΓòÉΓòÉΓòÉ 8.4.3. A word about memory management ΓòÉΓòÉΓòÉ
  16697.  
  16698. Several conventions are built into the SOM Interface Repository with regard to 
  16699. memory management. You will need to understand these conventions to know when 
  16700. it is safe and appropriate to free memory references and also when it is your 
  16701. responsibility to do so. 
  16702.  
  16703. All methods that access attributes (such as, the _get_<attribute> methods) 
  16704. always return either simple values or direct references to data within the 
  16705. target object. This is necessary because these methods are heavily used and 
  16706. must be fast and efficient. Consequently, you should never free any of the 
  16707. memory references obtained through attributes. This memory will be released 
  16708. automatically when the object that contains it is freed. 
  16709.  
  16710. For all methods that give out object references (there are five: within, 
  16711. contents, lookup_name, lookup_id, and describe_contents), when finished with 
  16712. the object, you are expected to release the object reference by invoking the 
  16713. somFree method. (This is illustrated in the sample program that accesses all 
  16714. Interface Repository objects.) Do not release the object reference until you 
  16715. have either copied or finished using all of the information obtained from the 
  16716. object. 
  16717.  
  16718. The describe methods (describe, describe_contents, and describe_interface) 
  16719. return structures and sequences that contain information. The actual structures 
  16720. returned by these methods are passed by value (and hence should only be freed 
  16721. if you have allocated the memory used to receive them). However, you may be 
  16722. required to free some of the information contained in the returned structures 
  16723. when you are finished. Consult the specific method in the SOMobjects Developer 
  16724. Toolkit: Programmers Reference Manual for more details about what to free. 
  16725.  
  16726. During execution of the describe and lookup methods, sometimes intermediate 
  16727. objects are activated automatically. These objects are kept in an internal 
  16728. cache of objects that are in use, but for which no explicit object references 
  16729. have been returned as results. Consequently, there is no way to identify or 
  16730. free these objects individually. However, whenever your program is finished 
  16731. using all of the information obtained thus far from the Interface Repository, 
  16732. invoking the release_cache method causes the Interface Repository to purge its 
  16733. internal cache of these implicitly referenced objects. This cache will 
  16734. replenish itself automatically if the need to do so subsequently arises. 
  16735.  
  16736.  
  16737. ΓòÉΓòÉΓòÉ 8.4.4. Using TypeCode pseudo-objects ΓòÉΓòÉΓòÉ
  16738.  
  16739. Much of the detailed information contained in Interface Repository objects is 
  16740. represented in the form of TypeCodes. TypeCodes are complex data structures 
  16741. whose actual representation is hidden. A TypeCode is an architected way of 
  16742. describing in complete detail everything that is known about a particular data 
  16743. type in the IDL language, regardless of whether it is a (built-in) basic type 
  16744. or a  (user-defined) aggregate  type. 
  16745.  
  16746. Conceptually, every TypeCode contains a "kind" field (which classifies it), and 
  16747. one or more parameters that carry descriptive information appropriate for that 
  16748. particular category of TypeCode. For example, if the data type is long, its 
  16749. TypeCode would contain a "kind" field with the value tk_long. No additional 
  16750. parameters are needed to completely describe this particular data type, since 
  16751. long is a basic type in the IDL language. 
  16752.  
  16753. By contrast, if the TypeCode describes an IDL struct, its "kind" field would 
  16754. contain the value tk_struct, and it would possess the following parameters: a 
  16755. string giving the name of the struct, and two additional parameters for each 
  16756. member of the struct: a string giving the member name and another (inner) 
  16757. TypeCode representing the member's type. This example illustrates the fact that 
  16758. TypeCodes can be nested and arbitrarily complex, as appropriate to express the 
  16759. type of data they describe. Thus, a structure that has N members will have a 
  16760. TypeCode of tk_struct with 2N+1 parameters (a name and TypeCode parameter for 
  16761. each member, plus a name for the struct itself). 
  16762.  
  16763. A tk_union TypeCode representing a union with N members has 3N+2 parameters: 
  16764. the type name of the union, the switch TypeCode, and a label value, member name 
  16765. and associated TypeCode for each member. (The label values all have the same 
  16766. type as the switch, except that the default member, if present, has a label 
  16767. value of zero octet.) 
  16768.  
  16769. A tk_enum TypeCode  (which represents an enum) has  N+1 parameters: the name of 
  16770. the enum followed by a string for each enumeration identifier. A tk_string 
  16771. TypeCode has a single parameter: the maximum string length, as an integer. (A 
  16772. maximum length of zero signifies an unbounded string.) 
  16773.  
  16774. A tk_sequence TypeCode has two parameters: a TypeCode for the sequence 
  16775. elements, and the maximum size, as an integer.  (Again, zero signifies 
  16776. unbounded.) 
  16777.  
  16778. A tk_array TypeCode has two parameters: a TypeCode for the array elements, and 
  16779. the array length, as an integer. (Arrays must be bounded.) 
  16780.  
  16781. The tk_objref TypeCode represents an object reference; its parameter is a 
  16782. repository ID that identifies its interface. 
  16783.  
  16784. A complete table showing the parameters of all possible TypeCodes is given in 
  16785. the SOMobjects Base Toolkit Programmers Reference Manual; see the TypeCode_kind 
  16786. function of the Interface Repository Framework. 
  16787.  
  16788. TypeCodes are not actually "objects" in the formal sense. TypeCodes are 
  16789. referred to in the CORBA standard as pseudo-objects and described as "opaque". 
  16790. This means that, in reality, TypeCodes are special data structures whose 
  16791. precise definition is not fully exposed. Their implementation can vary from one 
  16792. platform to another, but all implementations must exhibit a minimal set of 
  16793. architected behavior. SOM TypeCodes support the architected behavior and have 
  16794. additional capability as well (for example, they can be copied and freed). 
  16795.  
  16796. Although TypeCodes are not objects, the programming interfaces that support 
  16797. them adhere to the same conventions used for IDL method invocations in SOM. 
  16798. That is, the first argument is always a TypeCode pseudo-object, and the second 
  16799. argument is a pointer to an Environment structure. Similarly, the names of the 
  16800. TypeCode functions are constructed like SOM's C-language method-invocation 
  16801. macros (all functions that operate on TypeCodes are named 
  16802. TypeCode_<function-name>). Because of this ostensible similarity to an IDL 
  16803. class, the TypeCode programming interfaces can be conveniently defined in IDL 
  16804. as shown below. 
  16805.  
  16806. A complete table showing the parameters of all possible  TypeCodes is given in 
  16807. the SOMobjects Developer Toolkit Programmers Reference Manual; see the 
  16808. TypeCode_kind function of the Interface Repository Framework. 
  16809.  
  16810. interface TypeCode {
  16811.  
  16812. enum TCKind {
  16813.     tk_null, tk_void,
  16814.     tk_short, tk_long, tk_ushort, tk_ulong,
  16815.     tk_float, tk_double, tk_boolean, tk_char,
  16816.     tk_octet, tk_any, tk_TypeCode, tk_Principal, tk_objref,
  16817.     tk_struct, tk_union, tk_enum, tk_string,
  16818.     tk_sequence, tk_array,
  16819.  
  16820.     // The remaining enumerators are SOM-unique extensions
  16821.     // to the CORBA standard.
  16822.     //
  16823.     tk_pointer, tk_self, tk_foreign
  16824. };
  16825.  
  16826. exception Bounds {};
  16827. // This exception is returned if an attempt is made
  16828. // by the parameter() operation (described below) to
  16829. // access more parameters than exist in the receiving
  16830. // TypeCode.
  16831.  
  16832. boolean equal (in TypeCode tc);
  16833. // Compares the argument with the receiver and returns TRUE
  16834. // if both TypeCodes are equivalent.  This is NOT a test for
  16835. // identity.
  16836.  
  16837. TCKind kind ();
  16838. // Returns the type of the receiver as a TCKind.
  16839.  
  16840. long param_count ();
  16841. // Returns the number of parameters that make up the
  16842. // receiving TypeCode.
  16843.  
  16844. any parameter (in long index) raises (Bounds);
  16845. // Returns the indexed parameter from the receiving TypeCode.
  16846. // Parameters are indexed from 0 to param_count()-1.
  16847. //
  16848. //  The remaining operations are SOM-unique extensions.
  16849. //
  16850.  
  16851. short alignment ();
  16852. // This operation returns the alignment required for an instance
  16853. // of the type described by the receiving TypeCode.
  16854.  
  16855. TypeCode copy (in TypeCode tc);
  16856. // This operation returns a copy of the receiving TypeCode.
  16857.  
  16858. void free (in TypeCode tc);
  16859. // This operation frees the memory associated with the
  16860. // receiving TypeCode. Subsequently, no further use can be
  16861. // made of the receiver, which, in effect, ceases to exist.
  16862.  
  16863. void print (in TypeCode tc);
  16864. // This operation writes a readable representation of the
  16865. // receiving TypeCode to stdout.  Useful for examining
  16866. // TypeCodes when debugging.
  16867.  
  16868. void setAlignment (in short align);
  16869. // This operation overrides the required alignment for an
  16870. // instance of the type described by the receiving TypeCode.
  16871.  
  16872. long size (in TypeCode tc);
  16873. // This operation returns the size of an instance of the
  16874. // type represented by the receiving TypeCode.
  16875. };
  16876.  
  16877. A detailed description of the programming interfaces for TypeCodes is given in 
  16878. the SOMobjects Developer Toolkit: Programmers Reference Manual. 
  16879.  
  16880.  
  16881. ΓòÉΓòÉΓòÉ 8.4.4.1. Providing 'alignment' information ΓòÉΓòÉΓòÉ
  16882.  
  16883. In addition to the parameters in the TypeCodes that describe each type, a 
  16884. SOM-unique extension to the TypeCode functionality allows each TypeCode to 
  16885. carry alignment information as a "hidden" parameter. Use the TypeCode_alignment 
  16886. function to access the alignment value. The alignment value is a short integer 
  16887. that should evenly divide any memory address where an instance of the type will 
  16888. occur. 
  16889.  
  16890. If no alignment information is provided in your IDL source files, all TypeCodes 
  16891. carry default alignment information. The default alignment for a type is the 
  16892. natural boundary for the type, based on the natural boundary for the basic 
  16893. types of which it may be composed. This information can vary from one hardware 
  16894. platform to another. The  TypeCode will contain the default alignment 
  16895. information appropriate to the platform where it was defined. 
  16896.  
  16897. To provide alignment information for the types and instances of types in your 
  16898. IDL source file, use the "align=N" modifier, where N is your specified 
  16899. alignment. Use standard modifier syntax of the SOM Compiler to attach the 
  16900. alignment information to a particular element in the IDL source file. In the 
  16901. following example,  align=1 (that is, unaligned or no alignment) is attached to 
  16902. the struct "abc" and to one particular instance of struct "def" (the instance 
  16903. data item "y"). 
  16904.  
  16905. interface i {
  16906.     struct abc {
  16907.         long a;
  16908.         char b;
  16909.         long c;
  16910.     };
  16911.     struct def {
  16912.         char l;
  16913.         long m;
  16914.     };
  16915.  
  16916.     void foo ();
  16917.  
  16918.     implementation {
  16919.  
  16920.     //# instance data
  16921.         abc x;
  16922.         def y;
  16923.         def z;
  16924.  
  16925.     //# alignment modifiers
  16926.         abc: align=1;
  16927.         y: align=1;
  16928.     };
  16929. };
  16930.  
  16931. Be aware that assigning the required alignment information to a type does not 
  16932. guarantee that instances of that type will actually be aligned as indicated. To 
  16933. ensure that, you must find a way to instruct your compiler to provide the 
  16934. desired alignment. In practice, this can be difficult except in simple cases. 
  16935. Most compilers can be instructed to treat all data as aligned (that is, default 
  16936. alignment) or as unaligned, by using a compile-time option or #pragma. The more 
  16937. important consideration is to make certain that the TypeCodes going into the 
  16938. Interface Repository actually reflect the alignment that your compiler 
  16939. provides. This way, when programs (such as the DSOM Framework) need to 
  16940. interpret the layout of data during their execution, they will be able to 
  16941. accurately map your data structures. This happens automatically when using the 
  16942. normal default alignment. 
  16943.  
  16944. If you wish to use unaligned instance data when implementing a class, place an 
  16945. "unattached" align=1 modifier in the implementation section. An unattached 
  16946. align=N modifier is presumed to pertain to the class's instance data structure, 
  16947. and will by implication be attached to all of the instance data items. 
  16948.  
  16949. When designing your own public types, be aware that the best practice of all 
  16950. (and the one that offers the best opportunity for language neutrality) is to 
  16951. lay out your types carefully so that it will make no difference whether they 
  16952. are compiled as aligned or unaligned! 
  16953.  
  16954.  
  16955. ΓòÉΓòÉΓòÉ 8.4.4.2. Using the 'tk_foreign' TypeCode ΓòÉΓòÉΓòÉ
  16956.  
  16957. TypeCodes can be used to partially describe types that cannot be described in 
  16958. IDL (for example, a FILE type in C, or a specific class type in C++). The 
  16959. SOM-unique extension tk_foreign is used for this purpose. A  tk_foreign 
  16960. TypeCode contains three parameters: 
  16961.  
  16962.    1. The name of the type, 
  16963.    2. An implementation context string, and 
  16964.    3. A length. 
  16965.  
  16966.  The implementation context string can be used to carry an arbitrarily long 
  16967.  description that identifies the context where the foreign type can be used and 
  16968.  understood. If the length of the type is also known, it can be provided with 
  16969.  the length parameter. If the length is not known or is not constant, it should 
  16970.  be specified as zero. If the length is not specified, it will default to the 
  16971.  size of a pointer. A tk_foreign TypeCode  can also have alignment information 
  16972.  specified, just like any other TypeCode. 
  16973.  
  16974.  Using the following steps causes the SOM Compiler to create a foreign TypeCode 
  16975.  in the Interface Repository: 
  16976.  
  16977.    1. Define the foreign type as a typedef SOMFOREIGN in the IDL source file. 
  16978.  
  16979.    2. Use the #pragma modifier statement to supply the additional information 
  16980.       for the TypeCode as modifiers. The implementation context information is 
  16981.       supplied using the "impctx" modifier. 
  16982.  
  16983.    3. Compile the IDL file using the -u option to place the information in the 
  16984.       Interface Repository. 
  16985.  
  16986.  For example: 
  16987.  
  16988.   typedef SOMFOREIGN Point;
  16989.   #pragma modifier Point: impctx="C++ Point class",length=12,align=4;
  16990.  
  16991.  If a foreign type is used to define instance data, structs, unions, 
  16992.  attributes, or methods in an IDL source file, it is your responsibility to 
  16993.  ensure that the implementation and/or usage bindings contain an appropriate 
  16994.  definition of the type that will satisfy your compiler. You can use the 
  16995.  passthru statement in your IDL file to supply this definition. However, it is 
  16996.  not recommended that you expose foreign data in attributes, methods, or any of 
  16997.  the public types, if this can be avoided, because there is no guarantee that 
  16998.  appropriate usage binding information can be provided for all languages. If 
  16999.  you know that all users of the class will be using the same implementation 
  17000.  language that your class uses, you may be able to disregard this 
  17001.  recommendation. 
  17002.  
  17003.  
  17004. ΓòÉΓòÉΓòÉ 8.4.4.3. TypeCode constants ΓòÉΓòÉΓòÉ
  17005.  
  17006. TypeCodes are actually available in two forms: In addition to the TypeCode 
  17007. information provided by the methods of the Interface Repository, TypeCode 
  17008. constants can be generated by the SOM Compiler in your C or C++ usage bindings 
  17009. upon request. A TypeCode constant contains the same information found in the 
  17010. corresponding IR TypeCode, but has the advantage that it can be used as a 
  17011. literal in a C or C++ program anywhere a normal TypeCode would be acceptable. 
  17012.  
  17013. TypeCode constants have the form TC_< typename>, where <typename> is the name 
  17014. of a type (that is, a typedef, union, struct, or enum) that you have defined in 
  17015. an IDL source file. In addition, all IDL basic types and certain types dictated 
  17016. by the OMG CORBA standard come with pre-defined TypeCode constants (such as 
  17017. TC_long, TC_short, TC_char, and so forth). A full list of the pre-defined 
  17018. TypeCode constants can be found in the file "somtcnst.h". You must explicitly 
  17019. include this file in your source program to use the pre-defined TypeCode 
  17020. constants. 
  17021.  
  17022. Since the generation of TypeCode constants can increase the time required by 
  17023. the SOM Compiler to process your IDL files, you must explicitly request the 
  17024. production of TypeCode constants if you need them. To do so, use the 
  17025. "tcconsts" modifier with the -m option of the sc or somc command. For example, 
  17026. the command 
  17027.  
  17028. sc -sh -mtcconsts myclass.idl         (On AIX or Windows)
  17029. somc -sh -mtcconsts myclass.idl       (On Windows)
  17030.  
  17031. will cause the SOM Compiler to generate a "myclass.h" file that contains 
  17032. TypeCode constants for the types defined in "myclass.idl". 
  17033.  
  17034.  
  17035. ΓòÉΓòÉΓòÉ 8.4.4.4. Using the IDL basic type 'any' ΓòÉΓòÉΓòÉ
  17036.  
  17037. Some Interface Repository methods and TypeCode functions return information 
  17038. typed as the IDL basic type any. Usually this is done when a wide variety of 
  17039. different types of data may need to be returned through a common interface. The 
  17040. type any actually consists of a structure with two fields: a _type field and a 
  17041. _value field. The _value field is a pointer to the actual datum that was 
  17042. returned, while the _type field holds a TypeCode  that describes the datum. 
  17043.  
  17044. In many cases, the context in which an operation occurs makes the type of the 
  17045. datum apparent. If so, there is no need to examine the TypeCode unless it is 
  17046. simply as a consistency check. For example, when accessing the first parameter 
  17047. of a tk_struct TypeCode, the type of the result will always be the name of the 
  17048. structure (a string). Because this is known ahead of time, there is no need to 
  17049. examine the returned TypeCode in the any_type field to verify that it is a 
  17050. tk_string TypeCode. You can just rely on the fact that it is a string; or, you 
  17051. can check the TypeCode in the _type field to verify it, if you so choose. 
  17052.  
  17053. An IDL any type can be used in an interface as a way of bypassing the strong 
  17054. type checking that occurs in languages like ANSI C and C++. Your compiler can 
  17055. only check that the interface returns the any structure; it has no way of 
  17056. knowing what type of data will be carried by the any during execution of the 
  17057. program. Consequently, in order to write C or C++ code that accesses the 
  17058. contents of the any correctly, you must always cast the _value field to reflect 
  17059. the actual type of the datum at the time of the access. 
  17060.  
  17061. Here is an example of a code fragment written in C that illustrates how the 
  17062. casting must be done to extract various values from an any: 
  17063.  
  17064. #include <som.h>    /* For "any" & "Environment" typedefs */
  17065. #include <somtc.h>  /* For TypeCode_kind prototype        */
  17066.  
  17067. any result;
  17068. Environment *ev;
  17069.  
  17070. printf ("result._value = ");
  17071. switch (TypeCode_kind (result._type, ev)) {
  17072.  
  17073.     case tk_string:
  17074.         printf ("%s\n", *((string *) result._value));
  17075.         break;
  17076.  
  17077.     case tk_long:
  17078.         printf ("%ld\n", *((long *) result._value));
  17079.         break;
  17080.  
  17081.     case tk_boolean:
  17082.         printf ("%d\n", *((boolean *) result._value));
  17083.         break;
  17084.  
  17085.     case tk_float:
  17086.         printf ("%f\n", *((float *) result._value));
  17087.         break;
  17088.  
  17089.     case tk_double:
  17090.         printf ("%f\n", *((double *) result._value));
  17091.         break;
  17092.  
  17093.     default:
  17094.         printf ("something else!\n");
  17095. }
  17096.  
  17097. Note: Of course, an any has no restriction, per se, on the type of datum that 
  17098. it can carry. Frequently, however, methods that return an any or that accept an 
  17099. any as an argument do place semantic restrictions on the actual type of data 
  17100. they can accept or return. Always consult the reference page for a method that 
  17101. uses an any to determine whether it limits the range of types that may be 
  17102. acceptable. 
  17103.  
  17104.  
  17105. ΓòÉΓòÉΓòÉ 9. The Metaclass Framework ΓòÉΓòÉΓòÉ
  17106.  
  17107. In SOM, classes are objects; metaclasses are classes and thus are objects, too. 
  17108. Also depicted are the three primitive class objects of the SOM run time: 
  17109. SOMClass, SOMobject, and SOMClassMgr. 
  17110.  
  17111.  
  17112. Primitive objects of the SOM run time
  17113.  
  17114. The important point to be aware of here is that any class that is a subclass of 
  17115. SOMClass is a metaclass This chapter describes metaclasses that are available 
  17116. in SOMobjects Toolkit. There are two kinds of metaclasses: 
  17117.  
  17118. Framework metaclasses-metaclasses for building new metaclasses and Utility 
  17119. metaclasses - metaclasses to help you write applications 
  17120.  
  17121. Briefly, the SOMobjects Toolkit provides the following metaclasses of each 
  17122. category for use by programmers: 
  17123.  
  17124.      Framework metaclasses: 
  17125.  
  17126.     SOMMBeforeAfter Used to create a metaclass that has "before" and "after" 
  17127.            methods for all methods (inherited or introduced) invoked on 
  17128.            instances of its classes. 
  17129.  
  17130.      Utility metaclasses: 
  17131.  
  17132.     SOMMSingleInstance Used to create a class that may have at most one 
  17133.            instance. 
  17134.  
  17135.     SOMMTraced Provides tracing for every invocation of all methods on 
  17136.            instances of its classes. 
  17137.  
  17138.  The following sections describe each metaclass more fully. 
  17139.  
  17140.  
  17141.   Class organization of the Metaclass Framework.
  17142.  
  17143.  
  17144. ΓòÉΓòÉΓòÉ 9.1. A note about metaclass programming ΓòÉΓòÉΓòÉ
  17145.  
  17146. SOM metaclasses are carefully constructed so that they compose (see Section 8.1 
  17147. below). If you need to create a metaclass, you can introduce new class methods, 
  17148. and new class variables, but you should not override any of the methods 
  17149. introduced by SOMClass. If you need more than this, request access to the 
  17150. experimental Cooperative metaclass used to implement the Metaclass Framework 
  17151. metaclasses described in this chapter. 
  17152.  
  17153.  
  17154. ΓòÉΓòÉΓòÉ 9.2. Framework Metaclasses for "Before/After" Behavior ΓòÉΓòÉΓòÉ
  17155.  
  17156. This section covers the following subjects: 
  17157.  
  17158.      The 'SOMMBeforeAfter' metaclass 
  17159.      Composition of before/after metaclasses 
  17160.      Notes and advantages of 'before/after' usage 
  17161.  
  17162.  
  17163. ΓòÉΓòÉΓòÉ 9.2.1. The 'SOMMBeforeAfter' metaclass ΓòÉΓòÉΓòÉ
  17164.  
  17165. SOMMBeforeAfter is a metaclass that allows the user to create a class for which 
  17166. a particular method is invoked before each invocation of every method, nd for 
  17167. which a second method is invoked after each invocation. SOMMBeforeAfter defines 
  17168. two methods: sommBeforeMethod and sommAfterMethod.  These two methods are 
  17169. intended to be overridden in the child of SOMMBeforeAfter to define the 
  17170. particular "before" and "after" methods needed for the client application. 
  17171.  
  17172. For example, suppose a "Barking" metaclass (a subclass of SOMMBeforeAfter 
  17173. overrides the sommBeforeMethod and sommAfterMethod with a method that emits one 
  17174. bark when invoked. Thus, one can create the "BarkingDog" class, whose instances 
  17175. (such as "Lassie") bark twice when "disturbed" by a method invocation. 
  17176.  
  17177.  
  17178. A hierarchy of metaclasses
  17179.  
  17180. The SOMMBeforeAfter metaclass is designed to be subclassed; a subclass (or 
  17181. child) of SOMMBeforeAfter is also a metaclass. The subclass overrides 
  17182. sommBeforeMethod or sommAfterMethod or both. These (redefned) methods are 
  17183. invoked before and after any method supported by instances of the subclass 
  17184. (these methods are called primary methods). That is, they are invoked before 
  17185. and after methods invoked on the ordinary objects that are instances of the 
  17186. class objects that are instances of the subclass of SOMMBeforeAfter. 
  17187.  
  17188. The sommBeforeMethod returns a boolean value. This allows the "before" method 
  17189. to control whether the "after" method and the primary method get invoked. If 
  17190. sommBeforeMethod returns TRUE, normal processing occurs. If FALSE is returned, 
  17191. neither the primary method nor the corresponding sommAfterMethod is invoked. In 
  17192. addition, no more deeply nested before/after methods are invoked (see 
  17193. "Composition of before/after metaclasses" below). This facility can be used, 
  17194. for example, to allow a before/after metaclass to provide secure access to an 
  17195. object. The implication of this convention is that, if sommBeforeMethod is 
  17196. going to return FALSE, it must do any post-processing that might otherwise be 
  17197. done in the "after" method. 
  17198.  
  17199. Caution: somInit and somFree are among the methods that get before/after 
  17200. behavior. This implies the following two obligations are imposed on the 
  17201. programmer of a SOMMBeforeAfter class. First, the implementation must guard 
  17202. against sommBeforeMethod being called before somInit has executed, and the 
  17203. object is not yet fully initialized. Second, the implementation must guard 
  17204. against sommAfterMethod being called after somFree, at which time the object no 
  17205. longer exists (see the example "C implementation for 'Barking' metaclass" 
  17206. below). 
  17207.  
  17208. The following example shows the IDL needed to create a Barking metaclass. Just 
  17209. run the appropriate emitter to get an implementation binding, and then provide 
  17210. the appropriate "before" behavior and "after" behavior. 
  17211.  
  17212. SOM IDL for 'Barking' metaclass 
  17213.  
  17214. #ifndef Barking_idl
  17215. #define Barking_idl
  17216.  
  17217. #include <sombacls.idl>
  17218. interface  Barking : SOMMBeforeAfter
  17219. {
  17220. #ifdef __SOMIDL__
  17221. implementation
  17222. {
  17223.   //# Class Modifiers
  17224.   filestem = barking;
  17225.   callstyle = idl;
  17226.  
  17227.   //# Method Modifiers
  17228.   sommBeforeMethod : override;
  17229.   sommAfterMethod : override;
  17230. };
  17231. #endif /* __SOMIDL__ */
  17232. };
  17233. #endif  /* Barking_idl */
  17234.  
  17235. The next example shows an implementation of the Barking metaclass in which no 
  17236. barking occurs when somFree is invoked. 
  17237.  
  17238. C implementation for 'Barking' metaclass 
  17239.  
  17240. #define Barking_Class_Source
  17241. #include <barking.ih>
  17242.  
  17243. static char *somMN_somFree = "somFree";
  17244. static somId somId_somFree = &somMN_somFree;
  17245.  
  17246. SOM_Scope boolean  SOMLINK sommBeforeMethod(Barking somSelf,
  17247.                                             Environment *ev,
  17248.                                             SOMObject object,
  17249.                                             somId methodId,
  17250.                                             va_list ap)
  17251. {
  17252.     if ( !somCompareIds( methodId, somId_somFree )
  17253.        printf( "WOOF" );
  17254. }
  17255.  
  17256. SOM_Scope void  SOMLINK sommAfterMethod(Barking somSelf,
  17257.                                         Environment *ev,
  17258.                                         SOMObject object,
  17259.                                         somId methodId,
  17260.                                         somId descriptor,
  17261.                                         somToken returnedvalue,
  17262.                                         va_list ap)
  17263. {
  17264.     if ( !somCompareIds( methodId, somId_somFree )
  17265.        printf( "WOOF" );
  17266. }
  17267.  
  17268.  
  17269. ΓòÉΓòÉΓòÉ 9.2.2. Composition of before/after metaclasses ΓòÉΓòÉΓòÉ
  17270.  
  17271. When there are two before/after metaclasses -"Barking" (as before) and 
  17272. "Fierce", which has a sommBeforeMethod and sommAfterMethod that both growl 
  17273. (that is, both methods make a "grrrr" sound when executed). The preceding 
  17274. discussion demonstrated how to create a "FierceDog " or a "BarkingDog ", but 
  17275. has not yet addressed the question of how to compose these properties of fierce 
  17276. and barking. Composability means having the ability to easily create either a 
  17277. "FierceBarkingDog" that goes "grrr woof woof grrr " when it responds to a 
  17278. method call or a "BarkingFierceDog " that goes "woof grrr grrr woof" when it 
  17279. responds to a method call. 
  17280.  
  17281.  
  17282. Example for composition of before or after metaclasses.
  17283.  
  17284. There are several ways to express such compositions. Figure 1 depicts SOM IDL 
  17285. fragments for three techniques in which composition can be indicated by a 
  17286. programmer. These are denoted as Technique 1, Technique 2, and Technique 3, 
  17287. each of which creates a "FierceBarkingDog" class, named "FB-1", "FB-2", and 
  17288. "FB-3", respectively, as follows: 
  17289.  
  17290.      In Technique 1, a new metaclass ("FierceBarking") is created with both 
  17291.       the "Fierce" and "Barking" metaclasses as parents. An instance of this 
  17292.       new metaclass (that is, "FB-1") is a "FierceBarkingDog" (assuming "Dog " 
  17293.       is a parent). 
  17294.  
  17295.      In Technique 2, a new class is created which has parents that are 
  17296.       instances of "Fierce" and "Barking" respectively. That is, "FB-2" is a 
  17297.       "FierceBarkingDog" also (assuming "FierceDog" and "BarkingDog" do not 
  17298.       further specialize "Dog"). 
  17299.  
  17300.      In Technique 3, "FB-3", which also is a "FierceBarkingDog", is created by 
  17301.       declaring that its parent is a "BarkingDog" and that its explicit 
  17302.       (syntactically declared) metaclass is "Fierce". 
  17303.  
  17304.   ΓöîΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÉ
  17305.   ΓöéTECHNIQUE 1              ΓöéTECHNIQUE 2              ΓöéTECHNIQUE 3              Γöé
  17306.   Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  17307.   Γöéinterface                Γöéinterface                Γöéinterface                Γöé
  17308.   Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  17309.   ΓöéFB-1:Dog                 ΓöéFB-2:FierceDog,          ΓöéFB-3:BarkingDog          Γöé
  17310.   Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  17311.   Γöé{                        ΓöéBarkingDog               Γöé{                        Γöé
  17312.   Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  17313.   Γöé...                      Γöé{                        Γöé...                      Γöé
  17314.   Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  17315.   Γöéimplementation           Γöé...                      Γöéimplemetation            Γöé
  17316.   Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  17317.   Γöé{                        ΓöéImplementation           Γöé{                        Γöé
  17318.   Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  17319.   Γöémetaclass=FierceBarking; Γöé{                        Γöémetaclass=Fierce;        Γöé
  17320.   Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  17321.   Γöé...                      Γöé   ...                   Γöé   ...                   Γöé
  17322.   Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  17323.   Γöé };                      Γöé };                      Γöé };                      Γöé
  17324.   Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  17325.   Γöé};                       Γöé};                       Γöé};                       Γöé
  17326.   ΓööΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÿ
  17327.  
  17328.  Figure 1.Three techniques for composing before/after metaclasses. 
  17329.  
  17330.  Note that the explicit metaclass in the SOM IDL of "FB-1" is its derived 
  17331.  class, "FierceBarking". The derived metaclass of "FB-2" is also 
  17332.  "FierceBarking". Lastly, the derived metaclass of "FB-3" is  not  the 
  17333.  metaclass explicitly specified in the SOM IDL; rather, it  too is 
  17334.  "FierceBarking." 
  17335.  
  17336.  
  17337. ΓòÉΓòÉΓòÉ 9.2.3. Notes and advantages of 'before/after' usage ΓòÉΓòÉΓòÉ
  17338.  
  17339. Notes on the dispatching of before/after methods: 
  17340.  
  17341.      A before (after) method is invoked just once per primary method 
  17342.       invocation. 
  17343.  
  17344.      The dispatching of before/after methods is thread-safe. 
  17345.  
  17346.      The dispatching of before/after methods is fast. The time overhead for 
  17347.       dispatching a primary method is on the order of N times the time to 
  17348.       invoke a before/after method as a procedure, where N is the total number 
  17349.       of before/after methods to be applied. 
  17350.  
  17351.  In conclusion, consider an example that clearly demonstrates the power of the 
  17352.  composition of before/after metaclasses. Suppose you are creating a class 
  17353.  library that will have n classes. Further suppose there are p properties that 
  17354.  must be included in all combinations for all classes. Potentially, the library 
  17355.  must have n2p classes. Let us hypothesize that (fortunately) all these 
  17356.  properties can be captured by before/after metaclasses. In this case, the size 
  17357.  of the library is n+p. 
  17358.  
  17359.  The user of such a library need only produce those combinations necessary for 
  17360.  a given application. In addition, note that there is none of the usual 
  17361.  programming. Given the IDL for a combination of before/after metaclasses, the 
  17362.  SOM compiler generates the implementation of the combination (in either C or 
  17363.  C++) with no further manual intervention. 
  17364.  
  17365.  
  17366. ΓòÉΓòÉΓòÉ 9.3. The 'SOMMSingleInstance' Metaclass ΓòÉΓòÉΓòÉ
  17367.  
  17368. Sometimes it is necessary to define a class for which only one instance can be 
  17369. created. This is easily accomplished with the SOMMSingleInstance metaclass. 
  17370. Suppose the class "Collie" is an instance of SOMMSingleInstance. The first call 
  17371. to CollieNew creates the one possible instance of "Collie"; hence, subsequent 
  17372. calls to CollieNew return the first (and only) instance. 
  17373.  
  17374. Any class whose metaclass is SOMMSingleInstance gets this requisite behavior; 
  17375. nothing further needs to be done. The first instance created is always returned 
  17376. by the <className>New maro. 
  17377.  
  17378. Alternatively, the method sommGetSingleInstance does the same thing as the 
  17379. <className>New macro. This method invoked on a class object (for example, 
  17380. "Collie") is useful because the call site explicitly shows that something 
  17381. special is occurring and that a new object is not necessarily being created. 
  17382. For this reason, one might prefer the second form of creating a single-instance 
  17383. object to the first. 
  17384.  
  17385. Instances of SOMMSingleInstance keep a count of the number of times somNew and 
  17386. sommGetSingleInstance are invoked. Each invocation of somFree decrements this 
  17387. count. An invocation of somFree does not actually free the single instance 
  17388. until the count reaches zero. 
  17389.  
  17390. SOMMSingleInstance overrides somRenew, somRenewNoInit, somRenewNoInitNoZero, 
  17391. and somRenewNoZero so that a proxy is created in the space indicated in the 
  17392. somRenew* call. This proxy redispatches all methods to the single instance, 
  17393. which is always allocated in heap storage. Note that all of these methods 
  17394. (somRenew*) increment the reference count; therefore, somFree should be called 
  17395. on these objects, too. In this case, somFree decrements the reference and frees 
  17396. the single instance (and, of course, takes no action with respect to the 
  17397. storage indicated in the original somRenew* call). 
  17398.  
  17399. If a class is an instance of SOMMSingleInstance, all of its subclasse are also 
  17400. instances of SOMMSingleInstance. Be aware that this also means that each 
  17401. subclass is allowed to have only a single instance. (This may seem obvious. 
  17402. However, it is a common mistake to create a framework class that must have a 
  17403. single instance, while at the same time expecting users of the framework to 
  17404. subclass the single instance class. The result is that two single-instance 
  17405. objects are created: one for the framework class and one for the subclass. One 
  17406. technique that can mitigate this scenario is based on the use of 
  17407. somSubstituteClass. In this case, the creator of the subclass must substitute 
  17408. the subclass for the framework class - before the instance of the framework 
  17409. class is created.) 
  17410.  
  17411.  
  17412. ΓòÉΓòÉΓòÉ 9.4. The 'SOMMTraced' Metaclass ΓòÉΓòÉΓòÉ
  17413.  
  17414. SOMMTraced is a metaclass that facilitates tracing of method invocations. If 
  17415. class "Collie" is an instance of SOMMTraced (if SOMMTraced is the metaclass of 
  17416. "Collie"), any method invoked on an instance of "Collie" is traced. That is, 
  17417. before the method begins execution, a message prints (to standard output) 
  17418. giving the actual parameters. Then, after the method completes execution, a 
  17419. second message prints giving the returned value. This behavior is attained 
  17420. merely by being an instance of the SOMMTraced metaclass. 
  17421.  
  17422. If the class being traced is contained in the Interface Repository, actual 
  17423. parameters are printed as part of the trace. If the class is not contained in 
  17424. the Interface Repository, an ellipsis is printed. 
  17425.  
  17426. To be more concrete, suppose that the class "Collie" is a child of "Dog" and is 
  17427. an instance of SOMMTraced. Because SOMMTraced is the metaclass of "Collie," any 
  17428. method invoked on "Lassie" (an instance of "Collie") is traced. 
  17429.  
  17430. It is easy to use SOMMTraced: Just make a class an instance of SOMMTraced in 
  17431. order to get tracing. 
  17432.  
  17433. There is one more step for using SOMMTraced: Nothing prints unless the 
  17434. environment variable SOMM_TRACED is set. If it is set to the empty string, all 
  17435. traced classes print. If SOMM_TRACED is not the empty string, it should be set 
  17436. to the list of names of classes that should be traced. For example, the 
  17437. following command turns on printing of the trace for "Collie", but not for any 
  17438. other traced class: 
  17439.  
  17440. export  SOMM_TRACED=Collie      (on AIX)
  17441. SET     SOMM_TRACED=Collie      (on OS/2 or Windows)
  17442.  
  17443. The example below shows the IDL needed to create a traced dog class: Just run 
  17444. the appropriate emitter to get an implementation binding. 
  17445.  
  17446. SOM IDL for 'TracedDog' class 
  17447.  
  17448. #include "dog.idl"
  17449. #include <somtrcls.idl>
  17450. interface TracedDog : Dog
  17451. {
  17452. #ifdef __SOMIDL__
  17453. implementation
  17454. {
  17455.   //# Class Modifiers
  17456.   filestem = trdog;
  17457.   metaclass = SOMMTraced;
  17458. };
  17459. #endif /* __SOMIDL__ */
  17460. };
  17461.  
  17462.  
  17463. ΓòÉΓòÉΓòÉ 9.5. Error Codes ΓòÉΓòÉΓòÉ
  17464.  
  17465. It is possible to receive the following messages from the Metaclass Framework 
  17466. while an application is running. 
  17467.  
  17468.  60001     An attempt was made to construct a class with SOMMSingleInstance as 
  17469.            a metaclass constraint. (This may occur indirectly because of the 
  17470.            construction of a derived metaclass). The initialization of the 
  17471.            class failed because somInitMIClass defined by SOMMSingleInstance is 
  17472.            in conflict with another metaclass that has overridden somNew. That 
  17473.            is, some other metaclass has already claimed the right to return the 
  17474.            value for somNew. 
  17475.  
  17476.  60002     An attempt was made to construct a class with SOMMSingleInstance as 
  17477.            a metaclass constraint. (This may occur indirectly because of the 
  17478.            construction of a derived metaclass). The initialization of the 
  17479.            class failed because somInitMIClass defined by SOMMSingleInstance is 
  17480.            in conflict with another metaclass that has overridden somFree. That 
  17481.            is, some other metaclass has already claimed this right to override 
  17482.            somFree. 
  17483.  
  17484.  60004     An invocation of somrRepInit was made with a logging type other than 
  17485.            'o' or 'v'. 
  17486.  
  17487.  60005     The sommBeforeMethod or the sommAfterMethod was invoke on a 
  17488.            SOMRReplicbleObject whose logging type is other than 'o' or 'v'. 
  17489.            This error cannot occur normally. The likely cause is that some 
  17490.            method invoked on another object has overwritten this object's 
  17491.            memory. 
  17492.  
  17493.  60006     A Before/After Metaclass must override both sommBeforeMethod an 
  17494.            sommAfterMethod. This message indicates an attempt to create a 
  17495.            Before/After Metaclass where only one of the above methods is 
  17496.            overridden. 
  17497.  
  17498.  
  17499. ΓòÉΓòÉΓòÉ 10. The Event Management Framework ΓòÉΓòÉΓòÉ
  17500.  
  17501. The Event Management Framework is a central facility for registering all events 
  17502. of an application. Such a registration facilitates grouping of various 
  17503. application events and waiting on multiple events in a single event-processing 
  17504. loop. This facility is used by the Replication Framework and by DSOM to wait on 
  17505. their respective events of interest. The Event Management Framework must also 
  17506. be used by any interactive application that contains DSOM or replicated 
  17507. objects. 
  17508.  
  17509.  
  17510. ΓòÉΓòÉΓòÉ 10.1. Event Management Basics ΓòÉΓòÉΓòÉ
  17511.  
  17512. The Event Management Framework consists of an Event Manager (EMan) class, a 
  17513. Registration Data class and several Event classes. It provides a way to 
  17514. organize various application events into groups and to process all events in a 
  17515. single event-processing loop. The need for this kind of facility is seen very 
  17516. clearly in interactive applications that also need to process some background 
  17517. events (say, messages arriving from a remote process). Such applications must 
  17518. maintain contact with the user while responding to events coming from other 
  17519. sources. 
  17520.  
  17521. One solution in a multi-threaded environment is to have a different thread 
  17522. service each different source of events. For a single-threaded environment it 
  17523. should be possible to recognize and process all events of interest in a single 
  17524. main loop. EMan offers precisely this capability. EMan can be useful even when 
  17525. multiple threads are available, because of its simple programming model. It 
  17526. avoids contention for common data objects between EMan event processing and 
  17527. other main-loop processing activity. 
  17528.  
  17529.  
  17530. ΓòÉΓòÉΓòÉ 10.1.1. Model of EMan usage ΓòÉΓòÉΓòÉ
  17531.  
  17532. The programming model of EMan is similar to that of many GUI toolkits. The main 
  17533. program initializes EMan and then registers interest in various types of 
  17534. events. The main program ends by calling a non-returning function of EMan that 
  17535. waits for events and dispatches them as and when they occur. In short, the 
  17536. model includes steps that: 
  17537.  
  17538.    1. Initialize the Event Manager, 
  17539.    2. Register with EMan for all events of interest, and 
  17540.    3. Hand over control to EMan to loop forever and to dispatch events. 
  17541.  
  17542.  The Event Manager is a SOM object and is an instance of the SOMEEMan class. 
  17543.  Since any application requires only one instance of this object, the SOMEEMan 
  17544.  class is an instance of the SOMMSingleInstance class. Creation and 
  17545.  initialization of the Event Manager is accomplished by a function call to 
  17546.  SOMEEmanNew. 
  17547.  
  17548.  Currently, EMan supports the four kinds of events described in the following 
  17549.  topic. An application can register or unregister for events in a callback 
  17550.  routine (explained below) even after control has been turned over to EMan. 
  17551.  
  17552.  
  17553. ΓòÉΓòÉΓòÉ 10.1.2. Event types ΓòÉΓòÉΓòÉ
  17554.  
  17555. Event types are categorized as follows: 
  17556.  
  17557.      Timer events 
  17558.  
  17559.       These can be either one-time timers or interval timers. 
  17560.  
  17561.      Sink events (sockets, file descriptors, and message queues) 
  17562.  
  17563.       On AIX, this includes file descriptors for input/output files, sockets, 
  17564.       pipes, and message queues. On OS/2 and Windows, only TCP/IP sockets are 
  17565.       supported. 
  17566.  
  17567.       Note:On OS/2 and Windows, the Sockets classes for NetBIOS (NBSockets) and 
  17568.       Novell IPX/SPX (IPXSockets) are primarily intended for use by DSOM and 
  17569.       the Replication Framework, not for general application programming. (The 
  17570.       Replication Framework is available as part of the full-capability 
  17571.       SOMobjects Developer Toolkit.) 
  17572.  
  17573.      Client events (any event that the application wants to queue with EMan) 
  17574.  
  17575.       These events are defined, created, processed, and destroyed by the 
  17576.       application. EMan simply acts as a place to queue these events for 
  17577.       processing. EMan dispatches these client events whenever it sees them. 
  17578.       Typically, this happens immediately after the event is queued. 
  17579.  
  17580.      Work procedure events (procedures that can be called when there is no 
  17581.       other event) 
  17582.  
  17583.       These are typically background procedures that the application intends to 
  17584.       execute when there are spare processor cycles. When there are no other 
  17585.       events to process, EMan calls all registered work procedures. A work 
  17586.       procedure event is called only after all other higher priority events 
  17587.       have been called. A work procedure event is not called if there are no 
  17588.       other events to be processed. 
  17589.  
  17590.  The Event Management Framework is extendible (that is, other event types can 
  17591.  be added to it) through subclassing. The event types currently supported by 
  17592.  EMan are at a sufficiently low level so as to enable building other higher 
  17593.  level application events on top of them. For example, you can build an X-event 
  17594.  handler by simply registering the file descriptor for the X connection with 
  17595.  EMan and getting notified when any X-event occurs. 
  17596.  
  17597.  
  17598. ΓòÉΓòÉΓòÉ 10.1.3. Registration ΓòÉΓòÉΓòÉ
  17599.  
  17600. This topic illustrates how to register for an event type. 
  17601.  
  17602.  
  17603. ΓòÉΓòÉΓòÉ 10.1.3.1. Callbacks ΓòÉΓòÉΓòÉ
  17604.  
  17605. The programmer decides what processing needs to be done when an event occurs 
  17606. and then places the appropriate code either in a procedure or in a method of an 
  17607. object. This procedure or method is called a callback. (The callback is 
  17608. provided to EMan at the time of registration and is called by EMan when a 
  17609. registered event occurs.) The signature of a callback is fixed by the framework 
  17610. and must have one of the following three signatures: 
  17611.  
  17612. void SOMLINK EMRegProc(SOMEEvent, void *);
  17613. void SOMLINK EMMethodProc(SOMObject, SOMEEvent, void *);
  17614. void SOMLINK EMMethodProcEv(SOMObject, Environment *Ev,
  17615.                             SOMEEvent, void *);
  17616. /* On OS/2, they all use "system" linkage  */
  17617. /* On Windows, the SOMLINK keyword is Not included if the
  17618.  * application is intended to support multiple instances. */
  17619.  
  17620. The three specified prototypes correspond to a simple callback procedure, a 
  17621. callback method using OIDL call style, and a callback method using IDL call 
  17622. style. The parameter type SOMEEvent refers to an event object passed by EMan to 
  17623. the callback.  Event objects are described below. 
  17624.  
  17625. NOTE: When the callbacks are methods, EMan calls these methods using 
  17626. Name-lookup Resolution (see Chapter 5 Section 5.3 on Method Resolution). One of 
  17627. the implications is that at the time of registration EMan queries the target 
  17628. object's class object to provide a method pointer for the method name supplied 
  17629. to it. Eman uses this pointer for making event callbacks. 
  17630.  
  17631.  
  17632. ΓòÉΓòÉΓòÉ 10.1.3.2. Event classes ΓòÉΓòÉΓòÉ
  17633.  
  17634. All event objects are instances of either the SOMEEvent class or a subclass of 
  17635. it. The hierarchy of event classes is as follows: 
  17636.  
  17637.  
  17638. SOMObjectΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇSOMEEventΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇSOMETimerEvent
  17639.  
  17640.                   Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇSOMEClientEvent
  17641.  
  17642.                   Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇSOMESinkEvent
  17643.  
  17644.                   Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇSOMEWorkProcEvent
  17645.  
  17646. When called by EMan, a callback expects the appropriate event instance as a 
  17647. parameter. For example, a callback registered for a timer event expects a 
  17648. SOMETimerEvent instance from EMan. 
  17649.  
  17650.  
  17651. ΓòÉΓòÉΓòÉ 10.1.3.3. EMan parameters ΓòÉΓòÉΓòÉ
  17652.  
  17653. Several method calls in the Event Management Framework make use of bit masks 
  17654. and constants as parameters (for example, EMSinkEvent or EMInputReadMask). 
  17655. These methods are defined in the include file "eventmsk.h". When a user plans 
  17656. to extend the Event Management Framework, care must be taken to avoid name and 
  17657. value collisions with the definitions in "eventmsk.h". For convenience, the 
  17658. contents of the "eventmsk.h" file are shown below. 
  17659.  
  17660. #ifndef H_EVENTMASKDEF
  17661. #define H_EVENTMASKDEF
  17662.  
  17663. /* Event Types */
  17664. #define EMTimerEvent                    54
  17665. #define EMSignalEvent                   55
  17666. #define EMSinkEvent                     56
  17667.  
  17668. #define EMWorkProcEvent                 57
  17669.  
  17670. #define EMClientEvent                   58
  17671.  
  17672. #define EMMsgQEvent                     59
  17673.  
  17674. /* Sink input/output condition mask */
  17675.  
  17676. #define EMInputReadMask                 (1L<0)
  17677. #define EMInputWriteMask                (1L<1)
  17678. #define EMInputExceptMask               (1L<2)
  17679.  
  17680. /* Process Event mask */
  17681.  
  17682. #define EMProcessTimerEvent             (1L<0)
  17683. #define EMProcessSinkEvent              (1L<1)
  17684. #define EMProcessWorkProcEvent          (1L<2)
  17685. #define EMProcessClientEvent            (1L<3)
  17686. #define EMProcessAllEvents              (1L<6)
  17687.  
  17688. #endif   /* H_EVENTMASKDEF */
  17689.  
  17690.  
  17691. ΓòÉΓòÉΓòÉ 10.1.3.4. Registering for events ΓòÉΓòÉΓòÉ
  17692.  
  17693. In addition to the event classes, the Event Management Framework uses a 
  17694. registration data class (SOMEEMRegisterData) to capture all event-related 
  17695. registration information. The procedure for registering interest in an event is 
  17696. as follows: 
  17697.  
  17698.    1. Create an instance of the SOMEEMRegisterData class (this will be referred 
  17699.       to as a "RegData" object). 
  17700.  
  17701.    2. Set the event type of "RegData." 
  17702.  
  17703.    3. Set the various fields of "RegData" to supply information about the 
  17704.       particular event for which an interest is being registered. 
  17705.  
  17706.    4. Call the registration method of EMan, using "RegData" and the callback 
  17707.       method information as parameters. The callback information varies, 
  17708.       depending upon whether it is a simple procedure, a method called using 
  17709.       OIDL call style, or a method called using IDL call style. 
  17710.  
  17711.  The following code segment illustrates how to register input interest in a 
  17712.  socket "sock" and provide a callback procedure "ReadMsg". 
  17713.  
  17714.   data = SOMEEMRegisterDataNew( );       /* create a RegData object */
  17715.   _someClearRegData(data, Ev);
  17716.   _someSetRegDataEventMask(data,Ev,EMSinkEvent,NULL); /* Event type */
  17717.   _someSetRegDataSink(data, Ev, sock);     /* provide the socket id */
  17718.   _someSetRegDataSinkMask(data,Ev, EMInputReadMask );
  17719.                                                    /*input interest */
  17720.   regId = _someRegisterProc(some_gEMan,Ev,data,ReadMsg,"UserData" );
  17721.   /* some_gEMan points to EMan. The last parameter "userData" is any
  17722.      data the user wants to be passed to the callback procedure as a
  17723.      second parameter */
  17724.  
  17725.  
  17726. ΓòÉΓòÉΓòÉ 10.1.4. Unregistering for events ΓòÉΓòÉΓòÉ
  17727.  
  17728. One can unregister interest in a given event type at any time. To unregister, 
  17729. you must provide the registration id returned by EMan at the time of 
  17730. registration. Unregistering a non-existent event (such as, an invalid 
  17731. registration id) is a no-op. The following example unregisters the socket 
  17732. registered above: 
  17733.  
  17734. _someUnRegister(some_gEMan, Ev, regId);
  17735.  
  17736.  
  17737. ΓòÉΓòÉΓòÉ 10.1.5. An example callback procedure ΓòÉΓòÉΓòÉ
  17738.  
  17739. The following code segment illustrates how to write a callback procedure: 
  17740.  
  17741. void SOMLINK ReadMsg( SOMEEvent  event, void  *targetData )
  17742. {
  17743. int sock;
  17744.     printf( "Data = %s\n", targetData );
  17745.     switch( _somevGetEventType( event )) {
  17746.     case  EMSinkEvent:
  17747.         printf("callback: Perceived Sink Event\n");
  17748.         sock = _somevGetEventSink(event);
  17749.         /* code to read the message off the socket */
  17750.         break;
  17751.     default: printf("Unknown Event type in socket callback\n");
  17752.     }
  17753. }
  17754. /* On OS/2, "system" linkage is also required.  */
  17755. /* On Windows, callbacks do not use the SOMLINK keyword if
  17756.  * the application is intended to support multiple instances. */
  17757.  
  17758.  
  17759. ΓòÉΓòÉΓòÉ 10.1.6. Generating client events ΓòÉΓòÉΓòÉ
  17760.  
  17761. While the other events are caused by the operating system (for example, Timer), 
  17762. by I/O devices, or by external processes, client events are caused by the 
  17763. application itself. The application creates these events and enqueues them with 
  17764. EMan. When client events are dispatched, they are processed in a callback 
  17765. routine just like any other event. The following code segment illustrates how 
  17766. to create and enqueue client events. 
  17767.  
  17768. clientEvent1 = SOMEClientEventNew();  /* create a client event */
  17769. _somevSetEventClientType( clientEvent1, Ev, "MyClientType" );
  17770. _somevSetEventClientData( clientEvent1, Ev,
  17771.                                    "I can give any data here");
  17772. /* assuming that "MyClientType" is already registered with EMan */
  17773. /* enqueue the above event with EMan */
  17774. _someQueueEvent(some_gEMan, Ev, clientEvent1);
  17775.  
  17776.  
  17777. ΓòÉΓòÉΓòÉ 10.1.7. Examples of using other events ΓòÉΓòÉΓòÉ
  17778.  
  17779. The sample program shipped with the Event Management Framework illustrates the 
  17780. tasks listed below. (Due to its large size, the source code is not included 
  17781. here.) 
  17782.  
  17783.      Registering and unregistering for Timer events. 
  17784.  
  17785.      Registering and unregistering for Workproc events. 
  17786.  
  17787.      Registering an AIX Message Queue, sending messages on it, and 
  17788.       unregistering the Message Queue. 
  17789.  
  17790.      Registering a stream socket that listens to incoming connection requests. 
  17791.       Also, sockets connecting, accepting a connection, and sending/receiving 
  17792.       messages through EMan. 
  17793.  
  17794.      Registering a file descriptor on AIX and reading one line of the file at 
  17795.       a time in a callback. 
  17796.  
  17797.  
  17798. ΓòÉΓòÉΓòÉ 10.1.8. Processing events ΓòÉΓòÉΓòÉ
  17799.  
  17800. After all registrations are finished, an application typically turns over 
  17801. control to EMan and is completely event driven thereafter. Typically, an 
  17802. application main program ends with the following call to EMan: 
  17803.  
  17804. _someProcessEvents(some_gEMan, Ev);
  17805.  
  17806. An equivalent way to process events is to write a main loop and call 
  17807. someProcessEvent from inside the main loop, as indicated: 
  17808.  
  17809. while (1) { /* do forever */
  17810.       _someProcessEvent( some_gEMan, Ev, EMProcessTimerEvent  ╨ó
  17811.                                          EMProcessSinkEvent   ╨ó
  17812.                                          EMProcessClientEvent ╨ó
  17813.                                          EMProcessWorkProcEvent );
  17814.       /***  Do other main loop work, as needed. ***/
  17815. }
  17816.  
  17817. The second way allows more precise control over what type of events to process 
  17818. in each call. The example above enables all four types to be processed. The 
  17819. required subset is formed by logically OR'ing the appropriate bit constants 
  17820. (these are defined in "eventmsk.h)".  Another difference is that the second way 
  17821. is a non-blocking call to EMan. That is, if there are no events to process, 
  17822. control returns to the main loop immediately, whereas someProcessEvents is a 
  17823. non-returning blocking call. For most applications, the first way of calling 
  17824. EMan is better, since it does not waste processor cycles when there are no 
  17825. events to process. 
  17826.  
  17827.  
  17828. ΓòÉΓòÉΓòÉ 10.1.9. Interactive applications ΓòÉΓòÉΓòÉ
  17829.  
  17830. Interactive applications need special attention when coupled with EMan. Once 
  17831. control is turned over to EMan by calling someProcessEvents, a single-threaded 
  17832. application (for example, on AIX) has no way of responding to keyboard input. 
  17833. The user must register interest in "stdin" with EMan and provide a callback 
  17834. function that handles keyboard input. In a multi-threaded environment (for 
  17835. example, OS/2), this problem can be solved by spawning a thread to execute 
  17836. someProcessEvents and another to handle keyboard input. (These two options are 
  17837. illustrated in the sample program shipped with the Event Management Framework.) 
  17838.  
  17839.  
  17840. ΓòÉΓòÉΓòÉ 10.2. Event Manager Advanced Topics ΓòÉΓòÉΓòÉ
  17841.  
  17842. This section contains the following subjects: 
  17843.  
  17844.      Threads and thread safety 
  17845.      Writing an X or MOTIF application 
  17846.      Extending EMan 
  17847.      Using EMan from C++ 
  17848.      Using EMan from other languages 
  17849.      Tips on using EMan 
  17850.  
  17851.  
  17852. ΓòÉΓòÉΓòÉ 10.2.1. Threads and thread safety ΓòÉΓòÉΓòÉ
  17853.  
  17854. As indicated earlier, on OS/2, interactive programs call someProcessEvents in 
  17855. one thread and process keyboard input in a separate thread. (This recommended 
  17856. usage is illustrated in the sample program). The event manager object (EMan) is 
  17857. thread safe in the sense that concurrent method invocations on EMan are 
  17858. serialized. Even when someProcessEvents is invoked in a thread and other 
  17859. methods of EMan are invoked from other threads, EMan still preserves its data 
  17860. integrity. However, when Eman dispatches an event, a callback can call methods 
  17861. on the same data objects as the other interactive thread(s). The user must 
  17862. protect such data objects using appropriate concurrency control techniques (for 
  17863. example by using semaphores). 
  17864.  
  17865. One must also be aware of some deadlock possibilities. Consider the following 
  17866. situation. EMan code holds some SOMobjects Toolkit semaphores while it is 
  17867. running (for example, while in someProcessEvents). A user-defined object 
  17868. protects its data by requiring its methods to acquire and release a sempahore 
  17869. on the object. If a separate thread running in this object were to call an 
  17870. operation that requires a SOMobjects Toolkit semaphore (which is currently held 
  17871. by EMan) and if concurrently EMan dispatches an event whose callback invokes a 
  17872. method of this object, a deadlock occurs. Two possibilities exist to cope with 
  17873. such a situation: One is to acquire all needed semaphores ahead of time, and 
  17874. the other is to abort the operation when you fail to obtain a semaphore. To 
  17875. achieve mutual exclusion with EMan, you can call the methods someGetEManSem and 
  17876. someReleaseEmanSem. These methods acquire and release the SOMobject Developer 
  17877. Toolkit semaphores that EMan uses. 
  17878.  
  17879.  
  17880. ΓòÉΓòÉΓòÉ 10.2.2. Writing an X or MOTIF application ΓòÉΓòÉΓòÉ
  17881.  
  17882. Although the Event Manager does not recognize X events, an X or MOTIF 
  17883. application can be integrated with EMan as follows. First, the necessary 
  17884. initialization of X or MOTIF should be performed. Next, using the Xlib macro 
  17885. "ConnectionNumber" or the "XConnectionNumber" function, you can obtain the file 
  17886. descriptor of the X connection. This file descriptor can be registered with 
  17887. EMan as a sink. It can be registered for both input events and exception 
  17888. events. When there is any activity on this X file descriptor, the 
  17889. developer-provided callback is invoked. The callback can receive the X-event, 
  17890. analyze it, and do further dispatching. See the example program in Chapter 9, 
  17891. "The Replication Framework" (section 9.7). 
  17892.  
  17893.  
  17894. ΓòÉΓòÉΓòÉ 10.2.3. Extending EMan ΓòÉΓòÉΓòÉ
  17895.  
  17896. The current event manager can be extended without having access to the source 
  17897. code. The use of EMan in an X or MOTIF application mentioned above is just one 
  17898. such example. Several other extensions are possible. For example, new event 
  17899. types can be defined by subclassing either directly from SOMEEvent class or 
  17900. from any of its subclasses in the framework. There are three main problems to 
  17901. solve in adding a new event type: 
  17902.  
  17903.      How to register a new event type with EMan? 
  17904.  
  17905.      How to make EMan recognize the occurrence of the new event? 
  17906.  
  17907.      How to make EMan create and send the new event object (a subclass of 
  17908.       SOMEEvent) to the callback when the event is dispatched? 
  17909.  
  17910.  Because the registration information is supplied with appropriate "set" 
  17911.  methods of a RegData object, the RegData object should be extended to include 
  17912.  additional methods.  This can be achieved by subclassing from 
  17913.  SOMEEMRegisterData and building a new registration data class that has methods 
  17914.  to "set" and "get" additional fields of information that are needed to 
  17915.  describe the new event types fully. To handle registrations with instances of 
  17916.  new registration data subclass, we must also subclass from SOMEEMan and 
  17917.  override the someRegister and the someUnRegister methods. These methods should 
  17918.  handle the information in the new fields introduced by the new registration 
  17919.  data class and call parent methods to handle the rest. 
  17920.  
  17921.  Making EMan recognize the occurrence of the new event is primarily limited by 
  17922.  the primitive events EMan can wait on. Thus the new event would have to be 
  17923.  wrapped in a primitive event that EMan can recognize. For example, to wait on 
  17924.  a message queue on OS/2 concurrently with other EMan events, a separate thread 
  17925.  can be made to wait on the message queue and to enqueue a client event with 
  17926.  EMan when a message arrives on this message queue. We can thus bring multiple 
  17927.  event sources into the single EMan main loop. 
  17928.  
  17929.  The third problem of creating new event objects unknown to EMan can be easily 
  17930.  done by applying the previous technique of wrapping the new event in terms of 
  17931.  a known event. In a callback routine of the known event, we can create and 
  17932.  dispatch the new event unknown to EMan. Of course, this does introduce an 
  17933.  intermediate callback routine which would not be needed if EMan directly 
  17934.  understood the new event type. 
  17935.  
  17936.  A general way of extending EMan is to look for newly defined event types by 
  17937.  overriding someProcessEvent and someProcessEvents in a subclass of EMan. 
  17938.  
  17939.  
  17940. ΓòÉΓòÉΓòÉ 10.2.4. Using EMan from C++ ΓòÉΓòÉΓòÉ
  17941.  
  17942. The Event Management framework can be used from C++ just like any other 
  17943. framework in the SOMobjects Toolkit. You must ensure that the C++ usage 
  17944. bindings (that is, the .xh files) are available for the Event Management 
  17945. Framework classes. These .xh files are generated by the SOM Compiler in the 
  17946. SOMobjects Toolkit when the -s option includes an xh emitter. 
  17947.  
  17948.  
  17949. ΓòÉΓòÉΓòÉ 10.2.5. Using EMan from other languages ΓòÉΓòÉΓòÉ
  17950.  
  17951. The event manager and the other classes can be used from other languages, 
  17952. provided usage bindings are available for them. These usage bindings are 
  17953. produced from .idl files of the framework classes by the appropriate language 
  17954. emitter. 
  17955.  
  17956.  
  17957. ΓòÉΓòÉΓòÉ 10.2.6. Tips on using EMan ΓòÉΓòÉΓòÉ
  17958.  
  17959. The following are some do's and don'ts for EMan: 
  17960.  
  17961.      Eman callback procedures or methods must return quickly. You cannot wait 
  17962.       for long periods of time to return from the callbacks. If such long 
  17963.       delays occur, then the application may not notice some subsequent events 
  17964.       in time to process them meaningfully (for example, a timer event may not 
  17965.       be noticed until long after it occurred). 
  17966.  
  17967.      It follows from the previous tip that you should not do independent 
  17968.       "select" system calls on file descriptors while inside a callback.  (This 
  17969.       applies to sockets and message queues, as well.) In general, a callback 
  17970.       should not do any blocking of system calls. If an application must do 
  17971.       this, then it must be done with a small timeout value. 
  17972.  
  17973.      Since EMan callbacks must return quickly, no callback should wait on a 
  17974.       semaphore indefinitely. If a callback has to obtain some semaphores 
  17975.       during its processing, then the callback should try to acquire all of 
  17976.       them at the very beginning, and should be prepared to abort and return to 
  17977.       EMan if it fails to acquire the necessary semaphores. 
  17978.  
  17979.      EMan callback methods are called using name-lookup resolution. Therefore, 
  17980.       the parameters to an EMan registration call must be such that the class 
  17981.       object of the object parameter must be able to provide a pointer to the 
  17982.       method indicated by the method parameter. Although this requirement is 
  17983.       satisfied in a majority of cases, there are exceptions.  For example, if 
  17984.       the object is a proxy (in the DSOM sense) to a remote object, then the 
  17985.       "real" class object cannot provide a meaningful method pointer. Also note 
  17986.       that, when somDspatch is overridden, the effect of such an override will 
  17987.       not  apply  to the callback from EMan.  Do not use a method callback in 
  17988.       these situations; instead, use a procedure callback. 
  17989.  
  17990.  
  17991. ΓòÉΓòÉΓòÉ 10.3. Limitations ΓòÉΓòÉΓòÉ
  17992.  
  17993. The present implementation of the Event Management framework has the 
  17994. limitations described below. For a more up-to-date list of limitations, refer 
  17995. to the README file on EMan in the SOMobjects Developer Toolkit. 
  17996.  
  17997.      EMan supports registering a maximum of 64 AIX message queues. 
  17998.  
  17999.      EMan can only wait on file descriptors (including files, pipes, sockets, 
  18000.       and message queues) on AIX, and socket identifiers on OS/2. 
  18001.  
  18002.      EMan supports registering a maximum of FILENO (the AIX limit on maximum 
  18003.       number of open files) file descriptors on AIX, and FD_SETSIZE socket 
  18004.       identifiers on OS/2 (FD_SETSIZE is defined by the TCP/IP product). 
  18005.  
  18006.  
  18007. ΓòÉΓòÉΓòÉ 10.3.1. Use of EMan DLL ΓòÉΓòÉΓòÉ
  18008.  
  18009. The Event Manager Framework uses a Sockets "select" call to wait on multiple 
  18010. sockets.  At the time of EMan creation, the SOMEEMan class object loads one of 
  18011. the Sockets subclass DLLs, based on the value of the environment variable 
  18012. SOMSOCKETS. This environment variable should name the implementation class of 
  18013. sockets (see Appendix E describing the Sockets abstract class and the specific 
  18014. implementation DLLs available with the SOMobjects Toolkit.) The current choices 
  18015. for this environment variable are TCPIPSockets, (and TCPIPSockets32 for OS/2), 
  18016. NBSockets, and IPXSockets . 
  18017.  
  18018.  
  18019. ΓòÉΓòÉΓòÉ 11. SOMobjects Error Codes ΓòÉΓòÉΓòÉ
  18020.  
  18021. This section covers the following subjects: 
  18022.  
  18023.      SOM Kernel Error Codes 
  18024.      DSOM Error Codes 
  18025.      Metaclass Framework Error Codes 
  18026.  
  18027.  
  18028. ΓòÉΓòÉΓòÉ 11.1. SOM Kernel Error Codes ΓòÉΓòÉΓòÉ
  18029.  
  18030. Following are error codes with messages/explanations for the SOM kernel and the 
  18031. various frameworks of the SOMobjects Developer Toolkit. 
  18032.  
  18033.  Value     Symbolic Name and Description 
  18034.  
  18035.  20011     SOMERROR_CCNullClass 
  18036.            The somDescendedFrom method was passed a null class argument. 
  18037.  
  18038.  20029     SOMERROR_SompntOverflow 
  18039.            The internal buffer used in somPrintf overflowed. 
  18040.  
  18041.  20039     SOMERROR_MethodNotFound 
  18042.            somFindMethodOk failed to find the indicated method. 
  18043.  
  18044.  20049     SOMERROR_StaticMethodTableOverflow 
  18045.            A Method-table overflow occurred in somAddStaticMethod. 
  18046.  
  18047.  20059     SOMERROR_DefaultMethod 
  18048.            The somDefaultMethod was called; a defined method probably was not 
  18049.            added before it was invoked. 
  18050.  
  18051.  20069     SOMERROR_MissingMethod 
  18052.            The specified method was not defined on the target object. 
  18053.  
  18054.  20079     SOMERROR_BadVersion 
  18055.            An attempt to load, create, or use a version of a class-object 
  18056.            implementation is incompatible with the using program. 
  18057.  
  18058.  20089     SOMERROR_NullId 
  18059.            The SOM_CheckId was given a null ID to check. 
  18060.  
  18061.  20099     SOMERROR_OutOfMemory 
  18062.            Memory is exhausted. 
  18063.  
  18064.  20109     SOMERROR_TestObjectFailure 
  18065.            The somObjectTest found problems with the object it was testing. 
  18066.  
  18067.  20119     SOMERROR_FailedTest 
  18068.            The somTest detected a failure; generated only by test code. 
  18069.  
  18070.  20121     SOMERROR_ClassNotFound 
  18071.            The somFindClass could not find the requested class. 
  18072.  
  18073.  20131     SOMERROR_OldMethod 
  18074.            An old-style method name was used; change to an appropriate name. 
  18075.  
  18076.  20149     SOMERROR_CouldNotStartup 
  18077.            The somEnvironmentNew failed to complete. 
  18078.  
  18079.  20159     SOMERROR_NotRegistered 
  18080.            The somUnloadClassFile argument was not a registered class. 
  18081.  
  18082.  20169     SOMERROR_BadOverride 
  18083.            The somOverrideSMethod was invoked for a method that was not defined 
  18084.            in a parent class. 
  18085.  
  18086.  20179     SOMERROR_NotImplementedYet 
  18087.            The method raising the error message is not implemented yet. 
  18088.  
  18089.  20189     SOMERROR_MustOverride 
  18090.            The method raising the error message should have been overridden. 
  18091.  
  18092.  20199     SOMERROR_BadArgument 
  18093.            An argument to a core SOM method failed a validity test. 
  18094.  
  18095.  20219     SOMERROR_NoParentClass 
  18096.            During the creation of a class object, the parent class could not be 
  18097.            found. 
  18098.  
  18099.  20229     SOMERROR_NoMetaClass 
  18100.            During the creation of a class object, the metaclass object could 
  18101.            not be found. 
  18102.  
  18103.  
  18104. ΓòÉΓòÉΓòÉ 11.2. DSOM Error Codes ΓòÉΓòÉΓòÉ
  18105.  
  18106. The  following table lists the error codes that may be encountered when using 
  18107. DSOM. 
  18108.  
  18109.  Value     Description 
  18110.  
  18111.  30001     SOMDERROR_NoMemory 
  18112.            Memory is exhausted. 
  18113.  
  18114.  30002     SOMDERROR_NotImplemented 
  18115.            Function or method has a null implementation. 
  18116.  
  18117.  30003     SOMDERROR_UnexpectedNULL 
  18118.            Internal error:  a pointer variable was found to be NULL, 
  18119.            unexpectedly. 
  18120.  
  18121.  30004     SOMDERROR_IO 
  18122.            I/O error while accessing a file located in SOMDDIR. 
  18123.  
  18124.  30005     SOMDERROR_BadVersion 
  18125.            Internal error:  incorrect version of an object reference data 
  18126.            table. 
  18127.  
  18128.  30006     SOMDERROR_ParmSize 
  18129.            Internal error:  a parameter of incorrect size was detected. 
  18130.  
  18131.  30007     SOMDERROR_HostName 
  18132.            Communications error:  unable to retrieve local host name. 
  18133.  
  18134.  30008     SOMDERROR_HostAddress 
  18135.            Communications error:  unable to retrieve local host address. 
  18136.  
  18137.  30009     SOMDERROR_SocketCreate 
  18138.            Communications error:  unable to create socket. 
  18139.  
  18140.  30010     SOMDERROR_SocketBind 
  18141.            Communications error:  unable to bind address to socket. 
  18142.  
  18143.  30011     SOMDERROR_SocketName 
  18144.            Communications error:  unable to query socket information. 
  18145.  
  18146.  30012     SOMDERROR_SocketReceive 
  18147.            Communications error:  unable to receive message from socket. 
  18148.  
  18149.  30013     SOMDERROR_SocketSend 
  18150.            Communications error: indicates socket error. 
  18151.  
  18152.  30014     SOMDERROR_SocketIoctl 
  18153.            Communications error:  unable to set socket blocking state. 
  18154.  
  18155.  30015     SOMDERROR_SocketSelect 
  18156.            Communications error:  unable to select on socket. 
  18157.  
  18158.  30016     SOMDERROR_PacketSequence 
  18159.            Communications error:  unexpected message packet received. 
  18160.  
  18161.  30017     SOMDERROR_PacketTooBig 
  18162.            Communications error:  packet too big for allocated message space. 
  18163.  
  18164.  30018     SOMDERROR_AddressNotFound 
  18165.            Uninitialized DSOM communications object. 
  18166.  
  18167.  30019     SOMDERROR_NoMessages 
  18168.            No messages available (and caller specified "no wait"). 
  18169.  
  18170.  30020     SOMDERROR_UnknownAddress 
  18171.            Invalid client or server address. 
  18172.  
  18173.  30021     SOMDERROR_RecvError 
  18174.            Communications error during receive. 
  18175.  
  18176.  30022     SOMDERROR_SendError 
  18177.            Communications error in sending the request. 
  18178.  
  18179.  30023     SOMDERROR_CommTimeOut 
  18180.            Communications timeout. 
  18181.  
  18182.  30024     SOMDERROR_CannotConnect 
  18183.            Unable to initialize connection information. 
  18184.  
  18185.  30025     SOMDERROR_BadConnection 
  18186.            Invalid connection information detected. 
  18187.  
  18188.  30026     SOMDERROR_NoHostName 
  18189.            Unable to get host name. 
  18190.  
  18191.  30027     SOMDERROR_BadBinding 
  18192.            Invalid server location information in proxy object. 
  18193.  
  18194.  30028     SOMDERROR_BadMethodName 
  18195.            Invalid method name in request message. 
  18196.  
  18197.  30029     SOMDERROR_BadEnvironment 
  18198.            Invalid Environment value in request message. 
  18199.  
  18200.  30030     SOMDERROR_BadContext 
  18201.            Invalid Context object in request message. 
  18202.  
  18203.  30031     SOMDERROR_BadNVList 
  18204.            Invalid Named Value List (NVList). 
  18205.  
  18206.  30032     SOMDERROR_BadFlag 
  18207.            Bad flag in NVList item. 
  18208.  
  18209.  30033     SOMDERROR_BadLength 
  18210.            Bad length in NVList item. 
  18211.  
  18212.  30034     SOMDERROR_BadObjref 
  18213.            Invalid object reference. 
  18214.  
  18215.  30035     SOMDERROR_NullField 
  18216.            Unexpected null field in request message. 
  18217.  
  18218.  30036     SOMDERROR_UnknownReposId 
  18219.            Attempt to use Invalid Interface Repository ID. 
  18220.  
  18221.  30037     SOMDERROR_NVListAccess 
  18222.            Invalid NVList object in request message. 
  18223.  
  18224.  30038     SOMDERROR_NVIndexError 
  18225.            Attempt to use an out-of-range NVList index. 
  18226.  
  18227.  30039     SOMDERROR_SysTime 
  18228.            Error retrieving system time. 
  18229.  
  18230.  30040     SOMDERROR_SystemCallFailed 
  18231.            System call failed. 
  18232.  
  18233.  30041     SOMDERROR_CouldNotStartProcess 
  18234.            Unable to start a new process. 
  18235.  
  18236.  30042     SOMDERROR_NoServerClass 
  18237.            No SOMDServer (sub)class specified for server implementation. 
  18238.  
  18239.  30043     SOMDERROR_NoSOMDInit 
  18240.            Missing SOMD_Init call in program. 
  18241.  
  18242.  30044     SOMDERROR_SOMDDIRNotSet 
  18243.            SOMDDIR environment variable not set. 
  18244.  
  18245.  30045     SOMDERROR_NoImplDatabase 
  18246.            Could not open Implementation Repository database. 
  18247.  
  18248.  30046     SOMDERROR_ImplNotFound 
  18249.            Implementation not found in implementation repository. 
  18250.  
  18251.  30047     SOMDERROR_ClassNotFound 
  18252.            Class not found in implementation repository. 
  18253.  
  18254.  30048     SOMDERROR_ServerNotFound 
  18255.            Server not found in somdd's active server table. 
  18256.  
  18257.  30049     SOMDERROR_ServerAlreadyExists 
  18258.            Server already exists in somdd's active server table. 
  18259.  
  18260.  30050     SOMDERROR_ServerNotActive 
  18261.            Server is not active. 
  18262.  
  18263.  30051     SOMDERROR_CouldNotStartSOM 
  18264.            SOM initialization error. 
  18265.  
  18266.  30052     SOMDERROR_ObjectNotFound 
  18267.            Could not find desired object. 
  18268.  
  18269.  30053     SOMDERROR_NoParentClass 
  18270.            Unable to find / load parent class during proxy class creation. 
  18271.  
  18272.  30054     SOMDERROR_DispatchError 
  18273.            Unable to dispatch method. 
  18274.  
  18275.  30055     SOMDERROR_BadTypeCode 
  18276.            Invalid type code. 
  18277.  
  18278.  30056     SOMDERROR_BadDescriptor 
  18279.            Invalid method descriptor. 
  18280.  
  18281.  30057     SOMDERROR_BadResultType 
  18282.            Invalid method result type. 
  18283.  
  18284.  30058     SOMDERROR_KeyInUse 
  18285.            Internal object key is in use. 
  18286.  
  18287.  30059     SOMDERROR_KeyNotFound 
  18288.            Internal object key not found. 
  18289.  
  18290.  30060     SOMDERROR_CtxInvalidPropName 
  18291.            Illegal context property name. 
  18292.  
  18293.  30061     SOMDERROR_CtxNoPropFound 
  18294.            Could not find property name in context. 
  18295.  
  18296.  30062     SOMDERROR_CtxStartScopeNotFound 
  18297.            Could not find specified context start scope. 
  18298.  
  18299.  30063     SOMDERROR_CtxAccess 
  18300.            Error accessing context object. 
  18301.  
  18302.  30064     SOMDERROR_CouldNotStartThread 
  18303.            System error:  Could not start thread. 
  18304.  
  18305.  30065     SOMDERROR_AccessDenied 
  18306.            System error:  Access to a system resource (file, queue, shared 
  18307.            memory, etc.) denied. 
  18308.  
  18309.  30066     SOMDERROR_BadParm 
  18310.            System error:  invalid parameter supplied to a operating system 
  18311.            call. 
  18312.  
  18313.  30067     SOMDERROR_Interrupt 
  18314.            System error:  Interrupted system call. 
  18315.  
  18316.  30068     SOMDERROR_Locked 
  18317.            System error:  Drive locked by another process. 
  18318.  
  18319.  30069     SOMDERROR_Pointer 
  18320.            System error:  Invalid physical address. 
  18321.  
  18322.  30070     SOMDERROR_Boundary 
  18323.            OS/2 system error:  ERROR_CROSSES_OBJECT_BOUNDARY. 
  18324.  
  18325.  30071     SOMDERROR_UnknownError 
  18326.            System error:  Unknown error on operating system call. 
  18327.  
  18328.  30072     SOMDERROR_NoSpace 
  18329.            System error:  No space left on device. 
  18330.  
  18331.  30073     SOMDERROR_DuplicateQueue 
  18332.            System error:  Duplicate queue name. 
  18333.  
  18334.  30074     SOMDERROR_BadQueueName 
  18335.            System error:  Invalid queue name. 
  18336.  
  18337.  30075     SOMDERROR_DuplicateSem 
  18338.            System error:  Duplicate semaphore name used. 
  18339.  
  18340.  30076     SOMDERROR_BadSemName 
  18341.            System error:  Invalid semaphore name. 
  18342.  
  18343.  30077     SOMDERROR_TooManyHandles 
  18344.            System error:  Too many files open (no file handles left). 
  18345.  
  18346.  30078     SOMDERROR_BadAddrFamily 
  18347.            System error:  Invalid address family. 
  18348.  
  18349.  30079     SOMDERROR_BadFormat 
  18350.            System error:  Invalid format. 
  18351.  
  18352.  30080     SOMDERROR_BadDrive 
  18353.            System error:  Invalid drive. 
  18354.  
  18355.  30081     SOMDERROR_SharingViolation 
  18356.            System error:  Sharing violation. 
  18357.  
  18358.  30082     SOMDERROR_BadExeSignature 
  18359.            System error:  Program file contains a DOS mode program or invalid 
  18360.            program. 
  18361.  
  18362.  30083     SOMDERROR_BadExe 
  18363.            Executable file is invalid (linker errors occurred when program file 
  18364.            was created). 
  18365.  
  18366.  30084     SOMDERROR_Busy 
  18367.            System error:  Segment is busy. 
  18368.  
  18369.  30085     SOMDERROR_BadThread 
  18370.            System error:  Invalid thread id. 
  18371.  
  18372.  30086     SOMDERROR_SOMDPORTNotDefined 
  18373.            SOMDPORT not defined. 
  18374.  
  18375.  30087     SOMDERROR_ResourceExists 
  18376.            System resource (file, queue, shared memory segment,. etc.) already 
  18377.            exists. 
  18378.  
  18379.  30088     SOMDERROR_UserName 
  18380.            USER environment variable is not set. 
  18381.  
  18382.  30089     SOMDERROR_WrongRefType 
  18383.            Operation attempted on an object reference is incompatible with the 
  18384.            reference type. 
  18385.  
  18386.  30090     SOMDERROR_MustOverride 
  18387.            This method has no default implementation and must be overridden. 
  18388.  
  18389.  30091     SOMDERROR_NoSocketsClass 
  18390.            Could not find/load Sockets class. 
  18391.  
  18392.  30092     SOMDERROR_EManRegData 
  18393.            Unable to register DSOM events with the Event Manager. 
  18394.  
  18395.  30093     SOMDERROR_NoRemoteComm 
  18396.            Remote communications is disabled (for Workstation DSOM). 
  18397.  
  18398.  30096     SOMDERROR_GlobalAtomError 
  18399.            On Windows only, an error occurred while adding a segment name 
  18400.            to the Windows atom table. 
  18401.  
  18402.  30097     SOMDERROR_NamedMemoryTableError 
  18403.            On Windows only, an error occurred while creating or deleting a 
  18404.            (named) shared memory segment. 
  18405.  
  18406.  30098     SOMDERROR_WMQUIT 
  18407.            On Windows only, indicates DSOM received a Windows WM_QUIT message. 
  18408.            The developer of a server application should check for 
  18409.            SOMDERROR_WMQUIT returned from method execute_request_loop and 
  18410.            handle the error by cleaning up and exiting. 
  18411.  
  18412.  30105     SOMDERROR_DuplicateImplEntry 
  18413.            Implementation repository identifier already exists.  Add wait time 
  18414.            between `regimpl' calls. 
  18415.  
  18416.  30106     SOMDERROR_InvalidSOMSOCKETS 
  18417.            SOMSOCKETS environment variable set incorrectly. 
  18418.  
  18419.  30107     SOMDERR0R_IRNotFound 
  18420.            Interface Repository not found. 
  18421.  
  18422.  30108     SOMDERR0R_ClassNotInIR 
  18423.            Attempt to create an object whose Class is not in the Interface 
  18424.            Repository. 
  18425.  
  18426.  30110     SOMDERROR_SocketError 
  18427.            A communications socket error has occurred.  Make sure the DSOM 
  18428.            daemon is running. 
  18429.  
  18430.  30111     SOMDERROR_PacketError 
  18431.            A communications packet error has occurred. 
  18432.  
  18433.  30112     SOMDERROR_Marshal 
  18434.  
  18435.  30113     SOMDERROR_NotProcessOwner 
  18436.            This error code is returned when the somdd daemon is trying to kill 
  18437.            the server process and if the owner of the server process is 
  18438.            different from that of the somdd daemon. 
  18439.  
  18440.  30114     SOMDERROR_ServerInactive 
  18441.            The specified server is in the process of being activated. 
  18442.  
  18443.  30115     SOMDERROR_ServerDisabled 
  18444.            The server has been disabled by the program servmgr. 
  18445.  
  18446.  30117     SOMDERROR_SOMDAlreadyRunning 
  18447.            The DSOM daemon has been started when another daemon is already 
  18448.            running. 
  18449.  
  18450.  30118     SOMDERROR_ServerToBeDeleted 
  18451.            An attempt has been made to start or connect to a server marked for 
  18452.            deletion. 
  18453.  
  18454.  30119     SOMDERROR_NoObjRefTable 
  18455.            The Object Reference Table cannot be found. 
  18456.  
  18457.  30120     SOMDERROR_UpdateImplDef 
  18458.            The Implementation Repository cannot be updated. 
  18459.  
  18460.  30138     SOMDERROR_NoImplDirectory 
  18461.            The directory signified by SOMDDIR does not exist. 
  18462.  
  18463.  30169     SOMDERROR_ServerNotStoppable 
  18464.            An attempt has been made to stop a server (using the dsom stop 
  18465.            command or a SOMDServerMgr object) registered as nonstoppable. 
  18466.  
  18467.  XXXXX     SOMDERROR_OperatingSystem 
  18468.            On AIX, this is the value of the C error variable "errno" defined in 
  18469.            errno.h; on OS/2 and Windows, it is the DOS API return code. 
  18470.  
  18471.  
  18472. ΓòÉΓòÉΓòÉ 11.3. Metaclass Framework Error Codes ΓòÉΓòÉΓòÉ
  18473.  
  18474. It is possible to receive the following messages from the Metaclass Framework 
  18475. while an application is running. 
  18476.  
  18477.  60001     An attempt was made to construct a class with SOMMSingleInstance as 
  18478.            a metaclass constraint. (This may occur indirectly because of the 
  18479.            construction of a derived metaclass). The initialization of the 
  18480.            class failed because somInitMIClass defined by SOMMSingleInstance is 
  18481.            in conflict with another metaclass that has overridden somNew. That 
  18482.            is, some other metaclass has already claimed the right to return the 
  18483.            value for somNew. 
  18484.  
  18485.  60002     An attempt was made to construct a class with SOMMSingleInstance as 
  18486.            a metaclass constraint. (This may occur indirectly because of the 
  18487.            construction of a derived metaclass). The initialization of the 
  18488.            class failed because somInitMIClass defined by SOMMSingleInstance is 
  18489.            in conflict with another metaclass that has overridden somFree. That 
  18490.            is, some other metaclass has already claimed this right to override 
  18491.            somFree. 
  18492.  
  18493.  60004     An invocation of somrRepInit was made with a logging type other tha 
  18494.            `o' or `v'. 
  18495.  
  18496.  60005     The sommBeforeMethod or the sommAfterMethod was invoked on a 
  18497.            SOMRReplicableObject whose logging type is other than `o' or `v'. 
  18498.            This error cannot occur normally. The likely cause is that some 
  18499.            method invoked on another object has overwritten this object's 
  18500.            memory. 
  18501.  
  18502.  60006     A Before/After Metaclass must override both sommBeforeMethod and 
  18503.            sommAfterMethod.  This message indicates an attempt to create a 
  18504.            Before/After Metaclass where only one of the above methods is 
  18505.            overridden. 
  18506.  
  18507.  
  18508. ΓòÉΓòÉΓòÉ 12. SOM IDL Language Grammar ΓòÉΓòÉΓòÉ
  18509.  
  18510.  specification                 : [comment]  definition+ 
  18511.  definition                    : type_dcl  ; [comment] 
  18512.                                | const_dcl ; [comment] 
  18513.                                | interface ; [comment] 
  18514.                                | module   ; [comment] 
  18515.                                | pragma_stm 
  18516.  module                        : module identifier [comment] 
  18517.                                { [comment] definition+ } 
  18518.  interface                     : interface  identifier 
  18519.                                | interface_dcl 
  18520.  interface_dcl                 : interface identifier [inheritance] [comment] 
  18521.                                { [comment] export* } [comment] 
  18522.  inheritance                   : scoped_name {, scoped_name}* 
  18523.  export                        : type_dcl ; [comment] 
  18524.                                | const_dcl ; [comment] 
  18525.                                | attr_dcl ; [comment] 
  18526.                                | op_dcl ; [comment] 
  18527.                                | implementation_body ; [comment] 
  18528.                                | pragma_stm 
  18529.  scoped_name                   : identifier 
  18530.                                | :: identifer 
  18531.                                | scoped_name :: identifer 
  18532.  const_dcl                     : const const_type identifier = 
  18533.                                const_expr 
  18534.  const_type                    : integer_type 
  18535.                                | char_type 
  18536.                                | boolean_type 
  18537.                                | floating_pt_type 
  18538.                                | string_type 
  18539.                                | scoped_name 
  18540.  const_expr                    : or_expr 
  18541.  or_expr                       : xor_expr 
  18542.                                | or_expr 
  18543.                                | xor_expr 
  18544.  xor_expr                      : and_expr|xor_expr ^ and_expr 
  18545.  and_expr                      : shift_expr 
  18546.                                | and_expr & shift_expr 
  18547.  shift_expr                    : add_expr: 
  18548.                                | shift_expr:epv.:pk. >>  add_expr 
  18549.                                | shift_expr:epv. <<  add_expr 
  18550.  add_expr                      : mult_expr 
  18551.                                | add_expr + mult_expr 
  18552.                                | add_expr - mult_expr 
  18553.  mult_expr                     : unary_expr 
  18554.                                | mult_expr * unary_expr 
  18555.                                | mult_expr / unary_expr 
  18556.                                | mult_expr % unary_expr 
  18557.  unary_expr                    : unary_operator primary_expr 
  18558.                                | primary_expr 
  18559.  unary_operator                : - 
  18560.                                | + 
  18561.                                | ~ 
  18562.  primary_expr                  : scoped_name 
  18563.                                | literal 
  18564.                                | ( const_expr ) 
  18565.  literal                       : integer_literal 
  18566.                                | string_literal 
  18567.                                | character_literal 
  18568.                                | floating_pt_literal 
  18569.                                | boolean_literal 
  18570.  type_dcl                      : typedef type_declarator 
  18571.                                | constr_type_spec 
  18572.  type_declarator               : type_spec declarator {, declarator}* 
  18573.  type_spec                     : simple_type_spec 
  18574.                                | constr_type_spec 
  18575.  simple_type_spec              : base_type_spec 
  18576.                                | template_type_spec 
  18577.                                | scoped_name 
  18578.  base_type_spec                : floating_pt_type 
  18579.                                | integer_type 
  18580.                                | char_type 
  18581.                                | boolean_type 
  18582.                                | octet_type 
  18583.                                | any_type 
  18584.                                | voidptr_type 
  18585.  template_type_spec            : sequence_type 
  18586.                                | string_type 
  18587.  constr_type_spec              : struct_type 
  18588.                                | union_type 
  18589.                                | enum_type 
  18590.  declarator                    : [stars] std_declarator 
  18591.  std_declarator                : simple_declarator 
  18592.                                | complex_declarator 
  18593.  simple_declarator             : identifier 
  18594.  complex_declarator            : array_declarator 
  18595.  array_declarator              : simple_declarator fixed_array_size+ 
  18596.  fixed_array_size              : [ const_expr  ] 
  18597.  floating_pt_type              : float 
  18598.                                | double 
  18599.  integer_type                  : signed_int 
  18600.                                | unsigned_int 
  18601.  signed_int                    : long 
  18602.                                | short 
  18603.  unsigned_int                  : unsigned signed_int 
  18604.  char_type                     : char 
  18605.  boolean_type                  : boolean 
  18606.  octet_type                    : octet 
  18607.  any_type                      : any 
  18608.  voidptr_type                  : void stars 
  18609.  struct_type                   : ( struct|exception) identifier 
  18610.                                | ( struct|exception) [comment] 
  18611.                                { [comment] member* } 
  18612.  member                        : type_declarator ; [comment] 
  18613.  union_type                    : union identifier 
  18614.                                | union identifier switch 
  18615.                                ( switch_type_spec ) [ 
  18616.                                comment] 
  18617.                                { [comment] case+ } 
  18618.  switch_type_spec              : integer_type 
  18619.                                | char_type 
  18620.                                | boolean_type 
  18621.                                | enum_type 
  18622.                                | scoped_name 
  18623.  case                          : case_label+ element_spec ; [comment] 
  18624.  case_label                    : case const_expr : [comment] 
  18625.                                | default : [comment] 
  18626.  element_spec                  : type_spec declarator 
  18627.  enum_type                     : enum identifier { identifier 
  18628.                                {, identifier}* [comment] } 
  18629.  sequence_type                 : sequence < simple_type_spec , const_expr > 
  18630.                                | sequence < simple_type_spec > 
  18631.  string_type                   : string < const_expr > 
  18632.                                | string 
  18633.  attr_dcl                      : [readonly]  attribute simple_type_spec 
  18634.                                declarator {, declarator}* 
  18635.  op_dcl                        : [oneway] op_type_spec [stars] identifier 
  18636.                                parameter_dcls [raises_expr] [context_expr] 
  18637.  op_type_spec                  : simple_type_spec 
  18638.                                | void 
  18639.  parameter_dcls                : ( param_dcl {, param_dcl}* [comme  nt]  ) 
  18640.                                | (  ) 
  18641.  param_dcl                     : param_attribute simple_type_spec declarator 
  18642.  param_attribute               : in 
  18643.                                | out 
  18644.                                | inout 
  18645.  raises_expr                   : raises ( scope_name+ ) 
  18646.  context_expr                  : context  ( context_string{, context_string}* 
  18647.                                ) 
  18648.  implementation_body           : implementation [comment] 
  18649.                                { [comment] implementation+ } 
  18650.  implementation                : modifier_stm 
  18651.                                | pragma_stm 
  18652.                                | passthru 
  18653.                                | member 
  18654.  pragma_stm                    : #pragma modifier modifier_stm 
  18655.                                | #pragma somtemittypes on 
  18656.                                | #pragma somtemittypes off 
  18657.  modifier_stm                  : smidentifier : [modifier {, modifier}*] 
  18658.                                ;[comment] 
  18659.                                | modifier ; [comment] 
  18660.  modifier                      : smidentifier 
  18661.                                | smidentifier =  modifier_value 
  18662.  modifier_value                : smidentifier 
  18663.                                | string_literal 
  18664.                                | integer_literal 
  18665.                                | keyword 
  18666.  passthru                      :  passthru identifier = string_literal+  ; 
  18667.                                [comment] 
  18668.  smidentifier                  : identifer 
  18669.                                | _identifier 
  18670.  stars                         | *+ 
  18671.  
  18672.  
  18673. ΓòÉΓòÉΓòÉ 13. Implementing Sockets Subclasses ΓòÉΓòÉΓòÉ
  18674.  
  18675. Distributed SOM (DSOM) and the Replication Framework require basic message 
  18676. services for inter-process communications. The Event Management Framework must 
  18677. be integrated with the same communication services in order to handle 
  18678. communications events. 
  18679.  
  18680. To maximize their portability to a wide variety of local area network transport 
  18681. protocols, the DSOM, Replication, and Event Management Frameworks have been 
  18682. written to use a common communications interface, which is implemented by one 
  18683. or more SOM class libraries using available local protocols. 
  18684.  
  18685. The common communications interface is based on the "sockets" interface used 
  18686. with TCP/IP, since its interface and semantics are fairly widespread and well 
  18687. understood. The IDL interface is named Sockets. There is no implementation 
  18688. associated with the Sockets interface by default; specific protocol 
  18689. implementations are supplied by subclass implementations. 
  18690.  
  18691. Note:  The Sockets classes supplied with the SOMobjects Developer Toolkit and 
  18692.        run-time packages are only intended to support the DSOM, Replication, 
  18693.        and Event Management Frameworks. These class implementations are not 
  18694.        intended for general application usage. 
  18695.  
  18696.  Available Sockets subclasses by SOMobjects product are as follows: 
  18697.  
  18698.      For AIX: 
  18699.            TCPIPSockets class for TCP/IP, 
  18700.            IPXSockets class for Netware IPX/SPX, and 
  18701.            NBSockets class for NetBIOS. 
  18702.      For OS/2 and Windows: 
  18703.            TCPIPSockets class (a) for TCP/IP for Windows or (b) for TCP/IP 
  18704.            1.2.1 on OS/2, 
  18705.            TCPIPSockets32 class for TCP/IP 2.0 on OS/2 only (see Note below), 
  18706.            IPXSockets class for NetWare IPX/SPX, and 
  18707.            NBSockets class for NetBIOS. 
  18708.  
  18709.  Note:  The TCPIPSocket32 class gives greater performance over the TCPIPSockets 
  18710.         class on OS/2, but requires the 32-bit version of TCPP/IP (version 2.0) 
  18711.         rather than the 16-bit version of TCP/IP (version 1.2.1). 
  18712.  
  18713.  Application developers may need to develop their own Sockets  subclass if the 
  18714.  desired transport protocol or product version is not one of those supported by 
  18715.  the SOMobjects run-time packages. This appendix explains how to approach the 
  18716.  implementation of a Sockets subclass, if necessary. 
  18717.  
  18718.  Warning: this may be a non-trivial exercise! 
  18719.  
  18720.  
  18721. ΓòÉΓòÉΓòÉ 13.1. Sockets IDL interface ΓòÉΓòÉΓòÉ
  18722.  
  18723. The base Sockets interface is expressed in IDL in the file somssock.idl, listed 
  18724. below. There is a one-to-one mapping between TCP/IP socket APIs and the methods 
  18725. defined in the Sockets interface. 
  18726.  
  18727. Please note the following: 
  18728.  
  18729.      The semantics of each of the Sockets methods must be that of the 
  18730.       corresponding TCP/IP call. Currently, only Internet address family 
  18731.       (AF_INET) addresses are used by the frameworks. 
  18732.  
  18733.       (The TCP/IP sockets API is not documented as part of the SOMobjects 
  18734.       Developer Toolkit. The implementor is referred to the programming 
  18735.       references for IBM TCP/IP for AIX or OS/2, or to similar references that 
  18736.       describe the sockets interface for TCP/IP.) 
  18737.  
  18738.      Data types, constants, and macros which are part of the Sockets interface 
  18739.       are defined in a C include file, soms.h. This file is supplied with the 
  18740.       SOMobjects Toolkit, and is not shown in this manual. 
  18741.  
  18742.      The Sockets interface is expressed in terms of a 32-bit implementation. 
  18743.  
  18744.      Some of the method parameters and return values are expressed using 
  18745.       pointer types, for example: 
  18746.  
  18747.             hostent *somsGethostent ();
  18748.  
  18749.       This has been done to map TCP/IP socket interfaces as directly as 
  18750.       possible to their IDL equivalent. (Use of strict CORBA IDL was not a 
  18751.       primary goal for the Sockets interface, since it is only used internally 
  18752.       by the frameworks.) 
  18753.  
  18754.      The Sockets class and its subclasses are  single instance classes. 
  18755.  
  18756.  Following is a listing of the file somssock.idl. Each socket call is briefly 
  18757.  described with a comment. 
  18758.  
  18759.   // 96F8647, 96F8648 (C) Copyright IBM Corp. 1992, 1993
  18760.   // All Rights Reserved
  18761.   // Licensed Materials - Property of IBM
  18762.  
  18763.   #ifndef somssock_idl
  18764.   #define somssock_idl
  18765.  
  18766.   #include <somobj.idl>
  18767.   #include <snglicls.idl>
  18768.  
  18769.   interface Sockets : SOMObject
  18770.   {
  18771.       //# The following typedefs are fully defined in <soms.h>.
  18772.       typedef SOMFOREIGN sockaddr;
  18773.       #pragma modifier sockaddr : impctx="C", struct;
  18774.       typedef SOMFOREIGN iovec;
  18775.       #pragma modifier iovec : impctx="C", struct;
  18776.       typedef SOMFOREIGN msghdr;
  18777.       #pragma modifier msghdr : impctx="C", struct;
  18778.       typedef SOMFOREIGN fd_set;
  18779.       #pragma modifier fd_set : impctx="C", struct;
  18780.       typedef SOMFOREIGN timeval;
  18781.       #pragma modifier timeval : impctx="C", struct;
  18782.       typedef SOMFOREIGN hostent;
  18783.       #pragma modifier hostent : impctx="C", struct;
  18784.       typedef SOMFOREIGN servent;
  18785.       #pragma modifier servent : impctx="C", struct;
  18786.       typedef SOMFOREIGN in_addr;
  18787.       #pragma modifier in_addr : impctx="C", struct;
  18788.  
  18789.       long somsAccept (in long s, out sockaddr name, out long namelen);
  18790.       // Accept a connection request from a client.
  18791.  
  18792.       long somsBind (in long s, inout sockaddr name, in long namelen);
  18793.       // Binds a unique local name to the socket with descriptor s.
  18794.  
  18795.       long somsConnect (in long s, inout sockaddr name,
  18796.                         in long namelen);
  18797.       // For streams sockets, attempts to establish a connection
  18798.       // between two sockets.  For datagram sockets, specifies the
  18799.       // socket's peer.
  18800.  
  18801.       hostent *somsGethostbyaddr (in char *addr, in long addrlen,
  18802.                                   in long domain);
  18803.       // Returns a hostent structure for the host address specified on
  18804.       // the call.
  18805.  
  18806.       hostent *somsGethostbyname (in string name);
  18807.       // Returns a hostent structure for the host name specified on
  18808.       // the call.
  18809.  
  18810.       hostent *somsGethostent ();
  18811.       // Returns a pointer to the next entry in the hosts file.
  18812.  
  18813.       unsigned long somsGethostid ();
  18814.       // Returns the unique identifier for the current host.
  18815.  
  18816.       long somsGethostname (in string name, in long namelength);
  18817.       // Retrieves the standard host name of the local host.
  18818.  
  18819.       long somsGetpeername (in long s, out sockaddr name,
  18820.                            out long namelen);
  18821.       // Gets the name of the peer connected to socket s.
  18822.  
  18823.       servent *somsGetservbyname (in string name, in string protocol);
  18824.       // Retrieves an entry from the /etc/services file using the
  18825.       // service name as a search key.
  18826.  
  18827.       long somsGetsockname (in long s, out sockaddr name,
  18828.                             out long namelen);
  18829.       // Stores the current name for the socket specified by the s
  18830.       // parameter into the structure pointed to by the name
  18831.       // parameter.
  18832.  
  18833.       long somsGetsockopt (in long s, in long level, in long optname,
  18834.                           in char *optval, out long option);
  18835.       // Returns the values of socket options at various protocol
  18836.       // levels.
  18837.  
  18838.       unsigned long somsHtonl (in unsigned long a);
  18839.       // Translates an unsigned long integer from host-byte order to
  18840.       // network-byte order.
  18841.  
  18842.       unsigned short somsHtons (in unsigned short a);
  18843.       // Translates an unsigned short integer from host-byte order to
  18844.       // network-byte order.
  18845.  
  18846.       long somsIoctl (in long s, in long cmd, in char *data,
  18847.                       in long length);
  18848.       // Controls the operating characteristics of sockets.
  18849.  
  18850.       unsigned long somsInet_addr (in string cp);
  18851.       // Interprets character strings representing numbers expressed
  18852.       // in standard '.' notation and returns numbers suitable for use
  18853.       // as internet addresses.
  18854.  
  18855.       unsigned long somsInet_lnaof (in in_addr addr);
  18856.       // Breaks apart the internet address and returns the local
  18857.       // network address portion.
  18858.  
  18859.       in_addr somsInet_makeaddr (in unsigned long net,
  18860.                                  in unsigned long lna);
  18861.       // Takes a network number and a local network address and
  18862.       // constructs an internet address.
  18863.  
  18864.       unsigned long somsInet_netof (in in_addr addr);
  18865.       // Returns the network number portion of the given internet
  18866.       // address.
  18867.  
  18868.       unsigned long somsInet_network (in string cp);
  18869.       // Interprets character strings representing numbers expressed
  18870.       // in standard '.' notation and returns numbers suitable for use
  18871.       // as network numbers.
  18872.  
  18873.       string somsInet_ntoa (in in_addr addr);
  18874.       // Returns a pointer to a string expressed in the dotted-decimal
  18875.       // notation.
  18876.  
  18877.       long somsListen (in long s, in long backlog);
  18878.       // Creates a connection request queue of length backlog to queue
  18879.       // incoming connection requests, and then waits for incoming
  18880.       // connection requests.
  18881.  
  18882.       unsigned long somsNtohl (in unsigned long a);
  18883.       // Translates an unsigned long integer from network-byte order
  18884.       // to host-byte order.
  18885.  
  18886.       unsigned short somsNtohs (in unsigned short a);
  18887.       // Translates an unsigned short integer from network-byte order
  18888.       // to host-byte order.
  18889.  
  18890.       long somsReadv (in long s, inout iovec iov, in long iovcnt);
  18891.       // Reads data on socket s and stores it in a set of buffers
  18892.       // described by iov.
  18893.  
  18894.       long somsRecv (in long s, in char *buf, in long len,
  18895.                      in long flags);
  18896.       // Receives data on streams socket s and stores it in buf.
  18897.  
  18898.       long somsRecvfrom (in long s, in char *buf, in long len,
  18899.           in long flags, out sockaddr name, out long namelen);
  18900.       // Receives data on datagram socket s and stores it in buf.
  18901.  
  18902.       long somsRecvmsg (in long s, inout msghdr msg, in long flags);
  18903.       // Receives messages on a socket with descriptor s and stores
  18904.       // them in an array of message headers.
  18905.  
  18906.       long somsSelect (in long nfds, inout fd_set readfds,
  18907.                        inout fd_set writefds, inout fd_set exceptfds,
  18908.                        inout timeval timeout);
  18909.       // Monitors activity on a set of different sockets until a
  18910.       // timeout expires, to see if any sockets are ready for reading
  18911.       // or writing, or if an exceptional condition is pending.
  18912.  
  18913.       long somsSend (in long s, in char *msg, in long len,
  18914.                      in long flags);
  18915.       // Sends msg on streams socket s.
  18916.  
  18917.       long somsSendmsg (in long s, inout msghdr msg, in long flags);
  18918.       // Sends messages passed in an array of message headers on a
  18919.       // socket with descriptor s.
  18920.  
  18921.       long somsSendto (in long s, inout char msg, in long len,
  18922.                        in long flags, inout sockaddr to, in long tolen);
  18923.       // Sends msg on datagram socket s.
  18924.  
  18925.       long somsSetsockopt (in long s, in long level, in long optname,
  18926.                            in char *optval, in long optlen);
  18927.       // Sets options associated with a socket.
  18928.  
  18929.       long somsShutdown (in long s, in long how);
  18930.       // Shuts down all or part of a full-duplex connection.
  18931.  
  18932.       long somsSocket (in long domain, in long type,
  18933.                        in long protocol);
  18934.       // Creates an endpoint for communication and returns a socket
  18935.       // descriptor representing the endpoint.
  18936.  
  18937.       long somsSoclose (in long s);
  18938.       // Shuts down socket s and frees resources allocated to the
  18939.       // socket.
  18940.  
  18941.       long somsWritev (in long s, inout iovec iov, in long iovcnt);
  18942.       // Writes data on socket s.  The data is gathered from the
  18943.       // buffers described by iov.
  18944.  
  18945.       attribute long serrno;
  18946.       // Used to pass error numbers.
  18947.  
  18948.   #ifdef __SOMIDL__
  18949.       implementation
  18950.       {
  18951.       releaseorder:
  18952.           somsAccept, somsBind, somsConnect, somsGethostbyaddr,
  18953.           somsGethostbyname, somsGethostent, somsGethostid,
  18954.           somsGethostname, somsGetpeername, somsGetsockname,
  18955.           somsGetsockopt, somsHtonl, somsHtons, somsIoctl,
  18956.           somsInet_addr, somsInet_lnaof, somsInet_makeaddr,
  18957.           somsInet_netof, somsInet_network, somsInet_ntoa,
  18958.           somsListen, somsNtohl, somsNtohs, somsReadv,
  18959.           somsRecv, somsRecvfrom, somsRecvmsg, somsSelect,
  18960.           somsSend, somsSendmsg, somsSendto, somsSetsockopt,
  18961.           somsShutdown, somsSocket, somsSoclose, somsWritev,
  18962.           _set_serrno, _get_serrno, somsGetservbyname;
  18963.  
  18964.       //# Class modifiers
  18965.       callstyle=idl;
  18966.       metaclass = SOMMSingleInstance;
  18967.       majorversion=1; minorversion=1;
  18968.       dll="soms.dll";
  18969.       };
  18970.   #endif /* __SOMIDL__ */
  18971.   };
  18972.   #endif  /* somssock_idl */
  18973.  
  18974.  
  18975. ΓòÉΓòÉΓòÉ 13.2. IDL for a Sockets subclass ΓòÉΓòÉΓòÉ
  18976.  
  18977. Sockets subclasses inherit their entire interface from Sockets. All methods are 
  18978. overridden. 
  18979.  
  18980. For example, here is a listing of the TCPIPSockets IDL description. 
  18981.  
  18982. // 96F8647, 96F8648 (C) Copyright IBM Corp. 1992, 1993
  18983. // All Rights Reserved
  18984. // Licensed Materials - Property of IBM
  18985.  
  18986. #ifndef tcpsock_idl
  18987. #define tcpsock_idl
  18988.  
  18989. #include <somssock.idl>
  18990. #include <snglicls.idl>
  18991.  
  18992. interface TCPIPSockets : Sockets
  18993. {
  18994. #ifdef __SOMIDL__
  18995.     implementation
  18996.     {
  18997.     //# Class modifiers
  18998.     callstyle=idl;
  18999.     majorversion=1; minorversion=1;
  19000.     dllname="somst.dll";
  19001.     metaclass=SOMMSingleInstance;
  19002.     //# Method modifiers
  19003.     somsAccept: override;
  19004.     somsBind: override;
  19005.     somsConnect: override;
  19006.     somsGethostbyaddr: override;
  19007.     somsGethostbyname: override;
  19008.     somsGethostent: override;
  19009.     somsGethostid: override;
  19010.     somsGethostname: override;
  19011.     somsGetpeername: override;
  19012.     somsGetservbyname: override;
  19013.     somsGetsockname: override;
  19014.     somsGetsockopt: override;
  19015.     somsHtonl: override;
  19016.     somsHtons: override;
  19017.     somsIoctl: override;
  19018.     somsInet_addr: override;
  19019.     somsInet_lnaof: override;
  19020.     somsInet_makeaddr: override;
  19021.     somsInet_netof: override;
  19022.     somsInet_network: override;
  19023.     somsInet_ntoa: override;
  19024.     somsListen: override;
  19025.     somsNtohl: override;
  19026.     somsNtohs: override;
  19027.     somsReadv: override;
  19028.     somsRecv: override;
  19029.     somsRecvfrom: override;
  19030.     somsRecvmsg: override;
  19031.     somsSelect: override;
  19032.     somsSend: override;
  19033.     somsSendmsg: override;
  19034.     somsSendto: override;
  19035.     somsSetsockopt: override;
  19036.     somsShutdown: override;
  19037.     somsSocket: override;
  19038.     somsSoclose: override;
  19039.     somsWritev: override;
  19040.     _set_serrno: override;
  19041.    _get_serrno: override;
  19042.    };
  19043. #endif /* __SOMIDL__ */
  19044.  };
  19045. #endif  /* tcpsock_idl */
  19046.  
  19047.  
  19048. ΓòÉΓòÉΓòÉ 13.3. Implementation considerations ΓòÉΓòÉΓòÉ
  19049.  
  19050.      Only the AF_INET address family must be supported. That is, the DSOM, 
  19051.       Replication, and Event Manager frameworks all use Internet addresses and 
  19052.       port numbers to refer to specific sockets. 
  19053.  
  19054.      On OS/2, the SOMobjects run-time libraries were built using the C Set/2 
  19055.       32-bit compiler. If the underlying subclass implementation uses a 16-bit 
  19056.       subroutine library, conversion of the method call arguments may be 
  19057.       required. (This mapping of arguments is often referred to as "thunking.") 
  19058.  
  19059.      Sockets subclasses to be used in multi-threaded environments should be 
  19060.       made thread-safe. That is, it is possible that concurrent threads may 
  19061.       make calls on the (single) Sockets object, so data structures must be 
  19062.       protected within critical regions, as appropriate. 
  19063.  
  19064.      Valid values for the serrno attribute are defined in the file soms.h. The 
  19065.       subclass implementation should map local error numbers into the 
  19066.       appropriate corresponding Sockets error numbers. 
  19067.  
  19068.  
  19069. ΓòÉΓòÉΓòÉ 13.4. Example code ΓòÉΓòÉΓòÉ
  19070.  
  19071. The following code fragment shows an example of the implementation of the 
  19072. somsBind method of the TCPIPSockets subclass, for both AIX and OS/2. The sample 
  19073. illustrates that, for TCP/IP, the implementation is basically a one-to-one 
  19074. mapping of Sockets methods onto TCP/IP calls. For other transport protocols, 
  19075. the mapping from the socket abstraction to the protocol's API may be more 
  19076. difficult. 
  19077.  
  19078. For AIX, the mapping from Sockets method to TCP/IP call is trivial. 
  19079.  
  19080. SOM_Scope long  SOMLINK somsBind(TCPIPSockets somSelf,
  19081.                                  Environment *ev,
  19082.                                  long s, Sockets_sockaddr* name,
  19083.                                  long namelen)
  19084. {
  19085.     long rc;
  19086.  
  19087.     TCPIPSocketsMethodDebug("TCPIPSockets","somsBind");
  19088.  
  19089.     rc = (long) bind((int)s, name, (int)namelen);
  19090.  
  19091.     if (rc == -1)
  19092.        __set_serrno(somSelf, ev, errno);
  19093.  
  19094.     return rc;
  19095. }
  19096.  
  19097. On OS/2, however, the TCP/IP Release 1.2.1 library is a 16-bit library. 
  19098. Consequently, many of the method calls require conversion ("thunking") of 
  19099. 32-bit parameters into 16-bit parameters, before the actual TCP/IP calls can be 
  19100. invoked. For example, the function prototype for the somsBind method is defined 
  19101. as: 
  19102.  
  19103. SOM_Scope long  SOMLINK somsBind(TCPIPSockets somSelf,
  19104.                                  Environment *ev,
  19105.                                  long s, Sockets_sockaddr* name,
  19106.                                  long namelen);
  19107.  
  19108. whereas the file socket.h on OS/2 declares the bind function with the following 
  19109. prototype: 
  19110.  
  19111. short _Far16 _Cdecl bind(short /*s*/, void * _Seg16 /*name*/,
  19112.                          short /*len*/);
  19113.  
  19114. In this case, the pointer to the "name" structure, passed as a 32-bit address, 
  19115. cannot be used directly in the bind call: a 16-bit address must be passed 
  19116. instead. This can be accomplished by dereferencing the 32-bit pointer provided 
  19117. by the "name" parameter in the somsBind call, copying the caller's 
  19118. Sockets_sockaddr structure into a local structure ("name16"), and then passing 
  19119. the address of the local structure ("&name16") as a 16-bit address in the bind 
  19120. call. 
  19121.  
  19122. SOM_Scope long  SOMLINK somsBind(TCPIPSockets somSelf,
  19123.                                  Environment *ev,
  19124.                                  long s, Sockets_sockaddr* name,
  19125.                                  long namelen)
  19126. {
  19127.     long rc;
  19128.     Sockets_sockaddr name16;
  19129.  
  19130.     TCPIPSocketsMethodDebug("TCPIPSockets","somsBind");
  19131.  
  19132.     /* copy user's parameter into a local structure */
  19133.     memcpy ((char *)&name16, (char *)((sockaddr32 *)name), namelen);
  19134.     rc = (long) bind((short)s, (void *)&name16, (short)namelen);
  19135.  
  19136.     if (rc == -1)
  19137.        __set_serrno(somSelf, ev, tcperrno());
  19138.  
  19139.     return rc;
  19140. }
  19141.  
  19142.  
  19143. ΓòÉΓòÉΓòÉ 14. Notices ΓòÉΓòÉΓòÉ
  19144.  
  19145. Second Edition (January 1996) 
  19146.  
  19147. The following paragraph does not apply to the United Kingdom or any country 
  19148. where such provisions are inconsistent with local law:  INTERNATIONAL BUSINESS 
  19149. MACHINES CORPORATION PROVIDES THIS PUBLICATION "AS IS" WITHOUT WARRANTY OF ANY 
  19150. KIND, EITHER EXPRESS OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 
  19151. WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Some states 
  19152. do not allow disclaimer of express or implied warranties in certain 
  19153. transactions, therefore, this statement may not apply to you. 
  19154.  
  19155. This publication could include technical inaccuracies or typographical errors. 
  19156. Changes are periodically made to the information herein; these changes will be 
  19157. incorporated in new editions of the publication. IBM may make improvements 
  19158. and/or changes in the product(s) and/or the program(s) described in this 
  19159. publication at any time. 
  19160.  
  19161. It is possible that this publication may contain reference to, or information 
  19162. about, IBM products (machines and programs), programming, or services that are 
  19163. not announced in your country.  Such references or information must not be 
  19164. construed to mean that IBM intends to announce such IBM products, programming, 
  19165. or services in your country. 
  19166.  
  19167. Requests for technical information about IBM products should be made to your 
  19168. IBM reseller or IBM marketing representative. 
  19169.  
  19170.  
  19171. ΓòÉΓòÉΓòÉ 14.1. Copyright Notices ΓòÉΓòÉΓòÉ
  19172.  
  19173. COPYRIGHT LICENSE: This publication contains printed sample application 
  19174. programs in source language, which illustrate OS/2 programming techniques. You 
  19175. may copy, modify, and distribute these sample programs in any form without 
  19176. payment to IBM, for the purposes of developing, using, marketing or 
  19177. distributing application programs conforming to the OS/2 application 
  19178. programming interface. 
  19179.  
  19180. Each copy of any portion of these sample programs or any derivative work, which 
  19181. is distributed to others, must include a copyright notice as follows: "(C) 
  19182. (your company name) (year).  All rights reserved." 
  19183.  
  19184. (C) Copyright International Business Machines Corporation 1994, 1996. All 
  19185. rights reserved. 
  19186. Note to U.S. Government Users - Documentation related to restricted rights - 
  19187. Use, duplication or disclosure is subject to restrictions set forth in GSA ADP 
  19188. Schedule Contract with IBM Corp. 
  19189.  
  19190.  
  19191. ΓòÉΓòÉΓòÉ 14.2. Disclaimers ΓòÉΓòÉΓòÉ
  19192.  
  19193. References in this publication to IBM products, programs, or services do not 
  19194. imply that IBM intends to make these available in all countries in which IBM 
  19195. operates. Any reference to an IBM product, program, or service is not intended 
  19196. to state or imply that only IBM's product, program, or service may be used. 
  19197. Subject to IBM's valid intellectual property or other legally protectable 
  19198. rights, any functionally equivalent product, program, or service may be used 
  19199. instead of the IBM product, program, or service. Evaluation and verification of 
  19200. operation in conjunction with other products, programs, or services, except 
  19201. those expressly designated by IBM, are the user's responsibility. 
  19202.  
  19203. IBM may have patents or pending patent applications covering subject matter in 
  19204. this document. The furnishing of this document does not give you any license to 
  19205. these patents. You can send license inquiries, in writing, to the IBM Director 
  19206. of Licensing, IBM Corporation, 500 Columbus Avenue, Thornwood, NY 10594, U.S.A. 
  19207.  
  19208.  
  19209. ΓòÉΓòÉΓòÉ 14.3. Trademarks ΓòÉΓòÉΓòÉ
  19210.  
  19211. The following terms are trademarks of the IBM Corporation in the United States 
  19212. or other countries or both: The following terms are trademarks of the 
  19213. International Business Machines Corporation in the United States and/or other 
  19214. countries: 
  19215.  
  19216.             AIX
  19217.  
  19218.             Operating System/2
  19219.  
  19220.             OS/2
  19221.  
  19222.             OS/2 Workplace Shell
  19223.  
  19224.             RISC System 6000
  19225.  
  19226.             SOMobjects
  19227.  
  19228.             System Object Model
  19229.  
  19230.  The following terms are trademarks of other companies: 
  19231.  
  19232.  Each of the following terms used in this publication is a trademark of another 
  19233.  company: 
  19234.  
  19235.  Trademark                       Owner 
  19236.  EXCEL                           Microsoft Corporation 
  19237.  Intel                           Intel Corporation 
  19238.  IPX                             Novell Corporation 
  19239.  Lotus 1-2-3                     Lotus Development Corporation 
  19240.  NetWare                         Novell Corporation 
  19241.  Objective-C                     The Stepstone Corporation 
  19242.  Windows                         Microsoft Corporation 
  19243.  
  19244.  
  19245. ΓòÉΓòÉΓòÉ 15. Glossary ΓòÉΓòÉΓòÉ
  19246.  
  19247. Note:  In the following definitions, words shown in italics are terms for which 
  19248. separate glossary entries are also defined. 
  19249.  
  19250.  abstract class A class that is not designed to be instantiated, but serves as 
  19251.            a base class for the definition of subclasses. Regardless of whether 
  19252.            an abstract class inherits instance data and methods from parent 
  19253.            classes, it will always introduce methods that must be overridden in 
  19254.            a subclass, in order to produce a class whose objects are 
  19255.            semantically valid. 
  19256.  
  19257.  affinity group An array of class objects that were all registered with the 
  19258.            SOMClassMgr object during the dynamic loading of a class. Any class 
  19259.            is a member of at most one affinity group. 
  19260.  
  19261.  ancestor class A class from which another class inherits instance methods, 
  19262.            attributes, and instance variables, either directly or indirectly. A 
  19263.            direct descendant of an ancestor class is called a child class, 
  19264.            derived class, or  subclass. A direct ancestor of a class is called 
  19265.            a parent class, base class, or superclass. 
  19266.  
  19267.  aggregate type A user-defined data type that combines basic types (such as, 
  19268.            char, short, float, and so on) into a more complex type (such as 
  19269.            structs, arrays, strings, sequences, unions, or enums). 
  19270.  
  19271.  apply stub A procedure corresponding to a particular method that accepts as 
  19272.            arguments: the object on which the method is to be invoked, a 
  19273.            pointer to a location in memory where the method's result should be 
  19274.            stored, a pointer to the method's procedure, and the method's 
  19275.            arguments in the form of a va_list. The apply stub extracts the 
  19276.            arguments from the va_list, invokes the method with its arguments, 
  19277.            and stores its result in the specified location. Apply stubs are 
  19278.            registered with class objects when instance methods are defined, and 
  19279.            are invoked using the somApply function. Typically, implementations 
  19280.            that override somDispatch call somApply to invoke a method on a 
  19281.            va_list of arguments. 
  19282.  
  19283.  attribute A specialized syntax for declaring "set" and "get" methods. Method 
  19284.            names corresponding to attributes always begin with "_set_" or 
  19285.            "_get_". An attribute name is declared in the body of the interface 
  19286.            statement for a class. Method procedures for get/set methods are 
  19287.            automatically defined by the SOM Compiler unless an attribute is 
  19288.            declared as "noget/noset". Likewise, a corresponding instance 
  19289.            variable is automatically defined unless an attribute is declared as 
  19290.            "nodata". IDL also supports "readonly" attributes, which specify 
  19291.            only a "get" method. (Contrast an attribute with an instance 
  19292.            variable.) 
  19293.  
  19294.  auxiliary class data structure: A structure provided by the SOM API to support 
  19295.            efficient static access to class-specific information used in 
  19296.            dealing with SOM objects. The structure's name is 
  19297.            <className>CClassData. Its first component (parentMtab) is a list of 
  19298.            parent-class method tables (used to support efficient parent method 
  19299.            calls). Its second component (instanceDataToken) is the instance 
  19300.            token for the class (generally used to locate the instance data 
  19301.            introduced by method procedures that implement methods defined by 
  19302.            the class). 
  19303.  
  19304.  base class See parent class. 
  19305.  
  19306.  behavior (of an object) The methods that an object responds to. These methods 
  19307.            are those either introduced or inherited by the class of the object. 
  19308.            See also state. 
  19309.  
  19310.  bindings: Language-specific macros and procedures that make implementing and 
  19311.            using SOM classes more convenient. These bindings offer a convenient 
  19312.            interface to SOM that is tailored to a particular programming 
  19313.            language. The SOM Compiler generates binding files for C and C ++. 
  19314.            These binding files include an implementation template for the class 
  19315.            and two header files, one to be included in the class's 
  19316.            implementation file and the other in client programs. 
  19317.  
  19318.  BOA (basic object adapter) class: A CORBA interface (represented as an 
  19319.            abstract class in DSOM), which defines generic object-adapter (OA) 
  19320.            methods that a server can use to register itself and its objects 
  19321.            with an ORB (object request broker). See also SOMOA (SOM object 
  19322.            adapter) class. 
  19323.  
  19324.  callback  A user-provided procedure or method to the Event Management 
  19325.            Framework that gets invoked when a registered event occurs. (See 
  19326.            also event ). 
  19327.  
  19328.  casted dispatching A form of method dispatching that uses casted method 
  19329.            resolution; that is, it uses a designated ancestor class of the 
  19330.            actual target object's class to determine what procedure to call to 
  19331.            execute a specified method. 
  19332.  
  19333.  casted method resolution A method resolution technique that uses a method 
  19334.            procedure from the method table of an ancestor of the class of an 
  19335.            object (rather than using a procedure from the method table of the 
  19336.            object's own class). 
  19337.  
  19338.  child class A class that inherits instance methods, attributes, and instance 
  19339.            variables directly from another class, called the parent class, base 
  19340.            class, or superclass, or indirectly from an ancestor class. A child 
  19341.            class may also be called a derived class or subclass. 
  19342.  
  19343.  class     A way of categorizing objects based on their behavior (the methods 
  19344.            they support) and shape (memory layout). A class is a definition of 
  19345.            a generic object. In SOM, a class is also a special kind of object 
  19346.            that can manufacture other objects that all have a common shape and 
  19347.            exhibit similar behavior. The specification of what comprises the 
  19348.            shape and behavior of a set of objects is referred to as the 
  19349.            "definition" of a class. New classes are defined in terms of 
  19350.            existing classes through a technique known as inheritance. See also 
  19351.            class object. 
  19352.  
  19353.  class variable Instance data of a class object. All instance data of an object 
  19354.            is defined (through either introduction or inheritance) by the 
  19355.            object's class. Thus, class variables are defined by metaclasses. 
  19356.  
  19357.  class data structure A structure provided by the SOM API to support efficient 
  19358.            static access to class-specific information used in dealing with SOM 
  19359.            objects. The structure's name is <className>ClassData. Its first 
  19360.            component (classObject) is a pointer to the corresponding class 
  19361.            object. The remaining components (named after the instance methods 
  19362.            and instance variables) are method tokens or data tokens, in order 
  19363.            as specified by the class's implementation. Data tokens are only 
  19364.            used to support data (public and private) introduced by classes 
  19365.            declared using OIDL; IDL attributes are supported with method 
  19366.            tokens. 
  19367.  
  19368.  class manager An object that acts as a run-time registry for all SOM class 
  19369.            objects that exist within the current process and which assists in 
  19370.            the dynamic loading and unloading of class libraries. A class 
  19371.            implementor can define a customized class manager by subclassing 
  19372.            SOMClassMgr class to replace the SOM-supplied SOMClassMgrObject. 
  19373.            This is done to augment the functionality of the default 
  19374.            class-management registry (for example, to coordinate the automatic 
  19375.            quiescing and unloading of classes). 
  19376.  
  19377.  class method (Also known as factory method or constructor.) A class method is 
  19378.            a method that a class object responds to (as opposed to an instance 
  19379.            method). A class method that class <X> responds to is provided by 
  19380.            the metaclass of class <X>. Class methods are executed without 
  19381.            requiring any instances of class <X> to exist, and are frequently 
  19382.            used to create instances of the class. 
  19383.  
  19384.  class object The run-time object representing a SOM class. In SOM, a class 
  19385.            object can perform the same behavior common to all objects, 
  19386.            inherited from SOMObject. 
  19387.  
  19388.  client code (Or client program or client.) An application program, written in 
  19389.            the programmer's preferred language, which invokes methods on o 
  19390.            bjects that are instances of SOM classes. In DSOM, this could be a 
  19391.            program that invokes a method on a remote object. 
  19392.  
  19393.  constructor See class method. 
  19394.  
  19395.  context expression An optional expression in a method's IDL declaration, 
  19396.            specifying identifiers whose value (if any) can be used during SOM's 
  19397.            method resolution  process and/or by the target object as it 
  19398.            executes the method procedure. If a context expression is specified, 
  19399.            then a related Context parameter is required when the method is 
  19400.            invoked. (This Context parameter is an implicit parameter in the IDL 
  19401.            specification of the method, but it is an explicit parameter of the 
  19402.            method's procedure.) No SOM-supplied methods require context 
  19403.            parameters. 
  19404.  
  19405.  CORBA     The Common Object Request Broker Architecture established by the 
  19406.            Object Management Group. IBM's Interface Definition Language used to 
  19407.            describe the interface for SOM classes is fully compliant with CORBA 
  19408.            standards. 
  19409.  
  19410.  daemon    See DSOM daemon. 
  19411.  
  19412.  data token A value that identifies a specific instance variable within an 
  19413.            object whose class inherits the instance variable (as a result of 
  19414.            being derived, directly or indirectly, from the class that 
  19415.            introduces the instance variable). An object and a data token are 
  19416.            passed to the SOM run-time procedure, somDataResolve, which returns 
  19417.            is a pointer to the specific instance variable corresponding to the 
  19418.            data token. (See also instance token.) 
  19419.  
  19420.  derived class See subclass and subclassing. 
  19421.  
  19422.  derived metaclass (Or SOM-derived metaclass.) A metaclass  that SOM creates 
  19423.            automatically (often even when the class implementor specifies an 
  19424.            explicit metaclass) as needed to ensure that, for any code that 
  19425.            executes without method-resolution error on an instance of a given 
  19426.            class, the code will similarly execute without method-resolution 
  19427.            error on instances of any subclass of the given class. SOM's ability 
  19428.            to derive such metaclasses is a fundamental necessity in order to 
  19429.            ensure binary compatibility for client programs despite any 
  19430.            subsequent changes in class implementations. 
  19431.  
  19432.  descriptor (Or method descriptor.) An ID representing the identifier of a 
  19433.            method definition or an attribute definition in the Interface 
  19434.            Repository. The IR definition contains information about the 
  19435.            method's return type and the type of its arguments. 
  19436.  
  19437.  directive A message (a pre-defined character constant) received by a replica 
  19438.            from the Replication Framework. Indicates a potential failure 
  19439.            situation. 
  19440.  
  19441.  dirty object A persistent object that has been modified since it was last 
  19442.            written to persistent storage. 
  19443.  
  19444.  dispatch-function resolution Dispatch-function resolution is the slowest, but 
  19445.            most flexible, of the three method-resolution techniques SOM offers. 
  19446.            Dispatch functions permit method resolution to be based on arbitrary 
  19447.            rules associated with an object's class. Thus, a class implementor 
  19448.            has complete freedom in determining how methods invoked on its 
  19449.            instances are resolved. See also dispatch method and dynamic 
  19450.            dispatching. 
  19451.  
  19452.  dispatch method A method (such as somDispatch or somClassDispatch) that is 
  19453.            invoked (and passed an argument list and the ID of another method) 
  19454.            in order to determine the appropriate method procedure to execute. 
  19455.            The use of dispatch methods facilitates dispatch-function resolution 
  19456.            in SOM applications and enables method invocation on remote objects 
  19457.            in DSOM applications. See also dynamic dispatching. 
  19458.  
  19459.  DLL       Abbreviation for dynamic link library. 
  19460.  
  19461.  DSOM daemon (somdd) The DSOM process (somdd) that locates and activates 
  19462.            servers. The daemon (actually known as the location services daemon) 
  19463.            is primarily meant to provide a client with the necessary 
  19464.            communications information to allow the client to connect with an 
  19465.            implementation server. 
  19466.  
  19467.  dynamic dispatching Method dispatching using dispatch-function resolution; the 
  19468.            use of dynamic method resolution at run time. See also dispatch- 
  19469.            function resolution and dynamic method. 
  19470.  
  19471.  Dynamic Invocation Interface (DII) The CORBA-specified interface, implemented 
  19472.            in DSOM, that is used to dynamically build requests on remote 
  19473.            objects. Note that DSOM applications can also use the somDispatch 
  19474.            method for dynamic method calls when the object is remote. See also 
  19475.            dispatch method. 
  19476.  
  19477.  dynamic link library A piece of code that can be loaded (activated) 
  19478.            dynamically. This code is physically separate from its callers. DLLs 
  19479.            can be loaded at load time or at run time. Widely used term on OS/2, 
  19480.            Windows, and, to some extent, AIX. 
  19481.  
  19482.  dynamic method A method that is not declared in the IDL interface statement 
  19483.            for a class of objects, but is added to the interface at run time, 
  19484.            after which instances of the class (or of its subclasses) will 
  19485.            respond to the registered dynamic method. Because dynamic methods 
  19486.            are not declared, usage bindings for SOM classes cannot support 
  19487.            their use; thus, offset method resolution is not available. Instead, 
  19488.            name-lookup or dispatch-function method resolution must be used to 
  19489.            invoke dynamic methods. (There are currently no known uses of 
  19490.            dynamic methods by any SOM applications.) See also method and static 
  19491.            method. 
  19492.  
  19493.  encapsulation An object-oriented programming feature whereby the 
  19494.            implementation details of a class are hidden from client programs, 
  19495.            which are only required to know the interface of a class (the 
  19496.            signatures of its methods and the names of its attributes) in order 
  19497.            to use the class's methods and attributes. 
  19498.  
  19499.  encoder/decoder In the Persistence Framework, a class that knows how to 
  19500.            read/write the persistent object format of a persistent object. 
  19501.            Every persistent object is associated with an Encoder/Decoder, and 
  19502.            an encoder/decoder object is created for each attribute and instance 
  19503.            variable. An Encoder/Decoder is supplied by the Persistence 
  19504.            Framework by default, or an application can define its own. 
  19505.  
  19506.  entry class In the Emitter Framework, a class that represents some syntactic 
  19507.            unit of an interface definition in the IDL source file. 
  19508.  
  19509.  Environment parameter A CORBA-required parameter in all method procedures, it 
  19510.            represents a memory location where exception information can be 
  19511.            returned by the object of a method invocation. [Certain methods are 
  19512.            exempt (when the class contains a modifier of callstyle=oidl), to 
  19513.            maintain upward compatibility for client programs written using an 
  19514.            earlier release.] 
  19515.  
  19516.  emitter   Generically, a program that takes the output from one system and 
  19517.            converts the information into a different form. Using the Emitter 
  19518.            Framework, selected output from the SOM Compiler (describing each 
  19519.            syntactic unit in an IDL source file) is transformed and formatted 
  19520.            according to a user-defined template. Example emitter output, 
  19521.            besides the implementation template and language bindings, might 
  19522.            include reference documentation, class browser descriptions, or 
  19523.            "pretty" printouts. 
  19524.  
  19525.  event     The occurrence of a condition, or the beginning or ending of an 
  19526.            activity that is of interest to an application. Examples are elapse 
  19527.            of a time interval, sending or receiving of a message, and opening 
  19528.            or closing a file. (See also event manager and callback.) 
  19529.  
  19530.  event manager (EMan) The chief component of the Event Management Framework 
  19531.            that registers interest in various events from calling modules and 
  19532.            informs them through callbacks when those events occur. 
  19533.  
  19534.  factory method See class method. 
  19535.  
  19536.  ID:       See somId. 
  19537.  
  19538.  IDL source file A user-written .idl file, expressed using the syntax of the 
  19539.            Interface Definition Language (IDL), which describes the interface 
  19540.            for a particular class (or classes, for a module). The IDL source 
  19541.            file is processed by the SOM Compiler to generate the binding files 
  19542.            specific to the programming languages of the class implementor and 
  19543.            the client application. (This file may also be called the "IDL 
  19544.            file," the "source file," or the "interface definition file.") 
  19545.  
  19546.  implementation (Or object implementation.) The specification of what instance 
  19547.            variables implement an object's state and what procedures implement 
  19548.            its methods (or behaviors). In DSOM, a remote object's 
  19549.            implementation is also characterized by its server implementation (a 
  19550.            program). 
  19551.  
  19552.  Implementation Repository A database used by DSOM to store the implementation 
  19553.            definitions of DSOM servers. 
  19554.  
  19555.  implementation statement An optional declaration within the body of the 
  19556.            interface  definition of a class in a SOM IDL source file, 
  19557.            specifying information about how the class will be implemented (such 
  19558.            as, version numbers for the class, overriding of inherited methods, 
  19559.            or type of method resolution to be supported by particular methods). 
  19560.            This statement is a SOM-unique statement; thus, it must be preceded 
  19561.            by the term "#ifdef __SOMIDL__" and followed by "#endif". See also 
  19562.            interface declaration. 
  19563.  
  19564.  implementation template A template file containing stub procedures for 
  19565.            methods that a class introduces or overrides. The implementation 
  19566.            template is one of the binding files generated by the SOM Compiler 
  19567.            when it processes the IDL source file containing class interface 
  19568.            declarations. The class implementor then customizes the 
  19569.            implementation, by adding language-specific code to the method 
  19570.            procedures. 
  19571.  
  19572.  implicit method parameter A method parameter that is not included in the IDL 
  19573.            interface specification of a method, but which is a parameter of the 
  19574.            method's procedure and which is required when the method is invoked 
  19575.            from a client program. Implicit parameters include the required 
  19576.            Environment parameter indicating where exception information can be 
  19577.            returned, as well as a Context parameter, if needed. 
  19578.  
  19579.  incremental update A revision to an implementation template file that results 
  19580.            from reprocessing of the IDL source file by the SOM Compiler. The 
  19581.            updated implementation file will contain new stub procedures, added 
  19582.            comments, and revised method prototypes reflecting changes made to 
  19583.            the method definitions in the IDL specification. Importantly, these 
  19584.            updates do not disturb existing code that the class implementor has 
  19585.            defined for the prior method procedures. 
  19586.  
  19587.  inheritance The technique of defining one class (called a subclass, derived 
  19588.            class, or child class) as incremental differences from another class 
  19589.            (called the  parent class, base class, superclass, or ancestor 
  19590.            class). From its parents, the subclass inherits variables and 
  19591.            methods for its instances. The subclass can also provide additional 
  19592.            instance variables and methods. Furthermore, the subclass can 
  19593.            provide new procedures for implementing inherited methods. The 
  19594.            subclass is then said to override the parent class's methods. An 
  19595.            overriding method procedure can elect to call the parent class's 
  19596.            method procedure. (Such a call is known as a parent method call.) 
  19597.  
  19598.  inheritance hierarchy The sequential relationship from a root class to a 
  19599.            subclass, through which the subclass inherits instance methods, 
  19600.            attributes, and  instance variables from all of its ancestors, 
  19601.            either directly or indirectly. The root class of all SOM classes is 
  19602.            SOMObject. 
  19603.  
  19604.  instance  (Or object instance or just object.) A specific object, as 
  19605.            distinguished from a class of objects. See also object. 
  19606.  
  19607.  instance method A method valid for an object instance (as opposed to a class 
  19608.            method, which is valid for a class object). An instance method that 
  19609.            an object responds to is defined by its class or inherited from an 
  19610.            ancestor class. 
  19611.  
  19612.  instance token A data token that identifies the first instance variable among 
  19613.            those introduced by a given class. The somGetInstanceToken method 
  19614.            invoked on a class object returns that class's instance token. 
  19615.  
  19616.  instance variables (Or, instance data.) Variables declared for use within the 
  19617.            method procedures of a class. An instance variable is declared 
  19618.            within the body of the implementation statement in a SOM IDL source 
  19619.            file. An instance variable is "private" to the class and should not 
  19620.            be accessed by a client program. (Contrast an instance variable with 
  19621.            an attribute.) 
  19622.  
  19623.  interface The information that a client must know to use a class  namely, the 
  19624.            names of its attributes and the signatures of its methods . The 
  19625.            interface is described in a formal language (the Interface 
  19626.            Definition Language, IDL) that is independent of the programming 
  19627.            language used to implement the class's methods. 
  19628.  
  19629.  interface declaration (Or interface statement.) The statement in the IDL 
  19630.            source file that specifies the name of a new class and the names of 
  19631.            its parent class(es). The "body" of the interface declaration 
  19632.            defines the signature of each new method and any attribute(s) 
  19633.            associated with the class. In SOM IDL, the body may also include an 
  19634.            implementation statement (where instance variables are declared or a 
  19635.            modifier is specified, for example to overridea method). 
  19636.  
  19637.  Interface Definition Language (IDL) The formal language (independent of any 
  19638.            programming language) by which the interface for a class of objects 
  19639.            is defined in a .idl file, which the SOM Compiler then interprets to 
  19640.            create an implementation template file and binding files. SOM's 
  19641.            Interface Definition Language is fully compliant with standards 
  19642.            established by the Object Management Group's Common Object Request 
  19643.            Broker Architecture (CORBA). 
  19644.  
  19645.  Interface Repository (IR) The database that SOM optionally creates to provide 
  19646.            persistent storage of objects representing the major elements of 
  19647.            interface definitions. Creation and maintenance of the IR is based 
  19648.            on information supplied in the IDL source file.  The SOM IR 
  19649.            Framework supports all interfaces described in the CORBA standard. 
  19650.  
  19651.  Interface Repository Framework A set of classes that provide methods whereby 
  19652.            executing programs can access the persistent objects of the 
  19653.            Interface Repository to discover everything known about the 
  19654.            programming interfaces of SOM classes. 
  19655.  
  19656.  IR        Abbreviation for Interface Repository. 
  19657.  
  19658.  location services daemon (somdd) A process whose primary purpose is to give 
  19659.            DSOM clients the communications information that they need to 
  19660.            connect with an implementation server. 
  19661.  
  19662.  macro     An alias for executing a sequence of hidden instructions; in SOM, 
  19663.            typically the means of executing a command known within a binding 
  19664.            file created by the SOM Compiler. 
  19665.  
  19666.  metaclass A class whose instances are classes. In SOM, any class descended 
  19667.            from SOMClass is a metaclass. The methods a class inherits from its 
  19668.            metaclass are sometimes called class methods (in Smalltalk) or 
  19669.            factory methods (in Objective-C) or constructors. See also class 
  19670.            method. 
  19671.  
  19672.  metaclass incompatibility A situation where a subclass does not include all of 
  19673.            the class variables or respond to all of the class methods of its 
  19674.            ancestor classes. This situation can easily arise in OOP systems 
  19675.            that allow programmers to explicitly specify metaclasses, but is not 
  19676.            allowed to occur in SOM. Instead, SOM automatically prevents this by 
  19677.            creating and using derived metaclasses whenever necessary. 
  19678.  
  19679.  method    A combination of a procedure and a name, such that many different 
  19680.            procedures can be associated with the same name. In object-oriented 
  19681.            programming, invoking a method on an object causes the object to 
  19682.            execute a specific method procedure. The process of determining 
  19683.            which method procedure to execute when a method is invoked on an 
  19684.            object is called method resolution. (The CORBA standard uses the 
  19685.            term "operation" for method invocation). SOM supports two different 
  19686.            kinds of methods: static methods and dynamic methods. See also 
  19687.            static method and dynamic method. 
  19688.  
  19689.  method descriptor See descriptor. 
  19690.  
  19691.  method ID A number representing a zero-terminated string by which SOM uniquely 
  19692.            represents a method name. See also somId. 
  19693.  
  19694.  method pointer A pointer type that identifies one method procedure on a single 
  19695.            class. Method pointers are not ensured to be persistent among 
  19696.            multiple processes. 
  19697.  
  19698.  method procedure A function or procedure, written in an arbitrary programming 
  19699.            language, that implements a method of a class. A method procedure is 
  19700.            defined by the class implementor within the implementation template 
  19701.            file generated by the SOM Compiler. 
  19702.  
  19703.  method prototype A method declaration that includes the types of the 
  19704.            arguments. Based on method definitions in an IDL source file, the 
  19705.            SOM Compiler generates method prototypes in the implementation 
  19706.            template. A class implementor uses the method prototype as a basis 
  19707.            for writing the corresponding method procedurecode. The method 
  19708.            prototype also shows all arguments and their types that are required 
  19709.            to invoke the method from a client program. 
  19710.  
  19711.  method resolution The process of selecting a particular method procedure, 
  19712.            given a method name and an object instance. The process results in 
  19713.            selecting the particular function/procedure that implements the 
  19714.            abstract method in a way appropriate for the designated object. SOM 
  19715.            supports a variety of method-resolution mechanisms, including offset 
  19716.            method resolution, name-lookup resolution, and dispatch-function 
  19717.            resolution. 
  19718.  
  19719.  method table A table of pointers to the  method procedures that implement the 
  19720.            methods that an object supports. See also method token. 
  19721.  
  19722.  method token A value that identifies a specific method introduced by a class. 
  19723.            A method token is used during method resolution to locate the method 
  19724.            procedure that implements the identified method. The two basic 
  19725.            method-resolution procedures are somResolve (which takes as 
  19726.            arguments an object and a method token, and returns a pointer to a 
  19727.            procedure that implements the identified method on the given object) 
  19728.            and somClassResolve (which takes as arguments a class and a method 
  19729.            token, and returns a pointer to a procedure that implements the 
  19730.            identified method on an instance of the given class). 
  19731.  
  19732.  modifier  Any of a set of statements that control how a class, an attribute, 
  19733.            or a method will be implemented. Modifiers can be defined in the 
  19734.            implementation statement of a SOM IDL source file. The 
  19735.            implementation statement is a SOM-unique extension of the CORBA 
  19736.            specification. [User-defined modifiers can also be specified for use 
  19737.            by user-written emitters or to store information in the Interface 
  19738.            Repository, which can then be accessed via methods provided by the 
  19739.            Interface Repository Framework.] 
  19740.  
  19741.  module    The organizational structure required within an IDL source file that 
  19742.            contains interface declarations for two (or more) classes that are 
  19743.            not a class-metaclass pair. Such interfaces must be grouped within a 
  19744.            module declaration. 
  19745.  
  19746.  multiple inheritance The situation in which a class is derived from (and 
  19747.            inherits interface and implementation from) multiple parent classes. 
  19748.  
  19749.  name-lookup method resolution Similar to the method resolution techniques 
  19750.            employed by Objective-C and Smalltalk. It is significantly slower 
  19751.            than offset resolution. Name-lookup resolution, unlike offset 
  19752.            resolution, can be used when the name of the method to be invoked is 
  19753.            not known until run time, or the method is added to the class 
  19754.            interface at run time, or the name of the class introducing the 
  19755.            method is not known until run time. 
  19756.  
  19757.  naming scope: See scope. 
  19758.  
  19759.  object    (Or object instance  or just instance.) An entity that has state 
  19760.            (its data values) and behavior (its methods). An object is one of 
  19761.            the elements of data and function that programs create, manipulate, 
  19762.            pass as arguments, and so forth. An object is a way to encapsulate 
  19763.            state and behavior. Encapsulation permits many aspects of the 
  19764.            implementation of an object to change without affecting client 
  19765.            programs that depend on the object's behavior. In SOM, objects are 
  19766.            created by other objects called classes. 
  19767.  
  19768.  object adapter (OA) A CORBA term denoting the primary interface a server 
  19769.            implementation uses to access ORB functions; in particular, it 
  19770.            defines the mechanisms that a server uses to interact with DSOM, and 
  19771.            vice versa. This includes server activation/deactivation, 
  19772.            dispatching of methods, and authentication of the principal making a 
  19773.            call. The basic object adapter described by CORBA is defined by the 
  19774.            BOA (basic object adapter) abstract class; DSOM's primary object 
  19775.            adapter implementation is provided by the SOMOA (SOM Object Adapter) 
  19776.            class. 
  19777.  
  19778.  object definition See class. 
  19779.  
  19780.  object implementation See implementation. 
  19781.  
  19782.  object instance See instance and object. 
  19783.  
  19784.  object reference A CORBA term denoting the information needed to reliably 
  19785.            identify a particular object. This concept is implemented in DSOM 
  19786.            with a proxy object in a client process, or a SOMDObject in a server 
  19787.            process. See also proxy object and SOMDObject. 
  19788.  
  19789.  object request broker (ORB) See ORB. 
  19790.  
  19791.  offset method resolution: The default mechanism for performing method 
  19792.            resolution in SOM, because it is the fastest (nearly as fast as an 
  19793.            ordinary procedure call). It is roughly equivalent to the C ++ 
  19794.            "virtual function" concept.  Using offset method resolution requires 
  19795.            that the name of the method to be invoked must be known at compile 
  19796.            time, the name of the class that introduces the method must be known 
  19797.            at compile time (although not necessarily by the programmer), and 
  19798.            the method to be invoked must be a static method. 
  19799.  
  19800.  OIDL      The original language used for declaring SOM classes. The acronym 
  19801.            stands for Object Interface Definition Language. OIDL is still 
  19802.            supported by SOM release 2, but it does not include the ability to 
  19803.            specify multiple inheritance classes. 
  19804.  
  19805.  one-copy serializable The consistency property of the Replication Framework 
  19806.            which states that the concurrent execution of methods on a 
  19807.            replicated object is equivalent to the serial execution of those 
  19808.            same methods on a nonreplicated object. 
  19809.  
  19810.  OOP       An acronym for "object-oriented programming." 
  19811.  
  19812.  operation See method. 
  19813.  
  19814.  operation logging In the Replication Framework, a technique for maintaining 
  19815.            consistency among replicas of a replicated object, whereby the 
  19816.            execution of a method that updates the object is repeated at the 
  19817.            site of each replica. 
  19818.  
  19819.  ORB (object request broker) A CORBA term designating the means by which 
  19820.            objects transparently make requests (that is, invoke methods) and 
  19821.            receive responses from objects, whether they are local or remote. 
  19822.            With SOMobjects Developer Toolkit and Runtimes, this functionality 
  19823.            is implemented in the DSOM Framework. Thus, the DSOM (Distributed 
  19824.            SOM) system is an ORB. See also BOA (basic object adapter) class and 
  19825.            SOMOA (SOM object adapter) class. 
  19826.  
  19827.  overridden method A method defined by a parent class and reimplemented 
  19828.            (redefined or overridden) in the current class. 
  19829.  
  19830.  override  (Or overriding method.) The technique by which a class replaces 
  19831.            (redefines) the implementation of a method that it inherits from one 
  19832.            of its parent classes. An overriding method can elect to call the 
  19833.            parent class's method procedure as part of its own implementation. 
  19834.            (Such a call is known as a parent method call.) 
  19835.  
  19836.  parent class A class from which another class inherits instance methods, 
  19837.            attributes, and instance variables. A parent class is sometimes 
  19838.            called a base class or superclass. 
  19839.  
  19840.  parent method call A technique where an overriding method calls the method 
  19841.            procedure of its parent class as part of its own implementation. 
  19842.  
  19843.  persistent object An object whose state can be preserved beyond the 
  19844.            termination of the process that created it. Typically, such objects 
  19845.            are stored in files. 
  19846.  
  19847.  polymorphism An object-oriented programming feature that may take on different 
  19848.            meanings in different systems. Under various definitions of 
  19849.            polymorphism, (a) a method or procedure call can be executed using 
  19850.            arguments of a variety of types, or (b) the same variable can assume 
  19851.            values of different types at different times, or (c) a method name 
  19852.            can denote more than one method procedure.  The SOM system reflects 
  19853.            the third definition (for example, when a SOM class overrides a 
  19854.            parent class definition of a method to change its behavior). The 
  19855.            term literally means "having many forms." 
  19856.  
  19857.  principal The user on whose behalf a particular (remote) method call is being 
  19858.            performed. 
  19859.  
  19860.  procedure A small section of code that executes a limited, well-understood 
  19861.            task when called from another program. In SOM, a method procedure is 
  19862.            often referred to as a procedure. See also method procedure. 
  19863.  
  19864.  process   A series of instructions (a program or part of a program) that a 
  19865.            computer executes in a multitasking environment. 
  19866.  
  19867.  proxy object In DSOM, a SOM object in the client's address space that 
  19868.            represents a remote object. The proxy object has the same interface 
  19869.            as the remote object, but each method invoked on the proxy is 
  19870.            overridden by a dispatch method that forwards the invocation request 
  19871.            to the remote object. Under DSOM, a proxy object is created 
  19872.            dynamically and automatically in the client whenever a remote method 
  19873.            returns a pointer to an object that happens to be remote. 
  19874.  
  19875.  readers and writers In the Replication Framework, different processes can 
  19876.            access the same replicated object in different modes. A "reader" is 
  19877.            a process that does not intend to update the object, but wants to 
  19878.            continually watch the object as other processes update it. A 
  19879.            "writer" is a process that wants to update the object, as well as 
  19880.            continually watch the updates performed by others. 
  19881.  
  19882.  receiver  See target object. 
  19883.  
  19884.  redispatch stub A procedure, corresponding to a particular method, which has 
  19885.            the same signature as the method's procedure but which invokes 
  19886.            somDispatch to dispatch the method. The somOverrideMtab method can 
  19887.            be used to replace the procedure pointers in a class's method table 
  19888.            with the corresponding redispatch stubs. This is done when 
  19889.            overriding somDispatch to customize method resolution so that all 
  19890.            static method invocations will be routed through somDispatch for 
  19891.            selection of an appropriate method procedure. (Dynamic methods have 
  19892.            no entries in the method table, so they cannot be supported with 
  19893.            redispatch functionality.) 
  19894.  
  19895.  reference data Application-specific data that a server uses to identify or 
  19896.            describe an object in DSOM. The data, represented by a sequence of 
  19897.            up to 1024 bytes, is registered with DSOM when a server creates an 
  19898.            object reference. A server can later ask DSOM to return the 
  19899.            reference data associated with an object reference. See also object 
  19900.            reference. 
  19901.  
  19902.  replica   When an object is replicated among a set of processes (using the 
  19903.            Replication Framework), each process is said to have a replica of 
  19904.            the object. From the view point of any application model, the 
  19905.            replicas together represent a single object. 
  19906.  
  19907.  replicated object An object for which replicas (copies) exist.  See replica. 
  19908.  
  19909.  run-time environment The data structures, objects, and global variables that 
  19910.            are created, maintained, and used by the functions, procedures, and 
  19911.            methods in the SOM run-time library. 
  19912.  
  19913.  scope     (Or naming scope.) That portion of a program within which an 
  19914.            identifier name has "visibility" and denotes a unique variable. In 
  19915.            SOM, an IDL source file forms a scope. An identifier can only be 
  19916.            defined once within a scope; identifiers can be redefined within a 
  19917.            nested scope. In a .idl file, modules, interface statements, 
  19918.            structures, unions, methods, and exceptions form nested scopes. 
  19919.  
  19920.  serializable See one-copy serializable. 
  19921.  
  19922.  server    (Or server implementation.) In DSOM, a process, running in a 
  19923.            distributed environment, that executes the implementation of an 
  19924.            object. DSOM provides a default server implementation that can 
  19925.            dynamically load SOM class libraries, create SOM objects, and make 
  19926.            those objects accessible to clients. Developers can also write 
  19927.            application-specific servers for use with DSOM. 
  19928.  
  19929.  server object In DSOM, every server has an object that defines methods for 
  19930.            managing objects in that server. These methods include object 
  19931.            creation, object destruction, and maintaining mappings between 
  19932.            object references and the objects they reference. A server object 
  19933.            must be an instance of the class SOMDServer (or one of its 
  19934.            subclasses). See also object reference and SOMDObject. 
  19935.  
  19936.  shadowing In the Emitter Framework, a technique that is required when any of 
  19937.            the entry classes are subclassed. Shadowing causes instances of the 
  19938.            new subclass(es) (rather than instances of the original entry 
  19939.            classes) to be used as input for building the object graph, without 
  19940.            requiring a recompile of emitter framework code. Shadowing is 
  19941.            accomplished by using the macro SOM_SubstituteClass. 
  19942.  
  19943.  signature The collection of types associated with a method (the type of its 
  19944.            return value, if any, as well as the number, order, and type of each 
  19945.            of its arguments). 
  19946.  
  19947.  sister class object A duplicate of a class object that is created in order to 
  19948.            save a copy of the class's original method table before replacing 
  19949.            the method table to customize method resolution. The sister class 
  19950.            object is created so that some original method procedures can be 
  19951.            called by the replacement method procedures. 
  19952.  
  19953.  Sockets class A class that provides a common communications interface to 
  19954.            Distributed SOM, the Replication Framework, and the Event Management 
  19955.            Framework. The Sockets class provides the base interfaces (patterned 
  19956.            after TCP/IP sockets); the subclasses TCPIPSockets, NBSockets, and 
  19957.            IPXSockets provide actual implementations for TCP/IP, Netbios, and 
  19958.            Netware IPX/SPX, respectively. 
  19959.  
  19960.  SOM Compiler A tool provided by the SOM Toolkit that takes as input the 
  19961.            interface definition file for a class (the .idl file) and produces a 
  19962.            set of binding files that make it more convenient to implement and 
  19963.            use SOM classes. 
  19964.  
  19965.  SOMClass  One of the three primitive class objects of the SOM run-time 
  19966.            environment. SOMClass is the root (meta)class from which all 
  19967.            subsequent metaclasses are derived. SOMClass defines the essential 
  19968.            behavior common to all SOM class objects. 
  19969.  
  19970.  SOMClassMgr One of the three primitive class objects of the SOM run-time 
  19971.            environment. During SOM initialization, a single instance (object) 
  19972.            of SOMClassMgr is created, called SOMClassMgrObject. This object 
  19973.            maintains a directory of all SOM classes that exist within the 
  19974.            current process, and it assists with dynamic loading and unloading 
  19975.            of class libraries. 
  19976.  
  19977.  SOM-derived metaclass: See derived metaclass. 
  19978.  
  19979.  SOMDObject The class that implements the notion of a CORBA "object reference" 
  19980.            in DSOM. An instance of SOMDObject contains information about an 
  19981.            object's server implementation and interface, as well as a 
  19982.            user-supplied identifier. 
  19983.  
  19984.  somId     A pointer to a number that uniquely represents a zero-terminated 
  19985.            string. Such pointers are declared as type somId. In SOM, somId's 
  19986.            are used to represent method names, class names, and so forth. 
  19987.  
  19988.  SOMObject One of the three primitive class objects of the SOM run-time 
  19989.            environment. SOMObject is the root class for all SOM (sub)classes. 
  19990.            SOMObject defines the essential behavior common to all SOM objects. 
  19991.  
  19992.  SOMOA (SOM object adapter) class In DSOM, a class that dispatches methods on a 
  19993.            server's objects, using the SOM Compiler and run-time support. The 
  19994.            SOMOA class implements methods defined in the abstract BOA class 
  19995.            (its base class). See also BOA class. 
  19996.  
  19997.  somSelf   Within method procedures  in the implementation file for a class, a 
  19998.            parameter pointing to the target object that is an instance of the 
  19999.            class being implemented.  it is local to the method procedure. 
  20000.  
  20001.  somThis   Within method procedures, a local variable that points to a data 
  20002.            structure containing the instance variables introduced by the class. 
  20003.            If no instance variables are specified in the SOM IDL source file, 
  20004.            then the somThis assignment statement is commented out by the SOM 
  20005.            Compiler. 
  20006.  
  20007.  state (of an object) The data (attributes, instance variables and their 
  20008.            values) associated with an object. See also behavior. 
  20009.  
  20010.  static method Any method that can be accessed through offset method 
  20011.            resolution.  Any method declared in the IDL specification of a class 
  20012.            is a static method. See also method and dynamic method. 
  20013.  
  20014.  stub procedures Method procedures in the implementation template generated by 
  20015.            the SOM Compiler. They are procedures whose bodies are largely 
  20016.            vacuous, to be filled in by the implementor. 
  20017.  
  20018.  subclass  A class that inherits instance methods, attributes, and instance 
  20019.            variables directly from another class, called the parent class, base 
  20020.            class, superclass, or indirectly from an ancestor class. A subclass 
  20021.            may also be called a child class or derived class. 
  20022.  
  20023.  subclassing The process whereby a new class, as it is created (or derived), 
  20024.            inherits instance methods, attributes, and instance variables from 
  20025.            one or more previously defined ancestor classes. The immediate 
  20026.            parent class(es) of a new class must be specified in the class's 
  20027.            interface declaration. see also inheritance. 
  20028.  
  20029.  superclass See parent class. 
  20030.  
  20031.  symbol    In the Emitter Framework, any of a (standard or user-defined) set of 
  20032.            names (such as, className) that are used as placeholders when 
  20033.            building a text template to pattern the desired emitter output. When 
  20034.            a template is emitted, the symbols are replaced with their 
  20035.            corresponding values from the emitter's symbol table. Other symbols 
  20036.            (such as, classSN) have values that are used by section-emitting 
  20037.            methods to identify major sections of the template (which are 
  20038.            correspondingly labeled as "classS" or by a user-defined name). 
  20039.  
  20040.  target object (Or receiver.) The object responding to a method call. The 
  20041.            target object is always the first formal parameter of a method 
  20042.            procedure. For SOM's C-language bindings, the target object is the 
  20043.            first argument provided to the method invocation macro, _methodName. 
  20044.  
  20045.  usage bindings The language-specific binding files for a class that are 
  20046.            generated by the SOM Compiler for inclusion in client programs using 
  20047.            the class. 
  20048.  
  20049.  value logging In the Replication Framework, a technique for maintaining 
  20050.            consistency among replicas of a replicated object, whereby the new 
  20051.            value of the object is distributed after the execution of a method 
  20052.            that updates the object. 
  20053.  
  20054.  view-data paradigm A Replication Framework construct similar to the 
  20055.            Model-View-Controller paradigm in SmallTalk. The "view" object 
  20056.            contains only presentation-specific information, while the "data" 
  20057.            object contains the state of the application. The "view" and "data" 
  20058.            are connected by means of an "observation" protocol that lets the 
  20059.            "view" be notified whenever the "data" changes. 
  20060.  
  20061.  writers   See readers and writers. 
  20062.  
  20063.  
  20064. ΓòÉΓòÉΓòÉ <hidden>  ΓòÉΓòÉΓòÉ
  20065.  
  20066. **'. C++ is a trademark of AT&T, Inc.