Using C++ with Caché
Generating Proxy Classes
[Back] [Next]
Go to:

Proxy classes are generated by the Caché C++ Class Generator (see Using the C++ Generator), which reads the definition of a Caché class and uses the information to generate a corresponding C++ class. The generated class provides remote access to an instance of a Caché object from within a C++ application.

The C++ Generator produces C++ proxy classes that have the same inheritance hierarchy as the corresponding Caché classes. The type of a class (such as persistent or serial) determines its corresponding C++ superclass. For example, persistent classes have corresponding C++ classes derived from the C++ Persistent_t class included in the Caché C++ library. In case of multiple inheritance, a class becomes a subclass of the first superclass in Caché, and all methods and properties from other direct superclasses are generated as members of the proxy class.
The Caché C++ class library includes C++ versions of a number of the classes within the Caché class library, including %Persistent, %RegisteredObject, %SerialObject, the various Caché collection classes, and C++ versions of the various data type classes. In addition, the library contains the various classes used within a C++ application to manage the communication with the Caché server.
The C++ binding doesn't check at runtime to see whether metadata has changed since code was generated. In particular, it doesn't check whether the application is connecting to the same namespace as at code generation time, and doesn't check whether the classes are defined in the runtime namespace. If they aren't, it will go ahead and insert data anyway, but this data won't be accessible via SQL or via the object interface.
Standard Proxy Class Methods
In addition to any methods defined by a Caché class, all C++ proxy classes inherit a set of methods from the standard Caché C++ library classes Persistent_t (for persistent classes) or Registered_t (for serial classes).
The C++ Generator also adds a set of static create and open methods to the generated classes. To protect the C++ classes from incorrect usage, the proxy class constructors are made private. The only way to instantiate a generated class T is to call one of the static methods T::create_new(), T::open(), or T::openid(), each of which returns a d_ref<T> object (see Using Proxy Objects). These methods are generated only if the corresponding Caché methods exist for a given class.
The static methods are defined as follows (where My_Class is the name of the proxy class):
Implementing Proxy Methods
C++ instance methods are generated for Caché instance methods and C++ static methods are generated for Caché class methods. When called on the client, a C++ method invokes the actual method implementation on the Caché server. If a method signature includes arguments with default values, Caché uses the same default values within the generated C++ method. For example, suppose you define a simple Caché class with one method:
   Class MyApp.Simple Extends %RegisteredObject {
      Method LookupName(id As %String) As %String {
         // lookup a name using embedded SQL
         Set name = ""
         &sql(SELECT Name INTO :name FROM Person WHERE ID = :id)
         Quit name
The resulting C++ class header would look similar to the following:
   class MyApp_Simple : public Persistent_t {
      friend d_ref<MyApp_Simple>;
      // code
      virtual d_string LookupName(d_string id);
When a method is invoked from C++, the C++ client first synchronizes the server object cache, then invokes the method on the Caché server, and finally, returns the resulting value (if any). If any method arguments are specified as call-by-reference then their value is updated as well.
Implementing Proxy Properties
Properties in C++ proxy classes are accessed through a pair of accessor methods. Each property has a corresponding get<Property>() method to get its value and a set<Property>() method to set its value.
The values for literal properties (such as strings or integers) are represented using the appropriate C++ data type classes provided with the Caché C++ class library (such as d_string or d_int).
The values for object-valued properties are represented using the d_ref template class (see Using Proxy Objects).
For example, suppose you have defined a persistent class within Caché containing two properties, one literal and the other object-valued:
   Class MyApp.Student Extends %Persistent {
      // Student's name
      Property Name As %String;
      // Reference to a school object
      Property School As School;
The C++ representation of MyApp.Student contains get and set accessor methods for both the Name and School properties. In addition, it provides accessors for the object Id for the referenced School object.
For example, in the Caché sample class, Sample.Person, the DOB property is defined as follows:
   Property DOB As %Date(POPSPEC = "Date()");
The POPSPEC content is for populating the class with sample data and would not appear in an actual application. The C++ accessor methods for Sample.Person are:
   virtual d_date getDOB() const;
   virtual void setDOB(const d_date&);
When a C++ object is instantiated within C++, it fetches a copy of its property values from the Caché server and copies them into a local client-side cache. Subsequent access to the object's property values are made against this cache, reducing the number of messages sent to and from the server. Caché automatically manages this local cache and ensures that it is synchronized with the corresponding object state on the Caché server.
Property values for which you have defined a Get or Set method within your Caché class definition (to create a property whose value depends on other properties for example) are not stored within the local cache. Instead when you access such properties the corresponding accessor method is invoked on the Caché server. As this can entail higher network traffic, you should exercise care when using such properties within a client/server environment.
Naming Conventions
A generated C++ identifier, such as the name of a class, method, or variable, is usually the same as that of the corresponding Caché identifier. This section describes the exceptions to that rule.
It is important to remember that, unlike Caché ObjectScript, C++ identifiers must contain only characters A-Z, a-z, 1–9, and "_" (underscore). If a Caché identifier contains characters that are not permitted in C++, those characters will be replaced by underscores. If the Caché identifier consists of high-order Unicode characters, this may result in a C++ identifier that contains nothing but underscores. Alternate class and package names can be defined in Caché, as described below.
For details on Caché Basic and ObjectScript naming conventions, see Variables in Using Caché ObjectScript, Naming Conventions in Using Caché Objects, Identifiers and Variables in Using Caché Basic, and Rules and Guidelines for Identifiers in the Caché Programming Orientation Guide.
Using the C++ Generator
The Caché C++ Generator is a program that generates a C++ class and header file from a Caché class definition. It is available either as a command line program, or as an option in Caché Studio. If Caché is installed with level 3 ("locked down") security, %Service_Bindings must be enabled in order to run the Generator.
To access the Generator from Studio, select Tools > Generate C++ projection from the main menu. This option does not allow you to generate projections for the Light C++ Binding, which must use the command line program with the -lc parameter.
The command line program, cpp_generator.exe, is installed in the <cachesys>\dev\cpp\lib directory, which must be in your Path. (See Default Caché Installation Directory in the Caché Installation Guide for the location of <cachesys> on your system).
The syntax for the program is:
   -conn <conn>
   -user <user>
   -pswd <password>
   -path <path>
   [-class <class>] | [-class-list <filename>]
For example:
   -conn "localhost[1972]:SAMPLES"
   -user "MyUserName"
   -pswd "MyPassword"
   -path "./cppfiles"
   -class "Sample.Person"
C++ Generator Parameters
A connection string with the format <host>[<port>]:<namespace>.
For example:
   -conn "localhost[1972]:SAMPLES"
A string specifying the username.
A string specifying the password.
Either a classname or the name of a file containing a list of classnames.
The -class <class> option specifies a Caché server classname. For example:
The -class-list <filename> option specifies the name of a file containing Caché server class name strings (and nothing else), one per line. For example:
where classlist.txt contains the following lines:
A string specifying the directory in which the generated C++ class is to be placed.
-lc Optional. If the -lc switch is used, the generator will produce Light C++ Binding classes.
-help Optional. Displays the list of C++ Generator parameters.
The C++ Generator will automatically generate code for any other classes required to implement the specified class. For example, if you specify -class "Sample.Employee", code will also be generated for the Sample.Person and Sample.Address classes, because Sample.Employee is derived from Sample.Person, and Sample.Person has properties of type Sample.Address.